Browse Source

feat(weex): recycle-list support WIP

Evan You 8 năm trước cách đây
mục cha
commit
5254ee31c4

+ 1 - 0
flow/compiler.js

@@ -155,6 +155,7 @@ declare type ASTExpression = {
   type: 2;
   type: 2;
   expression: string;
   expression: string;
   text: string;
   text: string;
+  tokens: Array<string | Object>;
   static?: boolean;
   static?: boolean;
   // 2.4 ssr optimization
   // 2.4 ssr optimization
   ssrOptimizability?: number;
   ssrOptimizability?: number;

+ 13 - 13
src/compiler/parser/index.js

@@ -98,7 +98,7 @@ export function parse (
     }
     }
   }
   }
 
 
-  function endPre (element) {
+  function closeElement (element) {
     // check pre state
     // check pre state
     if (element.pre) {
     if (element.pre) {
       inVPre = false
       inVPre = false
@@ -106,6 +106,10 @@ export function parse (
     if (platformIsPreTag(element.tag)) {
     if (platformIsPreTag(element.tag)) {
       inPre = false
       inPre = false
     }
     }
+    // apply post-transforms
+    for (let i = 0; i < postTransforms.length; i++) {
+      postTransforms[i](element, options)
+    }
   }
   }
 
 
   parseHTML(template, {
   parseHTML(template, {
@@ -219,7 +223,7 @@ export function parse (
         currentParent = element
         currentParent = element
         stack.push(element)
         stack.push(element)
       } else {
       } else {
-        endPre(element)
+        closeElement(element)
       }
       }
     },
     },
 
 
@@ -233,12 +237,7 @@ export function parse (
       // pop stack
       // pop stack
       stack.length -= 1
       stack.length -= 1
       currentParent = stack[stack.length - 1]
       currentParent = stack[stack.length - 1]
-      endPre(element)
-
-      // apply post-transforms
-      for (let i = 0; i < postTransforms.length; i++) {
-        postTransforms[i](element, options)
-      }
+      closeElement(element)
     },
     },
 
 
     chars (text: string) {
     chars (text: string) {
@@ -270,11 +269,12 @@ export function parse (
         // only preserve whitespace if its not right after a starting tag
         // only preserve whitespace if its not right after a starting tag
         : preserveWhitespace && children.length ? ' ' : ''
         : preserveWhitespace && children.length ? ' ' : ''
       if (text) {
       if (text) {
-        let expression
-        if (!inVPre && text !== ' ' && (expression = parseText(text, delimiters))) {
+        let res
+        if (!inVPre && text !== ' ' && (res = parseText(text, delimiters))) {
           children.push({
           children.push({
             type: 2,
             type: 2,
-            expression,
+            expression: res.expression,
+            tokens: res.tokens,
             text
             text
           })
           })
         } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {
         } else if (text !== ' ' || !children.length || children[children.length - 1].text !== ' ') {
@@ -571,8 +571,8 @@ function processAttrs (el) {
     } else {
     } else {
       // literal attribute
       // literal attribute
       if (process.env.NODE_ENV !== 'production') {
       if (process.env.NODE_ENV !== 'production') {
-        const expression = parseText(value, delimiters)
-        if (expression) {
+        const res = parseText(value, delimiters)
+        if (res) {
           warn(
           warn(
             `${name}="${value}": ` +
             `${name}="${value}": ` +
             'Interpolation inside attributes has been removed. ' +
             'Interpolation inside attributes has been removed. ' +

+ 17 - 5
src/compiler/parser/text-parser.js

@@ -12,30 +12,42 @@ const buildRegex = cached(delimiters => {
   return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
   return new RegExp(open + '((?:.|\\n)+?)' + close, 'g')
 })
 })
 
 
+type TextParseResult = {
+  expression: string,
+  tokens: Array<string | { '@binding': string }>
+}
+
 export function parseText (
 export function parseText (
   text: string,
   text: string,
   delimiters?: [string, string]
   delimiters?: [string, string]
-): string | void {
+): TextParseResult | void {
   const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
   const tagRE = delimiters ? buildRegex(delimiters) : defaultTagRE
   if (!tagRE.test(text)) {
   if (!tagRE.test(text)) {
     return
     return
   }
   }
   const tokens = []
   const tokens = []
+  const rawTokens = []
   let lastIndex = tagRE.lastIndex = 0
   let lastIndex = tagRE.lastIndex = 0
-  let match, index
+  let match, index, tokenValue
   while ((match = tagRE.exec(text))) {
   while ((match = tagRE.exec(text))) {
     index = match.index
     index = match.index
     // push text token
     // push text token
     if (index > lastIndex) {
     if (index > lastIndex) {
-      tokens.push(JSON.stringify(text.slice(lastIndex, index)))
+      rawTokens.push(tokenValue = text.slice(lastIndex, index))
+      tokens.push(JSON.stringify(tokenValue))
     }
     }
     // tag token
     // tag token
     const exp = parseFilters(match[1].trim())
     const exp = parseFilters(match[1].trim())
     tokens.push(`_s(${exp})`)
     tokens.push(`_s(${exp})`)
+    rawTokens.push({ '@binding': exp })
     lastIndex = index + match[0].length
     lastIndex = index + match[0].length
   }
   }
   if (lastIndex < text.length) {
   if (lastIndex < text.length) {
-    tokens.push(JSON.stringify(text.slice(lastIndex)))
+    rawTokens.push(tokenValue = text.slice(lastIndex))
+    tokens.push(JSON.stringify(tokenValue))
+  }
+  return {
+    expression: tokens.join('+'),
+    tokens: rawTokens
   }
   }
-  return tokens.join('+')
 }
 }

+ 2 - 2
src/platforms/web/compiler/modules/class.js

@@ -11,8 +11,8 @@ function transformNode (el: ASTElement, options: CompilerOptions) {
   const warn = options.warn || baseWarn
   const warn = options.warn || baseWarn
   const staticClass = getAndRemoveAttr(el, 'class')
   const staticClass = getAndRemoveAttr(el, 'class')
   if (process.env.NODE_ENV !== 'production' && staticClass) {
   if (process.env.NODE_ENV !== 'production' && staticClass) {
-    const expression = parseText(staticClass, options.delimiters)
-    if (expression) {
+    const res = parseText(staticClass, options.delimiters)
+    if (res) {
       warn(
       warn(
         `class="${staticClass}": ` +
         `class="${staticClass}": ` +
         'Interpolation inside attributes has been removed. ' +
         'Interpolation inside attributes has been removed. ' +

+ 2 - 2
src/platforms/web/compiler/modules/style.js

@@ -14,8 +14,8 @@ function transformNode (el: ASTElement, options: CompilerOptions) {
   if (staticStyle) {
   if (staticStyle) {
     /* istanbul ignore if */
     /* istanbul ignore if */
     if (process.env.NODE_ENV !== 'production') {
     if (process.env.NODE_ENV !== 'production') {
-      const expression = parseText(staticStyle, options.delimiters)
-      if (expression) {
+      const res = parseText(staticStyle, options.delimiters)
+      if (res) {
         warn(
         warn(
           `style="${staticStyle}": ` +
           `style="${staticStyle}": ` +
           'Interpolation inside attributes has been removed. ' +
           'Interpolation inside attributes has been removed. ' +

+ 1 - 1
src/platforms/weex/compiler/modules/class.js

@@ -55,7 +55,7 @@ function parseStaticClass (staticClass: ?string, options: CompilerOptions): Stat
       const result = parseText(name, options.delimiters)
       const result = parseText(name, options.delimiters)
       if (result) {
       if (result) {
         dynamic = true
         dynamic = true
-        return result
+        return result.expression
       }
       }
       return JSON.stringify(name)
       return JSON.stringify(name)
     })
     })

+ 2 - 0
src/platforms/weex/compiler/modules/index.js

@@ -2,8 +2,10 @@ import klass from './class'
 import style from './style'
 import style from './style'
 import props from './props'
 import props from './props'
 import append from './append'
 import append from './append'
+import recycleList from './recycle-list/index'
 
 
 export default [
 export default [
+  recycleList,
   klass,
   klass,
   style,
   style,
   props,
   props,

+ 46 - 0
src/platforms/weex/compiler/modules/recycle-list/index.js

@@ -0,0 +1,46 @@
+/* @flow */
+
+import { addAttr } from 'compiler/helpers'
+
+let currentRecycleList = null
+
+function preTransformNode (el: ASTElement) {
+  if (el.tag === 'recycle-list') {
+    currentRecycleList = el
+  }
+}
+
+function transformNode (el: ASTElement) {
+  if (currentRecycleList) {
+    // TODO
+  }
+}
+
+function postTransformNode (el: ASTElement) {
+  if (currentRecycleList) {
+    // <text>: transform children text into value attr
+    if (el.tag === 'text') {
+      addAttr(el, 'value', genText(el.children[0]))
+      el.children = []
+      el.plain = false
+    }
+  }
+  if (el === currentRecycleList) {
+    currentRecycleList = null
+  }
+}
+
+function genText (node) {
+  const value = node.type === 3
+    ? node.text
+    : node.tokens.length === 1
+      ? node.tokens[0]
+      : node.tokens
+  return JSON.stringify(value)
+}
+
+export default {
+  preTransformNode,
+  transformNode,
+  postTransformNode
+}

+ 1 - 1
src/platforms/weex/compiler/modules/style.js

@@ -64,7 +64,7 @@ function parseStaticStyle (staticStyle: ?string, options: CompilerOptions): Stat
       const dynamicValue = parseText(value, options.delimiters)
       const dynamicValue = parseText(value, options.delimiters)
       if (dynamicValue) {
       if (dynamicValue) {
         dynamic = true
         dynamic = true
-        return key + ':' + dynamicValue
+        return key + ':' + dynamicValue.expression
       }
       }
       return key + ':' + JSON.stringify(value)
       return key + ':' + JSON.stringify(value)
     }).filter(result => result)
     }).filter(result => result)