Kaynağa Gözat

fix(props): should not unwrap props that are raw refs

close #12930
Evan You 2 yıl önce
ebeveyn
işleme
08382f0080

+ 18 - 12
src/core/instance/state.ts

@@ -95,19 +95,25 @@ function initProps(vm: Component, propsOptions: Object) {
           vm
         )
       }
-      defineReactive(props, key, value, () => {
-        if (!isRoot && !isUpdatingChildComponent) {
-          warn(
-            `Avoid mutating a prop directly since the value will be ` +
-              `overwritten whenever the parent component re-renders. ` +
-              `Instead, use a data or computed property based on the prop's ` +
-              `value. Prop being mutated: "${key}"`,
-            vm
-          )
-        }
-      })
+      defineReactive(
+        props,
+        key,
+        value,
+        () => {
+          if (!isRoot && !isUpdatingChildComponent) {
+            warn(
+              `Avoid mutating a prop directly since the value will be ` +
+                `overwritten whenever the parent component re-renders. ` +
+                `Instead, use a data or computed property based on the prop's ` +
+                `value. Prop being mutated: "${key}"`,
+              vm
+            )
+          }
+        },
+        true
+      )
     } else {
-      defineReactive(props, key, value)
+      defineReactive(props, key, value, undefined, true)
     }
     // static props are already proxied on the component's prototype
     // during Vue.extend(). We only need to proxy props defined at

+ 18 - 0
test/unit/features/options/props.spec.ts

@@ -1,6 +1,7 @@
 import Vue from 'vue'
 import { hasSymbol } from 'core/util/env'
 import testObjectOption from '../../../helpers/test-object-option'
+import { ref } from 'v3'
 
 describe('Options props', () => {
   testObjectOption('props')
@@ -593,4 +594,21 @@ describe('Options props', () => {
       'Invalid prop type: "String" is not a constructor'
     ).toHaveBeenWarned()
   })
+
+  // #12930
+  it('should not unwrap prop values that are raw refs', () => {
+    let val
+    const Comp = {
+      props: ['msg'],
+      created() {
+        val = this.msg
+      },
+      render() {}
+    }
+    const r = ref()
+    new Vue({
+      render: h => h(Comp, { props: { msg: r }})
+    }).$mount()
+    expect(val).toBe(r)
+  })
 })