فهرست منبع

remove support for old prop syntax

Evan You 10 سال پیش
والد
کامیت
0c9d6dcf57

+ 30 - 92
src/compiler/compile-props.js

@@ -1,13 +1,11 @@
 var _ = require('../util')
-var textParser = require('../parsers/text')
 var propDef = require('../directives/internal/prop')
 var propBindingModes = require('../config')._propBindingModes
 
 // regexes
 var identRE = require('../parsers/path').identRE
-var dataAttrRE = /^data-/
 var settablePathRE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*|\[[^\[\]]+\])*$/
-var literalValueRE = /^(true|false)$|^\d.*/
+var literalValueRE = /^(true|false)$|^\d.*|^'[^']*'$|^"[^"]*"$/
 
 /**
  * Compile props on a root element and return
@@ -18,13 +16,10 @@ var literalValueRE = /^(true|false)$|^\d.*/
  * @return {Function} propsLinkFn
  */
 
-// TODO: 1.0.0 we can just loop through el.attributes and
-// check for prop- prefixes.
-
 module.exports = function compileProps (el, propOptions) {
   var props = []
   var i = propOptions.length
-  var options, name, attr, value, path, prop, literal, single
+  var options, name, attr, value, path, prop
   while (i--) {
     options = propOptions[i]
     name = options.name
@@ -40,7 +35,7 @@ module.exports = function compileProps (el, propOptions) {
     // props could contain dashes, which will be
     // interpreted as minus calculations by the parser
     // so we need to camelize the path here
-    path = _.camelize(name.replace(dataAttrRE, ''))
+    path = _.camelize(name)
     if (!identRE.test(path)) {
       process.env.NODE_ENV !== 'production' && _.warn(
         'Invalid prop key: "' + name + '". Prop keys ' +
@@ -48,20 +43,9 @@ module.exports = function compileProps (el, propOptions) {
       )
       continue
     }
-    attr = _.hyphenate(name)
-    value = el.getAttribute(attr)
 
-    if (value === null) {
-      value = el.getAttribute('data-' + attr)
-      if (value !== null) {
-        attr = 'data-' + attr
-        if (process.env.NODE_ENV !== 'production') {
-          _.deprecation.DATA_PROPS(attr, value)
-        }
-      }
-    }
-
-    // create a prop descriptor
+    attr = 'prop-' + _.hyphenate(name)
+    value = el.getAttribute(attr)
     prop = {
       name: name,
       raw: value,
@@ -69,70 +53,36 @@ module.exports = function compileProps (el, propOptions) {
       options: options,
       mode: propBindingModes.ONE_WAY
     }
+
     if (value !== null) {
-      // important so that this doesn't get compiled
-      // again as a normal attribute binding
       el.removeAttribute(attr)
-      var tokens = textParser.parse(value)
-      if (tokens) {
-
-        if (process.env.NODE_ENV !== 'production') {
-          _.deprecation.PROPS(attr, value)
-        }
-
+      value = value.trim()
+      // check binding type
+      if (literalValueRE.test(value)) {
+        prop.mode = propBindingModes.ONE_TIME
+      } else {
         prop.dynamic = true
-        prop.parentPath = textParser.tokensToExp(tokens)
-        // check prop binding type.
-        single = tokens.length === 1
-        literal = literalValueRE.test(prop.parentPath)
-        // one time: {{* prop}}
-        if (literal || (single && tokens[0].oneTime)) {
+        if (value.charAt(0) === '*') {
           prop.mode = propBindingModes.ONE_TIME
-        } else if (
-          !literal &&
-          (single && tokens[0].twoWay)
-        ) {
-          if (settablePathRE.test(prop.parentPath)) {
+          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: ' + prop.parentPath
+              'parent path: ' + value
             )
           }
         }
       }
-    } else {
-      // new syntax
-      attr = 'bind-' + attr
-      value = prop.raw = el.getAttribute(attr)
-      if (value !== null) {
-        // mark it so we know this is a bind
-        prop.bindSyntax = true
-        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
-              )
-            }
-          }
-        }
-      }
       prop.parentPath = value
+    } else if (options.required) {
+      // warn missing required
+      process.env.NODE_ENV !== 'production' && _.warn(
+        'Missing required prop: ' + name
+      )
     }
 
     // warn required two-way
@@ -146,13 +96,6 @@ module.exports = function compileProps (el, propOptions) {
       )
     }
 
-    // warn missing required
-    if (value === null && options && options.required) {
-      process.env.NODE_ENV !== 'production' && _.warn(
-        'Missing required prop: ' + name
-      )
-    }
-
     // push prop
     props.push(prop)
   }
