Evan You 11 лет назад
Родитель
Сommit
12f5e34cbb

+ 6 - 12
src/compile/compile.js

@@ -18,13 +18,10 @@ function noop () {}
  */
  */
 
 
 module.exports = function compile (el, options) {
 module.exports = function compile (el, options) {
-  // for template tags, what we want is its content as
-  // a documentFragment (for block instances)
-  if (el.tagName === 'TEMPLATE') {
-    el = el.content instanceof DocumentFragment
-      ? el.content
-      : templateParser.parse(el.innerHTML)
-  }
+  var params = options.paramAttributes
+  var paramsLinkFn = params
+    ? compileParamAttributes(el, params, options)
+    : null
   var nodeLinkFn = el instanceof DocumentFragment
   var nodeLinkFn = el instanceof DocumentFragment
     ? null
     ? null
     : compileNode(el, options)
     : compileNode(el, options)
@@ -33,10 +30,6 @@ module.exports = function compile (el, options) {
     el.hasChildNodes()
     el.hasChildNodes()
       ? compileNodeList(el.childNodes, options)
       ? compileNodeList(el.childNodes, options)
       : null
       : null
-  var params = options.paramAttributes
-  var paramsLinkFn = params
-    ? compileParamAttributes(el, params, options)
-    : null
   return function link (vm, el) {
   return function link (vm, el) {
     if (paramsLinkFn) paramsLinkFn(vm, el)
     if (paramsLinkFn) paramsLinkFn(vm, el)
     if (nodeLinkFn) nodeLinkFn(vm, el)
     if (nodeLinkFn) nodeLinkFn(vm, el)
@@ -297,6 +290,7 @@ function compileParamAttributes (el, attrs, options) {
             '\nDon\'t mix binding tags with plain text ' +
             '\nDon\'t mix binding tags with plain text ' +
             'in param attribute bindings.'
             'in param attribute bindings.'
           )
           )
+          continue
         } else {
         } else {
           param.dynamic = true
           param.dynamic = true
           param.value = tokens[0].value
           param.value = tokens[0].value
@@ -325,7 +319,7 @@ function makeParamsLinkFn (params, options) {
       param = params[i]
       param = params[i]
       if (param.dynamic) {
       if (param.dynamic) {
         // dynamic param attribtues are bound as v-with.
         // dynamic param attribtues are bound as v-with.
-        // we can directly fake the descriptor here beacuse
+        // we can directly duck the descriptor here beacuse
         // param attributes cannot use expressions or
         // param attributes cannot use expressions or
         // filters.
         // filters.
         vm._bindDir('with', el, {
         vm._bindDir('with', el, {

+ 5 - 0
src/compile/transclude.js

@@ -14,6 +14,11 @@ var templateParser = require('../parse/template')
  */
  */
 
 
 module.exports = function transclude (el, options) {
 module.exports = function transclude (el, options) {
+  // for template tags, what we want is its content as
+  // a documentFragment (for block instances)
+  if (el.tagName === 'TEMPLATE') {
+    el = templateParser.parse(el)
+  }
   if (el instanceof DocumentFragment) {
   if (el instanceof DocumentFragment) {
     return transcludeBlock(el)
     return transcludeBlock(el)
   } else if (options.template) {
   } else if (options.template) {

+ 3 - 1
src/util/merge-option.js

@@ -88,7 +88,9 @@ strats.paramAttributes = function (parentVal, childVal) {
   return childVal
   return childVal
     ? parentVal
     ? parentVal
       ? parentVal.concat(childVal)
       ? parentVal.concat(childVal)
-      : [childVal]
+      : _.isArray(childVal)
+        ? childVal
+        : [childVal]
     : parentVal
     : parentVal
 }
 }
 
 

+ 57 - 10
test/unit/specs/compile/compile_spec.js

@@ -20,12 +20,12 @@ if (_.inBrowser) {
           return data[value]
           return data[value]
         },
         },
         $interpolate: function (value) {
         $interpolate: function (value) {
-          value = value.replace(/\{|\}/g, '')
           return data[value]
           return data[value]
         }
         }
       }
       }
       spyOn(vm, '$eval').and.callThrough()
       spyOn(vm, '$eval').and.callThrough()
       spyOn(vm, '$interpolate').and.callThrough()
       spyOn(vm, '$interpolate').and.callThrough()
+      spyOn(_, 'warn')
     })
     })
 
 
     it('normal directives', function () {
     it('normal directives', function () {
@@ -102,7 +102,9 @@ if (_.inBrowser) {
     })
     })
 
 
     it('terminal directives', function () {
     it('terminal directives', function () {
-      el.innerHTML = '<div v-repeat="items"><p v-a="b"></p></div>'
+      el.innerHTML =
+        '<div v-repeat="items"><p v-a="b"></p></div>' + // v-repeat
+        '<div v-pre><p v-a="b"></p></div>' // v-pre
       var def = Vue.options.directives.repeat
       var def = Vue.options.directives.repeat
       var descriptor = dirParser.parse('items')[0]
       var descriptor = dirParser.parse('items')[0]
       var linker = compile(el, Vue.options)
       var linker = compile(el, Vue.options)
@@ -114,23 +116,68 @@ if (_.inBrowser) {
     })
     })
 
 
     it('custom element components', function () {
     it('custom element components', function () {
-      // body...
+      var options = merge(Vue.options, {
+        components: {
+          'my-component': {}
+        }
+      })
+      el.innerHTML = '<my-component><div v-a="b"></div></my-component>'
+      var def = Vue.options.directives.component
+      var descriptor = dirParser.parse('my-component')[0]
+      var linker = compile(el, options)
+      linker(vm, el)
+      expect(vm._bindDir.calls.count()).toBe(1)
+      expect(vm._bindDir).toHaveBeenCalledWith('component', el.firstChild, descriptor, def)
     })
     })
 
 
     it('attribute interpolation', function () {
     it('attribute interpolation', function () {
-      // body...
+      data['{{*b}}'] = 'B'
+      el.innerHTML = '<div a="{{a}}" b="{{*b}}"></div>'
+      var def = Vue.options.directives.attr
+      var descriptor = dirParser.parse('a:a')[0]
+      var linker = compile(el, Vue.options)
+      linker(vm, el)
+      expect(vm._bindDir.calls.count()).toBe(1)
+      expect(vm._bindDir).toHaveBeenCalledWith('attr', el.firstChild, descriptor, def)
+      expect(el.firstChild.getAttribute('b')).toBe('B')
     })
     })
 
 
     it('param attributes', function () {
     it('param attributes', function () {
-      // body...
+      var options = merge(Vue.options, {
+        paramAttributes: ['a', 'b', 'c']
+      })
+      var def = Vue.options.directives['with']
+      el.setAttribute('a', '1')
+      el.setAttribute('b', '{{a}}')
+      el.setAttribute('c', 'a {{b}} c') // invalid
+      var linker = compile(el, options)
+      linker(vm, el)
+      // should skip literal & invliad
+      expect(vm._bindDir.calls.count()).toBe(1)
+      var args = vm._bindDir.calls.argsFor(0)
+      expect(args[0]).toBe('with')
+      expect(args[1]).toBe(el)
+      // skipping descriptor because it's ducked inline
+      expect(args[3]).toBe(def)
+      // invalid should've warn
+      expect(_.warn).toHaveBeenCalled()
+      // literal should've called vm.$set
+      expect(vm.$set).toHaveBeenCalledWith('a', '1')
     })
     })
 
 
     it('DocumentFragment', function () {
     it('DocumentFragment', function () {
-      // body...
-    })
-
-    it('template elements', function () {
-      // body...
+      var frag = document.createDocumentFragment()
+      frag.appendChild(el)
+      var el2 = document.createElement('div')
+      frag.appendChild(el2)
+      el.innerHTML = '{{*a}}'
+      el2.innerHTML = '{{*b}}'
+      data.a = 'A'
+      data.b = 'B'
+      var linker = compile(frag, Vue.options)
+      linker(vm, frag)
+      expect(el.innerHTML).toBe('A')
+      expect(el2.innerHTML).toBe('B')
     })
     })
 
 
   })
   })

+ 11 - 0
test/unit/specs/compile/transclude_spec.js

@@ -49,6 +49,17 @@ if (_.inBrowser) {
       expect(res.childNodes.length).toBe(3)
       expect(res.childNodes.length).toBe(3)
       expect(res.firstChild.nodeType).toBe(8)
       expect(res.firstChild.nodeType).toBe(8)
       expect(res.lastChild.nodeType).toBe(8)
       expect(res.lastChild.nodeType).toBe(8)
+      expect(res.childNodes[1]).toBe(el)
+    })
+
+    it('template element', function () {
+      var tpl = document.createElement('template')
+      tpl.innerHTML = '<div>123</div>'
+      var res = transclude(tpl, options)
+      expect(res.childNodes.length).toBe(3)
+      expect(res.firstChild.nodeType).toBe(8)
+      expect(res.lastChild.nodeType).toBe(8)
+      expect(res.childNodes[1].textContent).toBe('123')
     })
     })
 
 
     it('content transclusion', function () {
     it('content transclusion', function () {

+ 6 - 0
test/unit/specs/util/merge-option_spec.js

@@ -33,6 +33,12 @@ describe('Util - Option merging', function () {
     expect(res.length).toBe(2)
     expect(res.length).toBe(2)
     expect(res[0]).toBe(fn1)
     expect(res[0]).toBe(fn1)
     expect(res[1]).toBe(fn2)
     expect(res[1]).toBe(fn2)
+    // both arrays
+    res = merge({paramAttributes: [1]}, {paramAttributes: [2]}).paramAttributes
+    expect(Array.isArray(res)).toBe(true)
+    expect(res.length).toBe(2)
+    expect(res[0]).toBe(1)
+    expect(res[1]).toBe(2)
   })
   })
 
 
   it('events', function () {
   it('events', function () {