Browse Source

improve text&attr compile

Evan You 11 years ago
parent
commit
d82785e306
1 changed files with 213 additions and 222 deletions
  1. 213 222
      src/compile/compile.js

+ 213 - 222
src/compile/compile.js

@@ -59,33 +59,6 @@ function compileNode (node, options) {
   }
   }
 }
 }
 
 
-/**
- * Compile a node list and return a childLinkFn.
- *
- * @param {NodeList} nodeList
- * @param {Object} options
- * @return {Function|undefined}
- */
-
-function compileNodeList (nodeList, options) {
-  var linkFns = []
-  var nodeLinkFn, childLinkFn
-  for (var i = 0, l = nodeList.length; i < l; i++) {
-    // always refer to nodeList[i] because it might be
-    // replaced during tranclusion
-    nodeLinkFn = compileNode(nodeList[i], options)
-    childLinkFn =
-      (!nodeLinkFn || !nodeLinkFn.terminal) &&
-      nodeList[i].hasChildNodes()
-        ? compileNodeList(nodeList[i].childNodes, options)
-        : null
-    linkFns.push(nodeLinkFn, childLinkFn)
-  }
-  return linkFns.length
-    ? makeChildLinkFn(linkFns)
-    : null
-}
-
 /**
 /**
  * Compile an element and return a nodeLinkFn.
  * Compile an element and return a nodeLinkFn.
  *
  *
@@ -124,6 +97,32 @@ function compileElement (el, options) {
   }
   }
 }
 }
 
 
+/**
+ * Build a multi-directive link function.
+ *
+ * @param {Array} directives
+ * @return {Function} directivesLinkFn
+ */
+
+function makeDirectivesLinkFn (directives) {
+  return function directivesLinkFn (vm, el) {
+    // reverse apply because it's sorted low to high
+    var i = directives.length
+    var vmDirs = vm._directives
+    var dir, j
+    while (i--) {
+      dir = directives[i]
+      j = dir.descriptors.length
+      while (j--) {
+        vmDirs.push(
+          new Direcitve(dir.name, el, vm,
+                        dir.descriptors[j], dir.def)
+        )
+      }
+    }
+  }
+}
+
 /**
 /**
  * Compile a textNode and return a nodeLinkFn.
  * Compile a textNode and return a nodeLinkFn.
  *
  *
@@ -138,6 +137,7 @@ function compileTextNode (node, options) {
     return null
     return null
   }
   }
   var frag = document.createDocumentFragment()
   var frag = document.createDocumentFragment()
+  var dirs = options.directives
   var el, token, value
   var el, token, value
   for (var i = 0, l = tokens.length; i < l; i++) {
   for (var i = 0, l = tokens.length; i < l; i++) {
     token = tokens[i]
     token = tokens[i]
@@ -148,15 +148,18 @@ function compileTextNode (node, options) {
       } else {
       } else {
         if (token.html) {
         if (token.html) {
           el = document.createComment('v-html')
           el = document.createComment('v-html')
-          token.def = options.directives.html
+          token.type = 'html'
+          token.def = dirs.html
           token.descriptor = dirParser.parse(value)[0]
           token.descriptor = dirParser.parse(value)[0]
         } else if (token.partial) {
         } else if (token.partial) {
           el = document.createComment('v-partial')
           el = document.createComment('v-partial')
-          token.def = options.directives.partial
+          token.type = 'partial'
+          token.def = dirs.partial
           token.descriptor = dirParser.parse(value)[0]
           token.descriptor = dirParser.parse(value)[0]
         } else {
         } else {
           el = document.createTextNode('')
           el = document.createTextNode('')
-          token.def = options.directives.text
+          token.type = 'text'
+          token.def = dirs.text
           token.descriptor = dirParser.parse(value)[0]
           token.descriptor = dirParser.parse(value)[0]
         }
         }
       }
       }
@@ -168,6 +171,96 @@ function compileTextNode (node, options) {
   return makeTextNodeLinkFn(tokens, frag, options)
   return makeTextNodeLinkFn(tokens, frag, options)
 }
 }
 
 
+/**
+ * Build a function that processes a textNode.
+ *
+ * @param {Array<Object>} tokens
+ * @param {DocumentFragment} frag
+ */
+
+function makeTextNodeLinkFn (tokens, frag) {
+  return function textNodeLinkFn (vm, el) {
+    var fragClone = frag.cloneNode(true)
+    var childNodes = _.toArray(fragClone.childNodes)
+    var dirs = vm._directives
+    var token, value, node, type
+    for (var i = 0, l = tokens.length; i < l; i++) {
+      token = tokens[i]
+      value = token.value
+      if (token.tag) {
+        node = childNodes[i]
+        if (token.oneTime) {
+          value = vm.$get(value)
+          if (token.html) {
+            _.replace(node, templateParser.parse(value, true))
+          } else {
+            node.nodeValue = value
+          }
+        } else {
+          dirs.push(
+            new Direcitve(token.type, node, vm,
+                          token.descriptor, token.def)
+          )
+        }
+      }
+    }
+    _.replace(el, fragClone)
+  }
+}
+
+/**
+ * Compile a node list and return a childLinkFn.
+ *
+ * @param {NodeList} nodeList
+ * @param {Object} options
+ * @return {Function|undefined}
+ */
+
+function compileNodeList (nodeList, options) {
+  var linkFns = []
+  var nodeLinkFn, childLinkFn
+  for (var i = 0, l = nodeList.length; i < l; i++) {
+    // always refer to nodeList[i] because it might be
+    // replaced during tranclusion
+    nodeLinkFn = compileNode(nodeList[i], options)
+    childLinkFn =
+      (!nodeLinkFn || !nodeLinkFn.terminal) &&
+      nodeList[i].hasChildNodes()
+        ? compileNodeList(nodeList[i].childNodes, options)
+        : null
+    linkFns.push(nodeLinkFn, childLinkFn)
+  }
+  return linkFns.length
+    ? makeChildLinkFn(linkFns)
+    : null
+}
+
+/**
+ * Make a child link function for a node's childNodes.
+ *
+ * @param {Array<Function>} linkFns
+ * @return {Function} childLinkFn
+ */
+
+function makeChildLinkFn (linkFns) {
+  return function childLinkFn (vm, nodes) {
+    // stablize nodes
+    nodes = _.toArray(nodes)
+    var node, nodeLinkFn, childrenLinkFn
+    for (var i = 0, n = 0, l = linkFns.length; i < l; n++) {
+      node = nodes[n]
+      nodeLinkFn = linkFns[i++]
+      childrenLinkFn = linkFns[i++]
+      if (nodeLinkFn) {
+        nodeLinkFn(vm, node)
+      }
+      if (childrenLinkFn) {
+        childrenLinkFn(vm, node.childNodes)
+      }
+    }
+  }
+}
+
 /**
 /**
  * Compile param attributes on a root element and return
  * Compile param attributes on a root element and return
  * a paramAttributes link function.
  * a paramAttributes link function.
@@ -211,6 +304,40 @@ function compileParamAttributes (el, attrs, options) {
   return makeParamsLinkFn(params, options)
   return makeParamsLinkFn(params, options)
 }
 }
 
 
+/**
+ * Build a function that applies param attributes to a vm.
+ *
+ * @param {Array} params
+ * @param {Object} options
+ * @return {Function} paramsLinkFn
+ */
+
+function makeParamsLinkFn (params, options) {
+  var def = options.directives.with
+  return function paramsLinkFn (vm, el) {
+    var i = params.length
+    var param
+    while (i--) {
+      param = params[i]
+      if (param.dynamic) {
+        // dynamic param attribtues are bound as v-with.
+        // we can directly fake the descriptor here beacuse
+        // param attributes cannot use expressions or
+        // filters.
+        vm._directives.push(
+          new Direcitve('with', el, vm, {
+            arg: param.name,
+            expression: param.value
+          }, def)
+        )
+      } else {
+        // just set once
+        vm.$set(param.name, param.value)
+      }
+    }
+  }
+}
+
 /**
 /**
  * Check an element for terminal directives in fixed order.
  * Check an element for terminal directives in fixed order.
  * If it finds one, return a terminal link function.
  * If it finds one, return a terminal link function.
@@ -240,6 +367,52 @@ function checkTerminalDirectives (el, options) {
   }
   }
 }
 }
 
 
+/**
+ * Build a link function for a terminal directive.
+ *
+ * @param {Element} el
+ * @param {String} dirName
+ * @param {String} value
+ * @param {Object} options
+ * @return {Function} terminalLinkFn
+ */
+
+function makeTeriminalLinkFn (el, dirName, value, options) {
+  var descriptor = dirParser.parse(value)[0]
+  var def = options.directives[dirName]
+  // we can transclude and compile the child block here
+  // only when there's no dynamic component involved.
+  var dynamicComponent = false
+  var componentId, subOptions
+  if (dirName === 'repeat') {
+    componentId = el.getAttribute(config.prefix + 'component')
+  } else if (dirName === 'component') {
+    componentId = value
+  }
+  if (componentId) {
+    if (textParser.parse(componentId)) {
+      dynamicComponent = true
+    } else {
+      var Ctor = options.components[componentId]
+      _.assertAsset(Ctor, 'component', componentId)
+      if (Ctor) {
+        subOptions = Ctor.options
+      }
+    }
+  }
+  if (!dynamicComponent) {
+    subOptions = subOptions
+      ? mergeOptions(options, subOptions)
+      : _.Vue.options
+    descriptor.linkFn = compile(el, subOptions)
+  }
+  return function terminalLinkFn (vm, el) {
+    vm._directives.push(
+      new Direcitve(dirName, el, vm, descriptor, def)
+    )
+  }
+}
+
 /**
 /**
  * Collect the directives on an element.
  * Collect the directives on an element.
  *
  *
@@ -283,19 +456,6 @@ function collectDirectives (el, options) {
   return dirs
   return dirs
 }
 }
 
 
-/**
- * Directive priority sort comparator
- *
- * @param {Object} a
- * @param {Object} b
- */
-
-function directiveComparator (a, b) {
-  a = a.def.priority || 0
-  b = b.def.priority || 0
-  return a > b ? 1 : -1
-}
-
 /**
 /**
  * Check an attribute for potential dynamic bindings,
  * Check an attribute for potential dynamic bindings,
  * and return a directive object.
  * and return a directive object.
@@ -318,195 +478,26 @@ function collectAttrDirective (el, name, value, options) {
         'in attribute bindings.'
         'in attribute bindings.'
       )
       )
     } else {
     } else {
-      var descriptor = dirParser.parse(tokens[0].value)
-      descriptor.arg = name
+      var descriptors = dirParser.parse(tokens[0].value)
+      descriptors[0].arg = name
       return {
       return {
         name: 'attr',
         name: 'attr',
         def: options.directives.attr,
         def: options.directives.attr,
-        descriptors: [descriptor]
-      }
-    }
-  }
-}
-
-/**
- * Make a child link function for a node's childNodes.
- *
- * @param {Array<Function>} linkFns
- * @return {Function} childLinkFn
- */
-
-function makeChildLinkFn (linkFns) {
-  return function childLinkFn (vm, nodes) {
-    // stablize nodes
-    nodes = _.toArray(nodes)
-    var node, nodeLinkFn, childrenLinkFn
-    for (var i = 0, n = 0, l = linkFns.length; i < l; n++) {
-      node = nodes[n]
-      nodeLinkFn = linkFns[i++]
-      childrenLinkFn = linkFns[i++]
-      if (nodeLinkFn) {
-        nodeLinkFn(vm, node)
-      }
-      if (childrenLinkFn) {
-        childrenLinkFn(vm, node.childNodes)
+        descriptors: descriptors
       }
       }
     }
     }
   }
   }
 }
 }
 
 
 /**
 /**
- * Build a link function for a terminal directive.
- *
- * @param {Element} el
- * @param {String} dirName
- * @param {String} value
- * @param {Object} options
- * @return {Function} terminalLinkFn
- */
-
-function makeTeriminalLinkFn (el, dirName, value, options) {
-  var descriptor = dirParser.parse(value)[0]
-  var def = options.directives[dirName]
-  // we can transclude and compile the child block here
-  // only when there's no dynamic component involved.
-  var dynamicComponent = false
-  var componentId, subOptions
-  if (dirName === 'repeat') {
-    componentId = el.getAttribute(config.prefix + 'component')
-  } else if (dirName === 'component') {
-    componentId = value
-  }
-  if (componentId) {
-    if (textParser.parse(componentId)) {
-      dynamicComponent = true
-    } else {
-      var Ctor = options.components[componentId]
-      _.assertAsset(Ctor, 'component', componentId)
-      if (Ctor) {
-        subOptions = Ctor.options
-      }
-    }
-  }
-  if (!dynamicComponent) {
-    subOptions = subOptions
-      ? mergeOptions(options, subOptions)
-      : _.Vue.options
-    descriptor.linkFn = compile(el, subOptions)
-  }
-  return function terminalLinkFn (vm, el) {
-    vm._directives.push(
-      new Direcitve(dirName, el, vm, descriptor, def)
-    )
-  }
-}
-
-/**
- * Build a multi-directive link function.
- *
- * @param {Array} directives
- * @return {Function} directivesLinkFn
- */
-
-function makeDirectivesLinkFn (directives) {
-  return function directivesLinkFn (vm, el) {
-    // reverse apply because it's sorted low to high
-    var i = directives.length
-    var vmDirs = vm._directives
-    var dir, j
-    while (i--) {
-      dir = directives[i]
-      j = dir.descriptors.length
-      while (j--) {
-        vmDirs.push(
-          new Direcitve(dir.name, el, vm,
-                        dir.descriptors[j], dir.def)
-        )
-      }
-    }
-  }
-}
-
-/**
- * Build a function that processes a textNode.
- *
- * @param {Array<Object>} tokens
- * @param {DocumentFragment} frag
- */
-
-function makeTextNodeLinkFn (tokens, frag) {
-  return function textNodeLinkFn (vm, el) {
-    var fragClone = frag.cloneNode(true)
-    var childNodes = _.toArray(fragClone.childNodes)
-    var dirs = vm._directives
-    var token, value, node
-    for (var i = 0, l = tokens.length; i < l; i++) {
-      token = tokens[i]
-      value = token.value
-      if (token.tag) {
-        node = childNodes[i]
-        if (token.oneTime) {
-          value = vm.$get(value)
-          if (token.html) {
-            var htmlFrag = templateParser.parse(value, true)
-            _.replace(node, htmlFrag)
-          } else {
-            node.nodeValue = value
-          }
-        } else {
-          if (token.html) {
-            dirs.push(
-              new Direcitve('html', node, vm,
-                            token.descriptor, token.def)
-            )
-          } else if (token.partial) {
-            dirs.push(
-              new Direcitve('partial', node, vm,
-                            token.descriptor, token.def)
-            )
-          } else {
-            dirs.push(
-              new Direcitve('text', node, vm,
-                            token.descriptor, token.def)
-            )
-          }
-        }
-      }
-    }
-    _.replace(el, fragClone)
-  }
-}
-
-/**
- * Build a function that applies param attributes to a vm.
+ * Directive priority sort comparator
  *
  *
- * @param {Array} params
- * @param {Object} options
- * @return {Function} paramsLinkFn
+ * @param {Object} a
+ * @param {Object} b
  */
  */
 
 
-function makeParamsLinkFn (params, options) {
-  var def = options.directives.with
-  return function paramsLinkFn (vm, el) {
-    var i = params.length
-    var param
-    while (i--) {
-      param = params[i]
-      if (param.dynamic) {
-        // dynamic param attribtues are bound as v-with.
-        // we can directly fake the descriptor here beacuse
-        // param attributes cannot use expressions or
-        // filters.
-        vm._directives.push(
-          new Direcitve('with', el, vm, {
-            arg: param.name,
-            expression: param.value
-          }, def)
-        )
-      } else {
-        // just set once
-        vm.$set(param.name, param.value)
-      }
-    }
-  }
+function directiveComparator (a, b) {
+  a = a.def.priority || 0
+  b = b.def.priority || 0
+  return a > b ? 1 : -1
 }
 }