VUE 官方文档上有很明确的解释:
单向数据流,所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。
所以如果破坏了单向数据流,当应用复杂时,debug 的成本会非常高!!
在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。
那如果修改了,vue 是如何监控到属性并给出警告的?
在 vue 底层,做了一个类似全局标记 Flag;它的实现原理,还是 Object.defineProperty()API;
proxy.js
const sharedPropertyDefinition = { enumerable: true, // 可枚举 configurable: true // 是否可以被修改 被delete}; export default function proxy(target, temp, key) { sharedPropertyDefinition.get = function proxyGetter() { return temp[key]; }; sharedPropertyDefinition.set = function proxySetter(val) { temp[key] = val; if (!window.isUpdatingChildComponent) { console.error(`不可以直接更改: ${key}`); } window.isUpdatingChildComponent = false; }; Object.defineProperty(target, key, sharedPropertyDefinition);}
复制代码
window.isUpdatingChildComponent = false; 相当于一个 Flag; 只有当在父组件中修改传递给子组件的 Prop 值的时候,才会被赋值为 true; 在子组件 proxy.vue 中代理父组件传递的 Prop 值; 使用 this.$forceUpdate(); 强制更新; 这时候,触发代理中的 setter;提示不可以在子组件中直接修改父组件传递的 Prop 值的警告;
组件 proxy.vue:
<template> <div> info: {{ info }} <input :value="info.name" @input="handleChange" /> </div></template> <script> import proxy from "./proxy"; export default { props: { info: Object }, created() { this.temp = { name: "" }; Object.keys(this.temp).forEach(key => { proxy(this.info, this.temp, key); }); }, methods: { handleChange(e) { this.info.name = e.target.value; this.$forceUpdate(); //this.$emit("change", e.target.value); } } };</script>
复制代码
评论