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

prop bindings should inherit parent reactivity to allow local mutation (fix #2549)

Evan You 10 лет назад
Родитель
Сommit
a6b9454c19
2 измененных файлов с 34 добавлено и 1 удалено
  1. 8 1
      src/compiler/compile-props.js
  2. 26 0
      test/unit/specs/directives/internal/prop_spec.js

+ 8 - 1
src/compiler/compile-props.js

@@ -226,7 +226,14 @@ export function initProp (vm, prop, value) {
     value = getPropDefaultValue(vm, prop.options)
   }
   if (assertProp(prop, value)) {
-    var doNotObserve = !prop.dynamic || isSimplePath(prop.raw)
+    var doNotObserve =
+      // if the passed down prop was already converted, then
+      // subsequent sets should also be converted, because the user
+      // may mutate the prop binding in the child component (#2549)
+      !(value && value.__ob__) &&
+      // otherwise we can skip observation for props that are either
+      // literal or points to a simple path (non-derived values)
+      (!prop.dynamic || isSimplePath(prop.raw))
     defineReactive(vm, key, value, doNotObserve)
   }
 }

+ 26 - 0
test/unit/specs/directives/internal/prop_spec.js

@@ -721,4 +721,30 @@ describe('prop', function () {
       done()
     })
   })
+
+  // #2549
+  it('mutating child prop binding should be reactive if parent value was reactive', function (done) {
+    var vm = new Vue({
+      el: el,
+      template: '<comp :list="list"></comp>',
+      data: {
+        list: [1, 2, 3]
+      },
+      components: {
+        comp: {
+          props: ['list'],
+          template: '<div v-for="i in list">{{ i }}</div>',
+          created: function () {
+            this.list = [2, 3, 4]
+          }
+        }
+      }
+    })
+    expect(vm.$el.textContent).toBe('234')
+    vm.$children[0].list.push(5)
+    Vue.nextTick(function () {
+      expect(vm.$el.textContent).toBe('2345')
+      done()
+    })
+  })
 })