@@ -200,19 +143,14 @@ function makePropsLinkFn (props) {
         }
       } else {
         // literal, cast it and just set once
-        var raw = prop.raw
-        if (options.type === Boolean && raw === '') {
-          value = true
-        } else if (raw.trim()) {
-          value = _.toBoolean(_.toNumber(raw))
-          if (process.env.NODE_ENV !== 'production' &&
-              !prop.bindSyntax &&
-              value !== raw) {
-            _.deprecation.PROP_CASTING(prop.name, prop.raw)
-          }
-        } else {
-          value = raw
-        }
+        var raw = _.stripQuotes(prop.raw) || prop.raw
+        value = options.type === Boolean && raw === ''
+          ? true
+          // do not cast emptry string.
+          // _.toNumber casts empty string to 0.
+          : raw.trim()
+            ? _.toBoolean(_.toNumber(raw))
+            : raw
         _.initProp(vm, prop, value)
       }
     }

+ 7 - 28
src/compiler/compile.js

@@ -552,22 +552,6 @@ function compileDirectives (attrs, options) {
       dirDef = resolveAsset(options, 'directives', dirName)
       if (process.env.NODE_ENV !== 'production') {
         _.assertAsset(dirDef, 'directive', dirName)
-
-        // deprecations
-        if (dirName === 'transition') {
-          _.deprecation.V_TRANSITION()
-        } else if (dirName === 'class') {
-          _.deprecation.V_CLASS()
-        } else if (dirName === 'style') {
-          _.deprecation.V_STYLE()
-        } else if (dirName === 'on') {
-          _.deprecation.V_ON()
-        } else if (dirName === 'attr') {
-          _.deprecation.V_ATTR()
-        } else if (dirName === 'el') {
-          _.deprecation.V_EL()
-        }
-
       }
       if (dirDef) {
         dirs.push({
@@ -655,18 +639,13 @@ function makeNodeLinkFn (directives) {
     var dir, j, k
     while (i--) {
       dir = directives[i]
-      if (dir._link) {
-        // custom link fn
-        dir._link(vm, el, scope)
-      } else {
-        // TODO: no need for loop here in 1.0.0
-        // also, we can just pass in the dir object to _bindDir,
-        // which is going to be much simpler.
-        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.literal)
-        }
+      // TODO: no need for loop here in 1.0.0
+      // also, we can just pass in the dir object to _bindDir,
+      // which is going to be much simpler.
+      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.literal)
       }
     }
   }

+ 0 - 74
src/deprecations.js

@@ -23,21 +23,6 @@ if (process.env.NODE_ENV !== 'production') {
       )
     },
 
