Quellcode durchsuchen

make `paramAttribute` deal with attributes containing dashes

Evan You vor 11 Jahren
Ursprung
Commit
286ae93b65

+ 10 - 1
changes.md

@@ -73,6 +73,15 @@ By default, all child components **DO NOT** inherit the parent scope. Only anony
   })
   ```
 
+- #### `paramAttributes` change
+
+  `paramAttributes` now behaves a little differently when the attribute name contains dashes:
+
+  1. If the attribute is a data attribute, the `data-` prefix will be auto stripped;
+  2. If the attribute still contains dashes, it will be camelized. The reason is because it's inconvenient to access top level properties containing dashes in templates: the expression `my-param` will be parsed as a minus expression unless you use the awkward `this['my-param']` syntax.
+
+  This means a param attribute `data-hello` will be set on the vm as `vm.hello`; And `my-param` will be set as `vm.myParam`.
+
 - #### new option: `events`.
 
   When events are used extensively for cross-vm communication, the ready hook can get kinda messy. The new `events` option is similar to its Backbone equivalent, where you can declaratiely register a bunch of event listeners. You can also use it to register hook listeners.
@@ -131,7 +140,7 @@ By default, all child components **DO NOT** inherit the parent scope. Only anony
   // -> 2
   ```
 
-- #### new options: `name`.
+- #### new option: `name`.
 
   This option, when used with `Vue.extend`, gives your returned constructor a more descriptive name rather than the generic `VueComponent`. This makes debugging easier when you log instances in the console. For example:
 

+ 1 - 1
src/api/global.js

@@ -55,7 +55,7 @@ exports.extend = function (extendOptions) {
 
 function createClass (name) {
   return new Function(
-    'return function ' + _.camelize(name) +
+    'return function ' + _.camelize(name, true) +
     ' (options) { this._init(options) }'
   )()
 }

+ 9 - 3
src/compile/compile.js

@@ -346,25 +346,31 @@ function compileParamAttributes (el, attrs, options) {
  * @return {Function} paramsLinkFn
  */
 
+var dataAttrRE = /^data-/
+
 function makeParamsLinkFn (params, options) {
   var def = options.directives['with']
   return function paramsLinkFn (vm, el) {
     var i = params.length
-    var param
+    var param, path
     while (i--) {
       param = params[i]
+      // params could contain dashes, which will be
+      // interpreted as minus calculations by the parser
+      // so we need to wrap the path here
+      path = _.camelize(param.name.replace(dataAttrRE, ''))
       if (param.dynamic) {
         // dynamic param attribtues are bound as v-with.
         // we can directly duck the descriptor here beacuse
         // param attributes cannot use expressions or
         // filters.
         vm._bindDir('with', el, {
-          arg: param.name,
+          arg: path,
           expression: param.value
         }, def)
       } else {
         // just set once
-        vm.$set(param.name, param.value)
+        vm.$set(path, param.value)
       }
     }
   }

+ 6 - 3
src/util/lang.js

@@ -63,9 +63,12 @@ exports.stripQuotes = function (str) {
  * @return {String}
  */
 
-var camelRE = /(?:^|[-_])(\w)/g
-exports.camelize = function (str) {
-  return str.replace (camelRE, function (_, c) {
+var camelRE = /[-_](\w)/g
+var capitalCamelRE = /(?:^|[-_])(\w)/g
+
+exports.camelize = function (str, cap) {
+  var RE = cap ? capitalCamelRE : camelRE
+  return str.replace(RE, function (_, c) {
     return c ? c.toUpperCase () : '';
   })
 }

+ 6 - 4
test/unit/specs/compile/compile_spec.js

@@ -148,12 +148,13 @@ if (_.inBrowser) {
 
     it('param attributes', function () {
       var options = merge(Vue.options, {
-        paramAttributes: ['a', 'b', 'c']
+        paramAttributes: ['a', 'data-some-attr', 'some-other-attr', 'invalid']
       })
       var def = Vue.options.directives['with']
       el.setAttribute('a', '1')
-      el.setAttribute('b', '{{a}}')
-      el.setAttribute('c', 'a {{b}} c') // invalid
+      el.setAttribute('data-some-attr', '{{a}}')
+      el.setAttribute('some-other-attr', '2')
+      el.setAttribute('invalid', 'a {{b}} c') // invalid
       var linker = compile(el, options)
       linker(vm, el)
       // should skip literal & invliad
@@ -161,12 +162,13 @@ if (_.inBrowser) {
       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[2].arg).toBe('someAttr')
       expect(args[3]).toBe(def)
       // invalid should've warn
       expect(_.warn).toHaveBeenCalled()
       // literal should've called vm.$set
       expect(vm.$set).toHaveBeenCalledWith('a', '1')
+      expect(vm.$set).toHaveBeenCalledWith('someOtherAttr', '2')
     })
 
     it('DocumentFragment', function () {

+ 6 - 3
test/unit/specs/util/lang_spec.js

@@ -25,9 +25,12 @@ describe('Util - Language Enhancement', function () {
   })
 
   it('camelize', function () {
-    expect(_.camelize('abc')).toBe('Abc')
-    expect(_.camelize('some-long-name')).toBe('SomeLongName')
-    expect(_.camelize('what_about_this')).toBe('WhatAboutThis')
+    expect(_.camelize('abc')).toBe('abc')
+    expect(_.camelize('some-long-name')).toBe('someLongName')
+    expect(_.camelize('what_about_this')).toBe('whatAboutThis')
+    expect(_.camelize('abc', true)).toBe('Abc')
+    expect(_.camelize('some-long-name', true)).toBe('SomeLongName')
+    expect(_.camelize('what_about_this', true)).toBe('WhatAboutThis')
   })
 
   it('bind', function () {