Просмотр исходного кода

change prop- to bind- for props

Evan You 10 лет назад
Родитель
Сommit
88c8789d7d

+ 54 - 43
src/compiler/compile-props.js

@@ -24,11 +24,10 @@ module.exports = function compileProps (el, propOptions) {
     options = propOptions[i]
     name = options.name
 
-    if (name === '$data') {
-      process.env.NODE_ENV !== 'production' && _.warn(
-        'Do not use $data as prop.'
-      )
-      el.removeAttribute(name)
+    if (process.env.NODE_ENV !== 'production' && name === '$data') {
+      _.warn('Do not use $data as prop.')
+      el.removeAttribute('$data')
+      el.removeAttribute('bind-$data')
       continue
     }
 
@@ -44,45 +43,55 @@ module.exports = function compileProps (el, propOptions) {
       continue
     }
 
-    attr = 'prop-' + _.hyphenate(name)
-    value = el.getAttribute(attr)
     prop = {
       name: name,
-      raw: value,
       path: path,
       options: options,
       mode: propBindingModes.ONE_WAY
     }
 
+    // first check literal version
+    attr = _.hyphenate(name)
+    value = prop.raw = el.getAttribute(attr)
     if (value !== null) {
       el.removeAttribute(attr)
-      value = value.trim()
-      // check binding type
-      if (literalValueRE.test(value)) {
-        prop.mode = propBindingModes.ONE_TIME
-      } else {
-        prop.dynamic = true
-        if (value.charAt(0) === '*') {
-          prop.mode = propBindingModes.ONE_TIME
-          value = value.slice(1).trim()
-        } else if (value.charAt(0) === '@') {
-          value = value.slice(1).trim()
-          if (settablePathRE.test(value)) {
-            prop.mode = propBindingModes.TWO_WAY
-          } else {
-            process.env.NODE_ENV !== 'production' && _.warn(
-              'Cannot bind two-way prop with non-settable ' +
-              'parent path: ' + value
-            )
+    } else {
+      // then check dynamic version
+      attr = 'bind-' + attr
+      value = prop.raw = el.getAttribute(attr)
+      if (value !== null) {
+        el.removeAttribute(attr)
+        value = value.trim()
+        // check binding type
+        if (literalValueRE.test(value)) {
+          // for bind- literals such as numbers and booleans,
+          // there's no need to setup a prop binding, so we
+          // can optimize them as a one-time set.
+          prop.optimizedLiteral = true
+        } else {
+          prop.dynamic = true
+          if (value.charAt(0) === '*') {
+            prop.mode = propBindingModes.ONE_TIME
+            value = value.slice(1).trim()
+          } else if (value.charAt(0) === '@') {
+            value = value.slice(1).trim()
+            if (settablePathRE.test(value)) {
+              prop.mode = propBindingModes.TWO_WAY
+            } else {
+              process.env.NODE_ENV !== 'production' && _.warn(
+                'Cannot bind two-way prop with non-settable ' +
+                'parent path: ' + value
+              )
+            }
           }
         }
+        prop.parentPath = value
+      } else if (options.required) {
+        // warn missing required
+        process.env.NODE_ENV !== 'production' && _.warn(
+          'Missing required prop: ' + name
+        )
       }
-      prop.parentPath = value
-    } else if (options.required) {
-      // warn missing required
-      process.env.NODE_ENV !== 'production' && _.warn(
-        'Missing required prop: ' + name
-      )
     }
 
     // warn required two-way
@@ -114,13 +123,14 @@ function makePropsLinkFn (props) {
     // store resolved props info
     vm._props = {}
     var i = props.length
-    var prop, path, options, value
+    var prop, path, options, value, raw
     while (i--) {
       prop = props[i]
+      raw = prop.raw
       path = prop.path
-      vm._props[path] = prop
       options = prop.options
-      if (prop.raw === null) {
+      vm._props[path] = prop
+      if (raw === null) {
         // initialize absent prop
         _.initProp(vm, prop, getDefault(options))
       } else if (prop.dynamic) {
@@ -138,19 +148,20 @@ function makePropsLinkFn (props) {
           process.env.NODE_ENV !== 'production' && _.warn(
             'Cannot bind dynamic prop on a root instance' +
             ' with no parent: ' + prop.name + '="' +
-            prop.raw + '"'
+            raw + '"'
           )
         }
+      } else if (prop.optimizedLiteral) {
+        // optimized literal, cast it and just set once
+        raw = _.stripQuotes(raw) || raw
+        value = _.toBoolean(_.toNumber(raw))
+        _.initProp(vm, prop, value)
       } else {
-        // literal, cast it and just set once
-        var raw = _.stripQuotes(prop.raw) || prop.raw
+        // string literal, but we need to cater for
+        // Boolean props with no value
         value = options.type === Boolean && raw === ''
           ? true
-          // do not cast emptry string.
-          // _.toNumber casts empty string to 0.
-          : raw.trim()
-            ? _.toBoolean(_.toNumber(raw))
-            : raw
+          : raw
         _.initProp(vm, prop, value)
       }
     }

+ 1 - 1
test/unit/specs/async_component_spec.js

@@ -197,7 +197,7 @@ describe('Async components', function () {
   it('v-for', function (done) {
     new Vue({
       el: el,
-      template: '<test v-for="n in list" prop-n="n"></test>',
+      template: '<test v-for="n in list" bind-n="n"></test>',
       data: {
         list: [1, 2, 3]
       },

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

@@ -185,8 +185,8 @@ if (_.inBrowser) {
       compiler.compileAndLinkProps(vm, el, props)
       expect(vm._bindDir.calls.count()).toBe(3) // skip literal and one time
       // literal
-      expect(vm.testLiteral).toBe(1)
-      expect(vm._data.testLiteral).toBe(1)
+      expect(vm.testLiteral).toBe('1')
+      expect(vm._data.testLiteral).toBe('1')
       expect(vm.optimizeLiteral).toBe(1)
       expect(vm._data.optimizeLiteral).toBe(1)
       // one time
@@ -214,8 +214,8 @@ if (_.inBrowser) {
       // temporarily remove vm.$parent
       var context = vm._context
       vm._context = null
-      el.setAttribute('prop-a', '"hi"')
-      el.setAttribute('prop-b', 'hi')
+      el.setAttribute('bind-a', '"hi"')
+      el.setAttribute('bind-b', 'hi')
       compiler.compileAndLinkProps(vm, el, [
         { name: 'a' },
         { name: 'b' }
@@ -290,7 +290,7 @@ if (_.inBrowser) {
     it('should teardown props and replacer directives when unlinking', function () {
       var vm = new Vue({
         el: el,
-        template: '<test prop-msg="msg"></test>',
+        template: '<test bind-msg="msg"></test>',
         data: {
           msg: 'hi'
         },

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

@@ -157,7 +157,7 @@ describe('Slot Distribution', function () {
         a: 1,
         show: true
       },
-      template: '<test prop-show="show">{{a}}</test>',
+      template: '<test bind-show="show">{{a}}</test>',
       components: {
         test: {
           props: ['show'],
@@ -200,7 +200,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" prop-a="n.a">{{msg}}</test>',
+      template: '<test v-for="n in list" bind-class="cls" bind-a="n.a">{{msg}}</test>',
       data: {
         cls: 'parent',
         msg: 'hi',
@@ -266,7 +266,7 @@ describe('Slot Distribution', function () {
       el: el,
       template:
         '<testa>' +
-          '<testb v-if="ok" prop-msg="msg"></testb>' +
+          '<testb v-if="ok" bind-msg="msg"></testb>' +
         '</testa>',
       data: {
         ok: false,

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

@@ -16,7 +16,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test prop-b="b" ref="child"></test>',
+        template: '<test bind-b="b" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -46,7 +46,7 @@ if (_.inBrowser) {
             a: 'A'
           }
         },
-        template: '<test prop-testt="@test" prop-bb="@b" prop-a="@ test.a " ref="child"></test>',
+        template: '<test bind-testt="@test" bind-bb="@b" bind-a="@ test.a " ref="child"></test>',
         components: {
           test: {
             props: ['testt', 'bb', 'a'],
@@ -96,7 +96,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test prop-b="*b" ref="child"></test>',
+        template: '<test bind-b="*b" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -118,7 +118,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test prop-b="@ b + \'B\'" ref="child"></test>',
+        template: '<test bind-b="@ b + \'B\'" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -143,7 +143,7 @@ if (_.inBrowser) {
     it('warn expect two-way', function () {
       new Vue({
         el: el,
-        template: '<test prop-test="ok"></test>',
+        template: '<test bind-test="ok"></test>',
         data: {
           ok: 'hi'
         },
@@ -163,7 +163,7 @@ if (_.inBrowser) {
     it('warn $data as prop', function () {
       new Vue({
         el: el,
-        template: '<test prop-$data="ok"></test>',
+        template: '<test bind-$data="ok"></test>',
         data: {
           ok: 'hi'
         },
@@ -179,7 +179,7 @@ if (_.inBrowser) {
     it('warn invalid keys', function () {
       new Vue({
         el: el,
-        template: '<test prop-a.b.c="test"></test>',
+        template: '<test bind-a.b.c="test"></test>',
         components: {
           test: {
             props: ['a.b.c']
@@ -221,7 +221,7 @@ if (_.inBrowser) {
           a: 'A',
           b: 'B'
         },
-        template: '<test prop-aa="@a" prop-bb="b"></test>',
+        template: '<test bind-aa="@a" bind-bb="b"></test>',
         components: {
           test: {
             props: ['aa', 'bb'],
@@ -252,7 +252,7 @@ if (_.inBrowser) {
     it('block instance with replace:true', function () {
       new Vue({
         el: el,
-        template: '<test prop-b="a" prop-c="d"></test>',
+        template: '<test bind-b="a" bind-c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'
@@ -273,7 +273,7 @@ if (_.inBrowser) {
       function makeInstance (value, type, validator) {
         return new Vue({
           el: document.createElement('div'),
-          template: '<test prop-test="val"></test>',
+          template: '<test bind-test="val"></test>',
           data: {
             val: value
           },
@@ -390,7 +390,7 @@ if (_.inBrowser) {
     it('alternative syntax', function () {
       new Vue({
         el: el,
-        template: '<test prop-b="a" prop-c="d"></test>',
+        template: '<test bind-b="a" bind-c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'

+ 1 - 1
test/unit/specs/directives/public/component_spec.js

@@ -251,7 +251,7 @@ if (_.inBrowser) {
         data: {
           list: [{a: 1}, {a: 2}]
         },
-        template: '<test prop-collection="list"></test>',
+        template: '<test bind-collection="list"></test>',
         components: {
           test: {
             template: '<ul><li v-for="item in collection">{{item.a}}</li></ul>',

+ 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" prop-item="item" ref="test"></test>',
+      template: '<test v-for="item in items" bind-item="item" ref="test"></test>',
       components: {
         test: {
           props: ['item']
@@ -41,7 +41,7 @@ describe('v-for + ref', function () {
           b: 2
         }
       },
-      template: '<test v-for="item in items" prop-item="item" ref="test"></test>',
+      template: '<test v-for="item in items" bind-item="item" ref="test"></test>',
       components: {
         test: {
           props: ['item']

+ 7 - 7
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" prop-index="$index" prop-item="item"></test>',
+        template: '<test v-for="item in items" bind-index="$index" bind-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" v-component="test" prop-index="$index" prop-item="item"></p>',
+        template: '<p v-for="item in items" v-component="test" bind-index="$index" bind-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" prop-index="$index" prop-item="item" inline-template>' +
+          '<test v-for="item in items" bind-index="$index" bind-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" prop-index="$index" prop-value="item"></test>',
+        template: '<test v-for="item in items" bind-index="$index" bind-value="item"></test>',
         components: {
           test: {
             props: ['index', 'value'],
@@ -170,7 +170,7 @@ if (_.inBrowser) {
             b: {a: 2}
           }
         },
-        template: '<test v-for="item in items" prop-key="$key" prop-index="$index" prop-value="item"></test>',
+        template: '<test v-for="item in items" bind-key="$key" bind-index="$index" bind-value="item"></test>',
         components: {
           test: {
             props: ['key', 'index', 'value'],
@@ -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 prop-a="item.a"></test></template>',
+        template: '<template v-for="item in list"><test bind-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" prop-item="item" track-by="id"></test>',
+        template: '<test v-for="item in list" bind-item="item" track-by="id"></test>',
         data: {
           list: [
             { id: 1, msg: 'hi' },

+ 2 - 2
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 prop-a="a"></test></div>',
+        template: '<div v-if="test"><test bind-a="a"></test></div>',
         components: {
           test: {
             props: ['a'],
@@ -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" prop-a="item.a"></transcluded>' +
+              '<transcluded v-for="item in list" bind-a="item.a"></transcluded>' +
             '</div>' +
           '</outer>',
         components: {

+ 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('prop-c', '2')
+      el.setAttribute('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('prop-c', '2')
+      el.setAttribute('bind-c', '2')
       var vm = new Vue({
         el: el,
         props: ['c'],