Skip to content

WIP: implement Weex native directive compiler for <recycle-list> #6622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
6 changes: 3 additions & 3 deletions flow/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ declare type ASTNode = ASTElement | ASTText | ASTExpression;
declare type ASTElement = {
type: 1;
tag: string;
attrsList: Array<{ name: string; value: string }>;
attrsMap: { [key: string]: string | null };
attrsList: Array<{ name: string; value: any }>;
attrsMap: { [key: string]: any };
parent: ASTElement | void;
children: Array<ASTNode>;

Expand All @@ -84,7 +84,7 @@ declare type ASTElement = {
hasBindings?: boolean;

text?: string;
attrs?: Array<{ name: string; value: string }>;
attrs?: Array<{ name: string; value: any }>;
props?: Array<{ name: string; value: string }>;
plain?: boolean;
pre?: true;
Expand Down
11 changes: 9 additions & 2 deletions src/compiler/codegen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,15 +475,22 @@ function genComponent (
})`
}

function genProps (props: Array<{ name: string, value: string }>): string {
function genProps (props: Array<{ name: string, value: any }>): string {
let res = ''
for (let i = 0; i < props.length; i++) {
const prop = props[i]
res += `"${prop.name}":${transformSpecialNewlines(prop.value)},`
res += `"${prop.name}":${generateValue(prop.value)},`
}
return res.slice(0, -1)
}

function generateValue (value) {
if (typeof value === 'string') {
return transformSpecialNewlines(value)
}
return JSON.stringify(value)
}

// #3895, #4268
function transformSpecialNewlines (text: string): string {
return text
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function addProp (el: ASTElement, name: string, value: string) {
(el.props || (el.props = [])).push({ name, value })
}

export function addAttr (el: ASTElement, name: string, value: string) {
export function addAttr (el: ASTElement, name: string, value: any) {
(el.attrs || (el.attrs = [])).push({ name, value })
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const forAliasRE = /(.*?)\s+(?:in|of)\s+(.*)/
export const forIteratorRE = /\((\{[^}]*\}|[^,]*),([^,]*)(?:,([^,]*))?\)/

const argRE = /:(.*)$/
const bindRE = /^:|^v-bind:/
export const bindRE = /^:|^v-bind:/
const modifierRE = /\.[^.]+/g

const decodeHTMLCached = cached(he.decode)
Expand Down
16 changes: 11 additions & 5 deletions src/core/vdom/helpers/update-listeners.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
/* @flow */

import { warn } from 'core/util/index'
import { cached, isUndef } from 'shared/util'
import { cached, isUndef, isPlainObject } from 'shared/util'

const normalizeEvent = cached((name: string): {
name: string,
once: boolean,
capture: boolean,
passive: boolean
passive: boolean,
handler?: Function,
params?: Array<any>
} => {
const passive = name.charAt(0) === '&'
name = passive ? name.slice(1) : name
Expand Down Expand Up @@ -47,11 +49,15 @@ export function updateListeners (
remove: Function,
vm: Component
) {
let name, cur, old, event
let name, def, cur, old, event
for (name in on) {
cur = on[name]
def = cur = on[name]
old = oldOn[name]
event = normalizeEvent(name)
if (isPlainObject(def)) {
cur = def.handler
event.params = def.params
}
if (isUndef(cur)) {
process.env.NODE_ENV !== 'production' && warn(
`Invalid handler for event "${event.name}": got ` + String(cur),
Expand All @@ -61,7 +67,7 @@ export function updateListeners (
if (isUndef(cur.fns)) {
cur = on[name] = createFnInvoker(cur)
}
add(event.name, cur, event.once, event.capture, event.passive)
add(event.name, cur, event.once, event.capture, event.passive, event.params)
} else if (cur !== old) {
old.fns = cur
on[name] = old
Expand Down
11 changes: 10 additions & 1 deletion src/platforms/weex/compiler/modules/recycle-list/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/* @flow */

import { transformText } from './text'
import { transformVBind } from './v-bind'
import { transformVIf } from './v-if'
import { transformVFor } from './v-for'

let currentRecycleList = null

function preTransformNode (el: ASTElement) {
function preTransformNode (el: ASTElement, options: CompilerOptions) {
if (el.tag === 'recycle-list') {
currentRecycleList = el
}
if (currentRecycleList) {
// TODO
transformVBind(el)
transformVIf(el, options) // and v-else-if and v-else
transformVFor(el, options)
}
}

function transformNode (el: ASTElement) {
Expand Down
8 changes: 5 additions & 3 deletions src/platforms/weex/compiler/modules/recycle-list/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ function genText (node: ASTNode) {
export function transformText (el: ASTElement) {
// weex <text> can only contain text, so the parser
// always generates a single child.
addAttr(el, 'value', genText(el.children[0]))
el.children = []
el.plain = false
if (el.children.length) {
addAttr(el, 'value', genText(el.children[0]))
el.children = []
el.plain = false
}
}
25 changes: 25 additions & 0 deletions src/platforms/weex/compiler/modules/recycle-list/v-bind.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* @flow */

import { camelize } from 'shared/util'
import { bindRE } from 'compiler/parser/index'
import { getAndRemoveAttr } from 'compiler/helpers'

function parseAttrName (name: string): string {
return camelize(name.replace(bindRE, ''))
}

export function transformVBind (el: ASTElement) {
for (const attr in el.attrsMap) {
if (bindRE.test(attr)) {
const name: string = parseAttrName(attr)
const value = {
'@binding': getAndRemoveAttr(el, attr)
}
delete el.attrsMap[attr]
el.attrsMap[name] = value
el.attrsList.push({ name, value })
// addAttr(el, name, value)
// el.hasBindings = false
}
}
}
33 changes: 33 additions & 0 deletions src/platforms/weex/compiler/modules/recycle-list/v-for.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* @flow */

import { forAliasRE, forIteratorRE } from 'compiler/parser/index'
import { getAndRemoveAttr } from 'compiler/helpers'

export function transformVFor (el: ASTElement, options: CompilerOptions) {
const exp = getAndRemoveAttr(el, 'v-for')
if (!exp) {
return
}
const inMatch = exp.match(forAliasRE)
if (inMatch) {
const alias = inMatch[1].trim()
const desc: Object = {
'@expression': inMatch[2].trim(),
'@alias': alias
}
const iteratorMatch = alias.match(forIteratorRE)
if (iteratorMatch) {
desc['@alias'] = iteratorMatch[1].trim()
desc['@index'] = iteratorMatch[2].trim()
if (iteratorMatch[3]) {
desc['@key'] = iteratorMatch[2].trim()
desc['@index'] = iteratorMatch[3].trim()
}
}
delete el.attrsMap['v-for']
el.attrsMap['[[repeat]]'] = desc
el.attrsList.push({ name: '[[repeat]]', value: desc })
} else if (process.env.NODE_ENV !== 'production' && options.warn) {
options.warn(`Invalid v-for expression: ${exp}`)
}
}
48 changes: 48 additions & 0 deletions src/platforms/weex/compiler/modules/recycle-list/v-if.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* @flow */

import { getAndRemoveAttr } from 'compiler/helpers'

function hasConditionDirective (el: ASTElement): boolean {
for (const attr in el.attrsMap) {
if (/^v\-if|v\-else|v\-else\-if$/.test(attr)) {
return true
}
}
return false
}

function getPrevMatch (el: ASTElement): any {
if (el.parent && el.parent.children) {
const prev: Object = el.parent.children[el.parent.children.length - 1]
return prev.attrsMap['[[match]]']
}
}

export function transformVIf (el: ASTElement, options: CompilerOptions) {
if (hasConditionDirective(el)) {
let exp
const ifExp = getAndRemoveAttr(el, 'v-if')
const elseifExp = getAndRemoveAttr(el, 'v-else-if')
if (ifExp) {
exp = ifExp
} else {
const prevMatch = getPrevMatch(el)
if (prevMatch) {
exp = elseifExp
? `!(${prevMatch}) && (${elseifExp})` // v-else-if
: `!(${prevMatch})` // v-else
} else if (process.env.NODE_ENV !== 'production' && options.warn) {
options.warn(
`v-${elseifExp ? ('else-if="' + elseifExp + '"') : 'else'} ` +
`used on element <${el.tag}> without corresponding v-if.`
)
return
}
}
el.attrsMap['[[match]]'] = exp
el.attrsList.push({ name: '[[match]]', value: exp })
delete el.attrsMap['v-if']
delete el.attrsMap['v-else-if']
delete el.attrsMap['v-else']
}
}
4 changes: 2 additions & 2 deletions src/platforms/weex/entry-framework.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ const jsHandlers = {
}
}

function fireEvent (instance, nodeId, type, e, domChanges) {
function fireEvent (instance, nodeId, type, e, domChanges, params) {
const el = instance.document.getRef(nodeId)
if (el) {
return instance.document.fireEvent(el, type, e, domChanges)
return instance.document.fireEvent(el, type, e, domChanges, params)
}
return new Error(`invalid element reference "${nodeId}"`)
}
Expand Down
6 changes: 4 additions & 2 deletions src/platforms/weex/runtime/modules/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ function add (
event: string,
handler: Function,
once: boolean,
capture: boolean
capture: boolean,
passive?: boolean,
params?: Array<any>
) {
if (capture) {
console.log('Weex do not support event in bubble phase.')
Expand All @@ -26,7 +28,7 @@ function add (
}
}
}
target.addEvent(event, handler)
target.addEvent(event, handler, params)
}

function remove (
Expand Down