2
0
Эх сурвалжийг харах

initialize props properly

Evan You 11 жил өмнө
parent
commit
8f6dfce54e

+ 13 - 10
src/compiler/compile.js

@@ -456,18 +456,18 @@ function compileProps (el, propDescriptors) {
       )
     }
     value = el.getAttribute(name)
+    // create a prop descriptor
+    prop = {
+      name: name,
+      raw: value,
+      path: path,
+      assertions: assertions,
+      mode: propBindingModes.ONE_WAY
+    }
     if (value !== null) {
       // important so that this doesn't get compiled
       // again as a normal attribute binding
       el.removeAttribute(name)
-      // create a prop descriptor
-      prop = {
-        name: name,
-        raw: value,
-        path: path,
-        assertions: assertions,
-        mode: propBindingModes.ONE_WAY
-      }
       var tokens = textParser.parse(value)
       if (tokens) {
         if (el && el.nodeType === 1) {
@@ -495,10 +495,10 @@ function compileProps (el, propDescriptors) {
           }
         }
       }
-      props.push(prop)
     } else if (assertions && assertions.required) {
       _.warn('Missing required prop: ' + name)
     }
+    props.push(prop)
   }
   return makePropsLinkFn(props)
 }
@@ -517,7 +517,10 @@ function makePropsLinkFn (props) {
     while (i--) {
       prop = props[i]
       path = prop.path
-      if (prop.dynamic) {
+      if (prop.raw === null) {
+        // initialize undefined prop
+        vm._data[path] = undefined
+      } else if (prop.dynamic) {
         // dynamic prop
         if (vm.$parent) {
           if (prop.mode === propBindingModes.ONE_TIME) {

+ 9 - 1
src/instance/scope.js

@@ -49,7 +49,15 @@ exports._initData = function () {
   var optionsDataFn = this.$options.data
   var optionsData = optionsDataFn && optionsDataFn()
   if (optionsData) {
-    this._data = _.extend(optionsData, propsData)
+    this._data = optionsData
+    for (var prop in propsData) {
+      if (
+        !optionsData.hasOwnProperty(prop) ||
+        propsData[prop] !== undefined
+      ) {
+        optionsData[prop] = propsData[prop]
+      }
+    }
   }
   var data = this._data
   // proxy data on instance

+ 2 - 1
test/unit/specs/compiler/compile_spec.js

@@ -204,11 +204,12 @@ if (_.inBrowser) {
       expect(args[3]).toBe(def)
       // literal and one time should've been set on the _data
       // and numbers should be casted
-      expect(Object.keys(vm._data).length).toBe(4)
+      expect(Object.keys(vm._data).length).toBe(5)
       expect(vm._data.a).toBe(1)
       expect(vm._data.someOtherAttr).toBe(2)
       expect(vm._data.onetime).toBe('from parent: a')
       expect(vm._data.booleanLiteral).toBe('from parent: true')
+      expect(vm._data.camelCase).toBeUndefined()
       // camelCase should've warn
       expect(hasWarned(_, 'using camelCase')).toBe(true)
     })

+ 32 - 0
test/unit/specs/instance/scope_spec.js

@@ -33,6 +33,38 @@ describe('Instance Scope', function () {
 
   describe('$data', function () {
 
+    it('should initialize props', function () {
+      var vm = new Vue({
+        el: document.createElement('div'),
+        props: ['c']
+      })
+      expect(vm.hasOwnProperty('c')).toBe(true)
+    })
+
+    it('should use default prop value if prop not provided', function () {
+      var vm = new Vue({
+        el: document.createElement('div'),
+        props: ['c'],
+        data: {
+          c: 1
+        }
+      })
+      expect(vm.c).toBe(1)
+    })
+
+    it('prop should overwrite default value', function () {
+      var el = document.createElement('div')
+      el.setAttribute('c', '2')
+      var vm = new Vue({
+        el: el,
+        props: ['c'],
+        data: {
+          c: 1
+        }
+      })
+      expect(vm.c).toBe(2)
+    })
+
     it('replace $data', function () {
       var vm = new Vue({
         data: {