Evan You 10 rokov pred
rodič
commit
4236c53740

+ 2 - 1
src/compiler/compile.js

@@ -570,7 +570,7 @@ function compileDirectives (attrs, options) {
 
     // event handlers
     if (onRE.test(name)) {
-      pushDir('on', internalDirectives.on, {
+      pushDir('on', publicDirectives.on, {
         arg: name.replace(onRE, '')
       })
     } else
@@ -613,6 +613,7 @@ function compileDirectives (attrs, options) {
           isLiteral = true
         }
         pushDir(dirName, dirDef, {
+          arg: arg,
           literal: isLiteral
         })
       }

+ 9 - 0
src/directive.js

@@ -163,6 +163,15 @@ Directive.prototype.param = function (name) {
   if (param != null) {
     this.el.removeAttribute(name)
     param = (this._scope || this.vm).$interpolate(param)
+  } else {
+    param = _.getBindAttr(this.el, name)
+    if (param != null) {
+      param = (this._scope || this.vm).$eval(param)
+      process.env.NODE_ENV !== 'production' && _.log(
+        'You are using bind- syntax on "' + name + '", which ' +
+        'is a directive param. It will be evaluated only once.'
+      )
+    }
   }
   return param
 }

+ 5 - 4
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="1">hello</p><div v-b#="hi"></div>'
+      el.innerHTML = '<p v-a:hello="a" v-b="1">hello</p><div v-b#="hi"></div>'
       var defA = { priority: 1 }
       var defB = { priority: 2 }
       var options = _.mergeOptions(Vue.options, {
@@ -80,6 +80,7 @@ if (_.inBrowser) {
       expect(args[0].name).toBe('a')
       expect(args[0].expression).toBe('a')
       expect(args[0].def).toBe(defA)
+      expect(args[0].arg).toBe('hello')
       expect(args[1]).toBe(el.firstChild)
       // 3 (expression literal)
       args = vm._bindDir.calls.argsFor(isAttrReversed ? 1 : 2)
@@ -141,7 +142,7 @@ if (_.inBrowser) {
       expect(args[0].name).toBe('on')
       expect(args[0].expression).toBe('a++')
       expect(args[0].arg).toBe('click')
-      expect(args[0].def).toBe(internalDirectives.on)
+      expect(args[0].def).toBe(publicDirectives.on)
       expect(args[1]).toBe(el)
     })
 
@@ -315,13 +316,13 @@ if (_.inBrowser) {
       vm = new Vue({
         el: el,
         template:
-          '<test class="a" on-click="test(1)"></test>',
+          '<test class="a" v-on:click="test(1)"></test>',
         methods: {
           test: parentSpy
         },
         components: {
           test: {
-            template: '<div class="b" on-click="test(2)"></div>',
+            template: '<div class="b" v-on:click="test(2)"></div>',
             replace: true,
             methods: {
               test: childSpy

+ 2 - 2
test/unit/specs/directives/element/partial_spec.js

@@ -31,7 +31,7 @@ describe('Partial', function () {
   it('dynamic', function (done) {
     var vm = new Vue({
       el: el,
-      template: '<partial bind-name="\'test-\' + id"></partial>',
+      template: '<partial :name="\'test-\' + id"></partial>',
       data: {
         id: 'a'
       },
@@ -80,7 +80,7 @@ describe('Partial', function () {
   it('teardown', function () {
     var vm = new Vue({
       el: el,
-      template: '<partial bind-name="\'test-\' + id"></partial>',
+      template: '<partial :name="\'test-\' + id"></partial>',
       data: {
         id: 'a'
       },

+ 4 - 4
test/unit/specs/directives/element/slot_spec.js

@@ -160,7 +160,7 @@ describe('Slot Distribution', function () {
         a: 1,
         show: true
       },
-      template: '<test bind-show="show">{{a}}</test>',
+      template: '<test :show="show">{{a}}</test>',
       components: {
         test: {
           props: ['show'],
@@ -189,7 +189,7 @@ describe('Slot Distribution', function () {
     el.innerHTML = '<p slot="1">1</p><p slot="2">2</p><p slot="3">3</p>'
     new Vue({
       el: el,
-      template: '<div v-for="n in list"><slot bind-name="$index + 1"></slot></div>',
+      template: '<div v-for="n in list"><slot :name="$index + 1"></slot></div>',
       data: {
         list: 0
       },
@@ -203,7 +203,7 @@ describe('Slot Distribution', function () {
   it('v-for + component + parent directive + transclusion', function (done) {
     var vm = new Vue({
       el: el,
-      template: '<test v-for="n in list" bind-class="cls" bind-a="n.a">{{msg}}</test>',
+      template: '<test v-for="n in list" :class="cls" :a="n.a">{{msg}}</test>',
       data: {
         cls: 'parent',
         msg: 'hi',
@@ -269,7 +269,7 @@ describe('Slot Distribution', function () {
       el: el,
       template:
         '<testa>' +
-          '<testb v-if="ok" bind-msg="msg"></testb>' +
+          '<testb v-if="ok" :msg="msg"></testb>' +
         '</testa>',
       data: {
         ok: false,

+ 8 - 8
test/unit/specs/directives/internal/component_spec.js

@@ -104,7 +104,7 @@ if (_.inBrowser) {
     it('dynamic', function (done) {
       var vm = new Vue({
         el: el,
-        template: '<component bind-is="view" bind-view="view"></component>',
+        template: '<component :is="view" :view="view"></component>',
         data: {
           view: 'view-a'
         },
@@ -142,7 +142,7 @@ if (_.inBrowser) {
       var spyB = jasmine.createSpy()
       var vm = new Vue({
         el: el,
-        template: '<component bind-is="view" keep-alive></component>',
+        template: '<component :is="view" keep-alive></component>',
         data: {
           view: 'view-a'
         },
@@ -251,7 +251,7 @@ if (_.inBrowser) {
         data: {
           list: [{a: 1}, {a: 2}]
         },
-        template: '<test bind-collection="list"></test>',
+        template: '<test :collection="list"></test>',
         components: {
           test: {
             template: '<ul><li v-for="item in collection">{{item.a}}</li></ul>',
@@ -290,7 +290,7 @@ if (_.inBrowser) {
         data: {
           view: 'view-a'
         },
-        template: '<component bind-is="view"></component>',
+        template: '<component :is="view"></component>',
         components: {
           'view-a': {
             template: 'AAA',
@@ -339,7 +339,7 @@ if (_.inBrowser) {
         data: {
           view: 'view-a'
         },
-        template: '<component bind-is="view" keep-alive></component>',
+        template: '<component :is="view" keep-alive></component>',
         components: {
           'view-a': {
             template: 'AAA',
@@ -381,7 +381,7 @@ if (_.inBrowser) {
         data: {
           view: 'view-a'
         },
-        template: '<component bind-is="view" transition="test" transition-mode="in-out"></component>',
+        template: '<component :is="view" transition="test" transition-mode="in-out"></component>',
         components: {
           'view-a': { template: 'AAA' },
           'view-b': { template: 'BBB' }
@@ -425,7 +425,7 @@ if (_.inBrowser) {
         data: {
           view: 'view-a'
         },
-        template: '<component bind-is="view" transition="test" transition-mode="out-in"></component>',
+        template: '<component :is="view" transition="test" transition-mode="out-in"></component>',
         components: {
           'view-a': { template: 'AAA' },
           'view-b': { template: 'BBB' }
@@ -459,7 +459,7 @@ if (_.inBrowser) {
     it('teardown', function (done) {
       var vm = new Vue({
         el: el,
-        template: '<component bind-is="view" keep-alive></component>',
+        template: '<component :is="view" keep-alive></component>',
         data: {
           view: 'test'
         },

+ 12 - 12
test/unit/specs/directives/internal/prop_spec.js

@@ -16,7 +16,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test bind-b="b" $.child></test>',
+        template: '<test v-bind:b="b" $.child></test>',
         components: {
           test: {
             props: ['b'],
@@ -40,7 +40,7 @@ if (_.inBrowser) {
     it('with filters', function (done) {
       var vm = new Vue({
         el: el,
-        template: '<test bind-name="a | test"></test>',
+        template: '<test :name="a | test"></test>',
         data: {
           a: 123
         },
@@ -73,7 +73,7 @@ if (_.inBrowser) {
             a: 'A'
           }
         },
-        template: '<test bind-testt@="test" bind-bb@="b" bind-a@=" test.a " $.child></test>',
+        template: '<test v-bind:testt@="test" :bb@="b" :a@=" test.a " $.child></test>',
         components: {
           test: {
             props: ['testt', 'bb', 'a'],
@@ -123,7 +123,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test bind-b*="b" $.child></test>',
+        template: '<test :b*="b" $.child></test>',
         components: {
           test: {
             props: ['b'],
@@ -145,7 +145,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test bind-b@=" b + \'B\'" $.child></test>',
+        template: '<test :b@=" b + \'B\'" $.child></test>',
         components: {
           test: {
             props: ['b'],
@@ -170,7 +170,7 @@ if (_.inBrowser) {
     it('warn expect two-way', function () {
       new Vue({
         el: el,
-        template: '<test bind-test="ok"></test>',
+        template: '<test :test="ok"></test>',
         data: {
           ok: 'hi'
         },
@@ -190,7 +190,7 @@ if (_.inBrowser) {
     it('warn $data as prop', function () {
       new Vue({
         el: el,
-        template: '<test bind-$data="ok"></test>',
+        template: '<test></test>',
         data: {
           ok: 'hi'
         },
@@ -206,7 +206,7 @@ if (_.inBrowser) {
     it('warn invalid keys', function () {
       new Vue({
         el: el,
-        template: '<test bind-a.b.c="test"></test>',
+        template: '<test :a.b.c="test"></test>',
         components: {
           test: {
             props: ['a.b.c']
@@ -248,7 +248,7 @@ if (_.inBrowser) {
           a: 'A',
           b: 'B'
         },
-        template: '<test bind-aa@="a" bind-bb="b"></test>',
+        template: '<test :aa@="a" :bb="b"></test>',
         components: {
           test: {
             props: ['aa', 'bb'],
@@ -279,7 +279,7 @@ if (_.inBrowser) {
     it('block instance with replace:true', function () {
       new Vue({
         el: el,
-        template: '<test bind-b="a" bind-c="d"></test>',
+        template: '<test :b="a" :c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'
@@ -300,7 +300,7 @@ if (_.inBrowser) {
       function makeInstance (value, type, validator) {
         return new Vue({
           el: document.createElement('div'),
-          template: '<test bind-test="val"></test>',
+          template: '<test :test="val"></test>',
           data: {
             val: value
           },
@@ -417,7 +417,7 @@ if (_.inBrowser) {
     it('alternative syntax', function () {
       new Vue({
         el: el,
-        template: '<test bind-b="a" bind-c="d"></test>',
+        template: '<test :b="a" :c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'

+ 2 - 2
test/unit/specs/directives/internal/ref_spec.js

@@ -39,7 +39,7 @@ if (_.inBrowser) {
         el: el,
         components: components,
         data: { test: 'test' },
-        template: '<component bind-is="test" $.test></component>'
+        template: '<component :is="test" $.test></component>'
       })
       expect(vm.$.test.$options.id).toBe('test')
       vm.test = 'test2'
@@ -57,7 +57,7 @@ if (_.inBrowser) {
       var vm = new Vue({
         el: el,
         data: { view: 'one' },
-        template: '{{$.test.value}}<component bind-is="view" $.test></component>',
+        template: '{{$.test.value}}<component :is="view" $.test></component>',
         components: {
           one: {
             id: 'one',

+ 1 - 1
test/unit/specs/directives/internal/transition_spec.js

@@ -59,7 +59,7 @@ if (_.inBrowser) {
       }
       var vm = new Vue({
         el: el,
-        template: '<div v-show="show" bind-transition="trans"></div>',
+        template: '<div v-show="show" :transition="trans"></div>',
         data: {
           show: true,
           trans: 'a'

+ 2 - 2
test/unit/specs/directives/public/for/for_ref_spec.js

@@ -12,7 +12,7 @@ describe('v-for + ref', function () {
     var vm = new Vue({
       el: el,
       data: { items: [1, 2, 3, 4, 5] },
-      template: '<test v-for="item in items" bind-item="item" $.test></test>',
+      template: '<test v-for="item in items" :item="item" $.test></test>',
       components: {
         test: {
           props: ['item']
@@ -41,7 +41,7 @@ describe('v-for + ref', function () {
           b: 2
         }
       },
-      template: '<test v-for="item in items" bind-item="item" $.test></test>',
+      template: '<test v-for="item in items" :item="item" $.test></test>',
       components: {
         test: {
           props: ['item']

+ 9 - 9
test/unit/specs/directives/public/for/for_spec.js

@@ -94,7 +94,7 @@ if (_.inBrowser) {
         data: {
           items: [{a: 1}, {a: 2}]
         },
-        template: '<test v-for="item in items" bind-index="$index" bind-item="item"></test>',
+        template: '<test v-for="item in items" :index="$index" :item="item"></test>',
         components: {
           test: {
             props: ['index', 'item'],
@@ -112,7 +112,7 @@ if (_.inBrowser) {
         data: {
           items: [{a: 1}, {a: 2}]
         },
-        template: '<p v-for="item in items" is="test" bind-index="$index" bind-item="item"></p>',
+        template: '<p v-for="item in items" is="test" :index="$index" :item="item"></p>',
         components: {
           test: {
             props: ['index', 'item'],
@@ -131,7 +131,7 @@ if (_.inBrowser) {
           items: [{a: 1}, {a: 2}]
         },
         template:
-          '<test v-for="item in items" bind-index="$index" bind-item="item" inline-template>' +
+          '<test v-for="item in items" :index="$index" :item="item" inline-template>' +
             '{{index}} {{item.a}}' +
           '</test>',
         components: {
@@ -149,7 +149,7 @@ if (_.inBrowser) {
         data: {
           items: [2, 1, 2]
         },
-        template: '<test v-for="item in items" bind-index="$index" bind-value="item"></test>',
+        template: '<test v-for="item in items" :index="$index" :value="item"></test>',
         components: {
           test: {
             props: ['index', 'value'],
@@ -170,7 +170,7 @@ if (_.inBrowser) {
             b: {a: 2}
           }
         },
-        template: '<test v-for="item in items" bind-key="$key" bind-index="$index" bind-value="item"></test>',
+        template: '<test v-for="item in items" :key="$key" :index="$index" :value="item"></test>',
         components: {
           test: {
             props: ['key', 'index', 'value'],
@@ -227,7 +227,7 @@ if (_.inBrowser) {
     it('dynamic component type based on instance data', function () {
       new Vue({
         el: el,
-        template: '<component v-for="item in list" bind-is="\'view-\' + item.type"></component>',
+        template: '<component v-for="item in list" :is="\'view-\' + item.type"></component>',
         data: {
           list: [
             { type: 'a' },
@@ -252,7 +252,7 @@ if (_.inBrowser) {
       el = document.createElement('div')
       new Vue({
         el: el,
-        template: '<component v-for="type in list" bind-is="\'view-\' + type"></component>',
+        template: '<component v-for="type in list" :is="\'view-\' + type"></component>',
         data: {
           list: ['a', 'b', 'c']
         },
@@ -309,7 +309,7 @@ if (_.inBrowser) {
     it('fragment loop with component', function (done) {
       var vm = new Vue({
         el: el,
-        template: '<template v-for="item in list"><test bind-a="item.a"></test></template>',
+        template: '<template v-for="item in list"><test :a="item.a"></test></template>',
         data: {
           list: [
             { a: 1 },
@@ -445,7 +445,7 @@ if (_.inBrowser) {
 
       var vm = new Vue({
         el: el,
-        template: '<test v-for="item in list" bind-item="item" track-by="id"></test>',
+        template: '<test v-for="item in list" :item="item" track-by="id"></test>',
         data: {
           list: [
             { id: 1, msg: 'hi' },

+ 3 - 3
test/unit/specs/directives/public/if_spec.js

@@ -14,7 +14,7 @@ if (_.inBrowser) {
       var vm = new Vue({
         el: el,
         data: { test: false, a: 'A' },
-        template: '<div v-if="test"><test bind-a="a"></test></div>',
+        template: '<div v-if="test"><test :a="a"></test></div>',
         components: {
           test: {
             props: ['a'],
@@ -112,7 +112,7 @@ if (_.inBrowser) {
           ok: false,
           view: 'view-a'
         },
-        template: '<component bind-is="view" v-if="ok"></component>',
+        template: '<component :is="view" v-if="ok"></component>',
         components: {
           'view-a': {
             template: 'AAA'
@@ -223,7 +223,7 @@ if (_.inBrowser) {
         template:
           '<outer>' +
             '<div>' + // an extra layer to test components deep inside the tree
-              '<transcluded v-for="item in list" bind-a="item.a"></transcluded>' +
+              '<transcluded v-for="item in list" :a="item.a"></transcluded>' +
             '</div>' +
           '</outer>',
         components: {

+ 6 - 6
test/unit/specs/directives/public/model_spec.js

@@ -90,10 +90,10 @@ if (_.inBrowser) {
           expression2: 'string2'
         },
         template:
-          '<input type="radio" value="1" v-model="test" name="test" bind-value="true">' +
-          '<input type="radio" value="0" v-model="test" name="test" bind-value="false">' +
-          '<input type="radio" value="1" v-model="test2" name="test2" bind-value="expression1">' +
-          '<input type="radio" value="0" v-model="test2" name="test2" bind-value="expression2">'
+          '<input type="radio" value="1" v-model="test" name="test" :value="true">' +
+          '<input type="radio" value="0" v-model="test" name="test" :value="false">' +
+          '<input type="radio" value="1" v-model="test2" name="test2" :value="expression1">' +
+          '<input type="radio" value="0" v-model="test2" name="test2" :value="expression2">'
       })
       expect(el.childNodes[0].checked).toBe(false)
       expect(el.childNodes[1].checked).toBe(true)
@@ -149,7 +149,7 @@ if (_.inBrowser) {
           expression1: 'aTrueValue',
           expression2: 'aFalseValue'
         },
-        template: '<input type="checkbox" v-model="test" bind-true-value="expression1" bind-false-value="expression2">'
+        template: '<input type="checkbox" v-model="test" :true-value="expression1" :false-value="expression2">'
       })
       expect(vm.test).toBe('')
       el.firstChild.click()
@@ -341,7 +341,7 @@ if (_.inBrowser) {
         },
         template:
           '<select v-model="test">' +
-            '<option v-for="op in opts" bind-value="op.value">{{op.text}}</option>' +
+            '<option v-for="op in opts" :value="op.value">{{op.text}}</option>' +
           '</select>'
       })
       var select = el.firstChild

+ 28 - 10
test/unit/specs/directives/public/on_spec.js

@@ -10,7 +10,7 @@ function trigger (target, event, process) {
 }
 
 if (_.inBrowser) {
-  describe('on-', function () {
+  describe('v-on', function () {
 
     var el
     beforeEach(function () {
@@ -22,7 +22,25 @@ if (_.inBrowser) {
       var spy = jasmine.createSpy()
       var vm = new Vue({
         el: el,
-        template: '<a on-click="test"></a>',
+        template: '<a v-on:click="test"></a>',
+        data: {a: 1},
+        methods: {
+          test: spy
+        }
+      })
+      var a = el.firstChild
+      trigger(a, 'click')
+      expect(spy.calls.count()).toBe(1)
+      vm.$destroy()
+      trigger(a, 'click')
+      expect(spy.calls.count()).toBe(1)
+    })
+
+    it('shorthand', function () {
+      var spy = jasmine.createSpy()
+      var vm = new Vue({
+        el: el,
+        template: '<a @click="test"></a>',
         data: {a: 1},
         methods: {
           test: spy
@@ -39,7 +57,7 @@ if (_.inBrowser) {
     it('inline expression', function (done) {
       new Vue({
         el: el,
-        template: '<a on-click="a++">{{a}}</a>',
+        template: '<a v-on:click="a++">{{a}}</a>',
         data: {a: 1}
       })
       var a = el.firstChild
@@ -53,7 +71,7 @@ if (_.inBrowser) {
     it('with key filter', function (done) {
       new Vue({
         el: el,
-        template: '<a on-keyup-enter="test">{{a}}</a>',
+        template: '<a v-on:keyup:enter="test">{{a}}</a>',
         data: {a: 1},
         methods: {
           test: function () {
@@ -74,7 +92,7 @@ if (_.inBrowser) {
     it('with key filter (keycode)', function (done) {
       new Vue({
         el: el,
-        template: '<a on-keyup-13="test">{{a}}</a>',
+        template: '<a v-on:keyup:13="test">{{a}}</a>',
         data: {a: 1},
         methods: {
           test: function () {
@@ -92,11 +110,11 @@ if (_.inBrowser) {
       })
     })
 
-    it('warn non-function values', function () {
+    it('warn nv-on:function values', function () {
       new Vue({
         el: el,
         data: { test: 123 },
-        template: '<a on-keyup="test"></a>'
+        template: '<a v-on:keyup="test"></a>'
       })
       expect(hasWarned(_, 'expects a function value')).toBe(true)
     })
@@ -108,7 +126,7 @@ if (_.inBrowser) {
       var spy = jasmine.createSpy()
       var vm = new Vue({
         el: el,
-        template: '<iframe on-click="test"></iframe>',
+        template: '<iframe v-on:click="test"></iframe>',
         methods: {
           test: spy
         }
@@ -126,7 +144,7 @@ if (_.inBrowser) {
       var test = jasmine.createSpy()
       new Vue({
         el: el,
-        template: '<a on-click="test($event)"></a>',
+        template: '<a v-on:click="test($event)"></a>',
         methods: {
           test: test
         }
@@ -144,7 +162,7 @@ if (_.inBrowser) {
       })
       parent.$addChild({
         el: el,
-        template: '<a on-click="$parent.test($event)"></a>'
+        template: '<a v-on:click="$parent.test($event)"></a>'
       })
       var e = trigger(el.firstChild, 'click')
       expect(test).toHaveBeenCalledWith(e)

+ 2 - 2
test/unit/specs/instance/state_spec.js

@@ -54,7 +54,7 @@ describe('Instance state initialization', function () {
 
     it('external prop should overwrite default value', function () {
       var el = document.createElement('div')
-      el.setAttribute('bind-c', '2')
+      el.setAttribute('v-bind:c', '2')
       el.textContent = '{{c}}'
       var vm = new Vue({
         el: el,
@@ -69,7 +69,7 @@ describe('Instance state initialization', function () {
 
     it('props should be available in data() and create()', function () {
       var el = document.createElement('div')
-      el.setAttribute('bind-c', '2')
+      el.setAttribute(':c', '2')
       var vm = new Vue({
         el: el,
         props: ['c'],

+ 2 - 2
test/unit/specs/util/component_spec.js

@@ -15,8 +15,8 @@ describe('Util - component', function () {
     expect(res.id).toBe('what')
     expect(res.dynamic).toBeFalsy()
 
-    // <component bind-is="...">
-    el.setAttribute('bind-is', 'what')
+    // <component :is="...">
+    el.setAttribute(':is', 'what')
     res = _.checkComponent(el)
     expect(res.id).toBe('what')
     expect(res.dynamic).toBe(true)