-    V_EL: function () {
-      warn(
-        'v-el will no longer be a directive in 1.0.0. Use the "el" special attribute instead. ' +
-        'See https://github.com/yyx990803/vue/issues/1198 for details.'
-      )
-    },
-
-    V_TRANSITION: function () {
-      warn(
-        'v-transition will no longer be a directive in 1.0.0; It will become a ' +
-        'special attribute without the prefix. Use "transition" instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
     V_REF: function () {
       warn(
         'v-ref will no longer be a directive in 1.0.0; It will become a ' +
@@ -46,65 +31,6 @@ if (process.env.NODE_ENV !== 'production') {
       )
     },
 
-    V_CLASS: function () {
-      warn(
-        'v-class will no longer be a directive in 1.0.0; Use "bind-class" instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
-    V_STYLE: function () {
-      warn(
-        'v-style will no longer be a directive in 1.0.0; Use "bind-style" instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
-    V_ATTR: function () {
-      warn(
-        'v-attr will no longer be a directive in 1.0.0; Use the "bind-" syntax instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
-    V_ON: function () {
-      warn(
-        'v-on will no longer be a directive in 1.0.0; Use the "on-" syntax instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
-    ATTR_INTERPOLATION: function (name, value) {
-      warn(
-        'Mustache interpolations inside attributes: ' + name + '="' + value + '". ' +
-        'This will be deprecated in 1.0.0. ' +
-        'Use the "bind-" syntax instead.' + newBindingSyntaxLink
-      )
-    },
-
-    PROPS: function (attr, value) {
-      warn(
-        'Prop ' + attr + '="' + value + '": props no longer use mustache tags ' +
-        'to indicate a dynamic binding. Use the "bind-" prefix instead.' +
-        newBindingSyntaxLink
-      )
-    },
-
-    DATA_PROPS: function (attr, value) {
-      warn(
-        'Prop ' + attr + '="' + value + '": props will no longer support the ' +
-        '"data-" prefix in 1.0.0.' + newBindingSyntaxLink
-      )
-    },
-
-    PROP_CASTING: function (attr, value) {
-      warn(
-        'Prop ' + attr + '="' + value + '": literal props will no longer be ' +
-        'auto-casted into booleans/numbers in 1.0.0 - they will all be treated ' +
-        'as literal strings. Use "bind-" syntax for boolean/number literals instead.'
-      )
-    },
-
     PARTIAL_NAME: function (id) {
       warn(
         '<partial name="' + id + '">: mustache interpolations inside attributes ' +

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

@@ -215,8 +215,8 @@ if (_.inBrowser) {
       // temporarily remove vm.$parent
       var context = vm._context
       vm._context = null
-      el.setAttribute('a', 'hi')
-      el.setAttribute('b', '{{hi}}')
+      el.setAttribute('prop-a', '"hi"')
+      el.setAttribute('prop-b', 'hi')
       compiler.compileAndLinkProps(vm, el, [
         { name: 'a' },
         { name: 'b' }
@@ -291,13 +291,13 @@ if (_.inBrowser) {
     it('should teardown props and replacer directives when unlinking', function () {
       var vm = new Vue({
         el: el,
-        template: '<test prop="{{msg}}"></test>',
+        template: '<test prop-msg="msg"></test>',
         data: {
           msg: 'hi'
         },
         components: {
           test: {
-            props: ['prop'],
+            props: ['msg'],
             template: '<div v-show="true"></div>',
             replace: true
           }

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

@@ -157,7 +157,7 @@ describe('Slot Distribution', function () {
         a: 1,
         show: true
       },
-      template: '<test show="{{show}}">{{a}}</test>',
+      template: '<test prop-show="show">{{a}}</test>',
       components: {
         test: {
           props: ['show'],
@@ -266,7 +266,7 @@ describe('Slot Distribution', function () {
       el: el,
       template:
         '<testa>' +
-          '<testb v-if="ok" prop="{{msg}}"></testb>' +
+          '<testb v-if="ok" prop-msg="msg"></testb>' +
         '</testa>',
       data: {
         ok: false,
@@ -275,8 +275,8 @@ describe('Slot Distribution', function () {
       components: {
         testa: { template: '<slot></slot>' },
         testb: {
-          props: ['prop'],
-          template: '{{prop}}'
+          props: ['msg'],
+          template: '{{msg}}'
         }
       }
     })

+ 47 - 30
test/unit/specs/directives/internal/prop_spec.js

@@ -16,7 +16,7 @@ if (_.inBrowser) {
         data: {
           b: 'B'
         },
-        template: '<test b="{{b}}" v-ref="child"></test>',
+        template: '<test prop-b="b" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -46,7 +46,7 @@ if (_.inBrowser) {
             a: 'A'
           }
         },
-        template: '<test testt="{{@test}}" bb="{{@b}}" a="{{@ test.a }}" v-ref="child"></test>',
+        template: '<test prop-testt="@test" prop-bb="@b" prop-a="@ test.a " ref="child"></test>',
         components: {
           test: {
             props: ['testt', 'bb', 'a'],
@@ -90,32 +90,13 @@ if (_.inBrowser) {
       })
     })
 
-    it('$data as prop', function () {
-      new Vue({
-        el: el,
-        template: '<test $data="{{ok}}"></test>',
-        data: {
-          ok: {
-            msg: 'hihi'
-          }
-        },
-        components: {
-          test: {
-            props: ['$data'],
-            template: '{{msg}}'
-          }
-        }
-      })
-      expect(hasWarned(_, 'Do not use $data as prop')).toBe(true)
-    })
-
     it('explicit one time binding', function (done) {
       var vm = new Vue({
         el: el,
         data: {
           b: 'B'
         },
-        template: '<test b="{{*b}}" v-ref="child"></test>',
+        template: '<test prop-b="*b" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -131,13 +112,13 @@ if (_.inBrowser) {
       })
     })
 
-    it('non-settable parent path', function (done) {
+    it('warn non-settable parent path', function (done) {
       var vm = new Vue({
         el: el,
         data: {
           b: 'B'
         },
-        template: '<test b="{{@ b + \'B\' }}" v-ref="child"></test>',
+        template: '<test prop-b="@ b + \'B\'" ref="child"></test>',
         components: {
           test: {
             props: ['b'],
@@ -159,10 +140,46 @@ if (_.inBrowser) {
       })
     })
 
+    it('warn expect two-way', function () {
+      new Vue({
+        el: el,
+        template: '<test prop-test="ok"></test>',
+        data: {
+          ok: 'hi'
+        },
+        components: {
+          test: {
+            props: {
+              test: {
+                twoWay: true
+              }
+            }
+          }
+        }
+      })
+      expect(hasWarned(_, 'expects a two-way binding type')).toBe(true)
+    })
+
+    it('warn $data as prop', function () {
+      new Vue({
+        el: el,
+        template: '<test prop-$data="ok"></test>',
+        data: {
+          ok: 'hi'
+        },
+        components: {
+          test: {
+            props: ['$data']
+          }
+        }
+      })
+      expect(hasWarned(_, 'Do not use $data as prop')).toBe(true)
+    })
+
     it('warn invalid keys', function () {
       new Vue({
         el: el,
-        template: '<test a.b.c="{{test}}"></test>',
+        template: '<test prop-a.b.c="test"></test>',
         components: {
           test: {
             props: ['a.b.c']
@@ -204,7 +221,7 @@ if (_.inBrowser) {
           a: 'A',
           b: 'B'
         },
-        template: '<test aa="{{@a}}" bb="{{b}}"></test>',
+        template: '<test prop-aa="@a" prop-bb="b"></test>',
         components: {
           test: {
             props: ['aa', 'bb'],
@@ -235,7 +252,7 @@ if (_.inBrowser) {
     it('block instance with replace:true', function () {
       new Vue({
         el: el,
-        template: '<test b="{{a}}" c="{{d}}"></test>',
+        template: '<test prop-b="a" prop-c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'
@@ -256,7 +273,7 @@ if (_.inBrowser) {
       function makeInstance (value, type, validator) {
         return new Vue({
           el: document.createElement('div'),
-          template: '<test prop="{{val}}"></test>',
+          template: '<test prop-test="val"></test>',
           data: {
             val: value
           },
@@ -264,7 +281,7 @@ if (_.inBrowser) {
             test: {
               props: [
                 {
-                  name: 'prop',
+                  name: 'test',
                   type: type,
                   validator: validator
                 }
@@ -373,7 +390,7 @@ if (_.inBrowser) {
     it('alternative syntax', function () {
       new Vue({
         el: el,
-        template: '<test b="{{a}}" c="{{d}}"></test>',
+        template: '<test prop-b="a" prop-c="d"></test>',
         data: {
           a: 'AAA',
           d: 'DDD'

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

@@ -1,7 +1,7 @@
 var Vue = require('../../../../../../src/vue')
 var _ = Vue.util
 
-describe('v-for + v-ref', function () {
+describe('v-for + ref', function () {
 
   var el
   beforeEach(function () {
@@ -12,7 +12,7 @@ describe('v-for + v-ref', function () {
     var vm = new Vue({
       el: el,
       data: { items: [1, 2, 3, 4, 5] },
-      template: '<test v-for="item in items" item="{{item}}" v-ref="test"></test>',
+      template: '<test v-for="item in items" prop-item="item" ref="test"></test>',
       components: {
         test: {
           props: ['item']
@@ -41,7 +41,7 @@ describe('v-for + v-ref', function () {
           b: 2
         }
       },
-      template: '<test v-for="item in items" item="{{item}}" v-ref="test"></test>',
+      template: '<test v-for="item in items" prop-item="item" ref="test"></test>',
       components: {
         test: {
           props: ['item']
@@ -65,10 +65,10 @@ describe('v-for + v-ref', function () {
   it('nested', function () {
     var vm = new Vue({
       el: el,
-      template: '<c1 v-ref="c1"></c1>',
+      template: '<c1 ref="c1"></c1>',
       components: {
         c1: {
-          template: '<div v-for="n in 2" v-ref="c2"></div>'
+          template: '<div v-for="n in 2" ref="c2"></div>'
         }
       }
     })

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

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