Parcourir la source

support new literal directive syntax

Evan You il y a 10 ans
Parent
commit
0818e697dd

+ 13 - 3
src/compiler/compile.js

@@ -538,7 +538,7 @@ function makeTerminalNodeLinkFn (el, dirName, value, options, def) {
 function compileDirectives (attrs, options) {
   var i = attrs.length
   var dirs = []
-  var attr, name, value, dir, dirName, dirDef, arg
+  var attr, name, value, dir, dirName, dirDef, isLiteral, arg
   while (i--) {
     attr = attrs[i]
     name = attr.name
@@ -546,6 +546,15 @@ function compileDirectives (attrs, options) {
     // Core directive
     if (name.indexOf(config.prefix) === 0) {
       dirName = name.slice(config.prefix.length)
+
+      // check literal directive
+      if (dirName.charAt(dirName.length - 1) === ':') {
+        dirName = dirName.slice(0, -1)
+        isLiteral = true
+      } else {
+        isLiteral = false
+      }
+
       dirDef = resolveAsset(options, 'directives', dirName)
       if (process.env.NODE_ENV !== 'production') {
         _.assertAsset(dirDef, 'directive', dirName)
@@ -570,7 +579,8 @@ function compileDirectives (attrs, options) {
         dirs.push({
           name: dirName,
           descriptors: dirParser.parse(value),
-          def: dirDef
+          def: dirDef,
+          literal: isLiteral
         })
       }
     } else
@@ -661,7 +671,7 @@ function makeNodeLinkFn (directives) {
         k = dir.descriptors.length
         for (j = 0; j < k; j++) {
           vm._bindDir(dir.name, el,
-            dir.descriptors[j], dir.def, host, scope, frag, dir.arg)
+            dir.descriptors[j], dir.def, host, scope, frag, dir.arg, dir.literal)
         }
       }
     }

+ 10 - 3
src/directive.js

@@ -26,7 +26,7 @@ var expParser = require('./parsers/expression')
 
 // TODO: 1.0.0 cleanup the arguments
 
-function Directive (name, el, vm, descriptor, def, host, scope, frag, arg) {
+function Directive (name, el, vm, descriptor, def, host, scope, frag, arg, literal) {
   // public
   this.name = name
   this.el = el
@@ -45,6 +45,8 @@ function Directive (name, el, vm, descriptor, def, host, scope, frag, arg) {
   this._host = host
   this._scope = scope
   this._frag = frag
+  // 1.0.0 literal
+  this._literal = literal
 }
 
 /**
@@ -62,7 +64,9 @@ Directive.prototype._bind = function () {
     (name !== 'cloak' || this.vm._isCompiled) &&
     this.el && this.el.removeAttribute
   ) {
-    this.el.removeAttribute(config.prefix + this.name)
+    this.el.removeAttribute(
+      config.prefix + this.name + (this._literal ? ':' : '')
+    )
     // 1.0.0: remove bind/on
     // TODO simplify this
     if (name === 'attr') {
@@ -85,7 +89,10 @@ Directive.prototype._bind = function () {
   if (this.bind) {
     this.bind()
   }
-  if (this._watcherExp &&
+
+  if (this._literal) {
+    this.update && this.update(this._descriptor.raw)
+  } else if (this._watcherExp &&
       (this.update || this.twoWay) &&
       (!this.isLiteral || this._isDynamicLiteral) &&
       !this._checkStatement()) {

+ 2 - 2
src/instance/lifecycle.js

@@ -107,9 +107,9 @@ exports._initElement = function (el) {
  * @param {Fragment} [frag] - owner fragment
  */
 
-exports._bindDir = function (name, node, desc, def, host, scope, frag, arg) {
+exports._bindDir = function (name, node, desc, def, host, scope, frag, arg, literal) {
   this._directives.push(
-    new Directive(name, node, this, desc, def, host, scope, frag, arg)
+    new Directive(name, node, this, desc, def, host, scope, frag, arg, literal)
   )
 }
 

+ 9 - 9
test/unit/specs/compiler/compile_spec.js

@@ -50,7 +50,7 @@ if (_.inBrowser) {
 
     it('normal directives', function () {
       el.setAttribute('v-a', 'b')
-      el.innerHTML = '<p v-a="a" v-b="b">hello</p><div v-b="b"></div>'
+      el.innerHTML = '<p v-a="a" v-b="b">hello</p><div v-b:="b"></div>'
       var defA = { priority: 1 }
       var defB = { priority: 2 }
       var descriptorA = dirParser.parse('a')[0]
@@ -66,10 +66,10 @@ if (_.inBrowser) {
       linker(vm, el)
       expect(directiveBind.calls.count()).toBe(4)
       expect(vm._bindDir.calls.count()).toBe(4)
-      expect(vm._bindDir).toHaveBeenCalledWith('a', el, descriptorB, defA, undefined, undefined, undefined, undefined)
-      expect(vm._bindDir).toHaveBeenCalledWith('a', el.firstChild, descriptorA, defA, undefined, undefined, undefined, undefined)
-      expect(vm._bindDir).toHaveBeenCalledWith('b', el.firstChild, descriptorB, defB, undefined, undefined, undefined, undefined)
-      expect(vm._bindDir).toHaveBeenCalledWith('b', el.lastChild, descriptorB, defB, undefined, undefined, undefined, undefined)
+      expect(vm._bindDir).toHaveBeenCalledWith('a', el, descriptorB, defA, undefined, undefined, undefined, undefined, false)
+      expect(vm._bindDir).toHaveBeenCalledWith('a', el.firstChild, descriptorA, defA, undefined, undefined, undefined, undefined, false)
+      expect(vm._bindDir).toHaveBeenCalledWith('b', el.firstChild, descriptorB, defB, undefined, undefined, undefined, undefined, false)
+      expect(vm._bindDir).toHaveBeenCalledWith('b', el.lastChild, descriptorB, defB, undefined, undefined, undefined, undefined, true)
       // check the priority sorting
       // the "b"s should be called first!
       expect(directiveBind.calls.argsFor(0)[0]).toBe('b')
@@ -88,9 +88,9 @@ if (_.inBrowser) {
       var linker = compile(el, Vue.options)
       linker(vm, el)
       expect(vm._bindDir.calls.count()).toBe(3)
-      expect(vm._bindDir).toHaveBeenCalledWith('class', el, descA, Vue.options.directives.class, undefined, undefined, undefined, undefined)
-      expect(vm._bindDir).toHaveBeenCalledWith('style', el, descB, Vue.options.directives.style, undefined, undefined, undefined, undefined)
-      expect(vm._bindDir).toHaveBeenCalledWith('attr', el, descC, Vue.options.directives.attr, undefined, undefined, undefined, 'title')
+      expect(vm._bindDir).toHaveBeenCalledWith('class', el, descA, Vue.options.directives.class, undefined, undefined, undefined, undefined, undefined)
+      expect(vm._bindDir).toHaveBeenCalledWith('style', el, descB, Vue.options.directives.style, undefined, undefined, undefined, undefined, undefined)
+      expect(vm._bindDir).toHaveBeenCalledWith('attr', el, descC, Vue.options.directives.attr, undefined, undefined, undefined, 'title', undefined)
     })
 
     it('on- syntax', function () {
@@ -99,7 +99,7 @@ if (_.inBrowser) {
       var linker = compile(el, Vue.options)
       linker(vm, el)
       expect(vm._bindDir.calls.count()).toBe(1)
-      expect(vm._bindDir).toHaveBeenCalledWith('on', el, desc, Vue.options.directives.on, undefined, undefined, undefined, 'click')
+      expect(vm._bindDir).toHaveBeenCalledWith('on', el, desc, Vue.options.directives.on, undefined, undefined, undefined, 'click', undefined)
     })
 
     it('text interpolation', function () {