关于vue的单向数据流问题?
当一个组件接收一个“引用类型”的状态, 如果只是修改这个状态的属性(不触发这个对象的setter), 这算不算违反了单向数据流?
<template>
<input v-model="user.name">
</template>
<script>
{
props:['user']
}
</script>
个人偏向于认为这违反了“单向数据流”. 因为本质上,它还是直接更改了共享状态,而不是通过emit或commit.
不过vue又没有去显示的阻止这种行为,这让我很疑惑,官方到底赞不赞同这种做法?
我知道官方文档,举了例子建议使用data或computed,但是那个例子的共享状态是值类型.
而状态是引用类型的情况,即使 用一个data来接收也只是引用的复制, 还是会更改相同的数据(对象所在的堆区).
我能想到的一种比较较真且能够减轻本人的强迫症(钻牛角尖)的办法是:
<template>
<input v-model="mutableUser.name" />
</template>
<script>
import { cloneDeep } from "lodash-es";
export default {
props: ["user"],
data() {
return {
//1.深拷贝 共享状态
mutableUser: cloneDeep(this.user)
};
},
created() {
//2.递归的监听mutableUser的所有属性,
this.$watch(
"mutableUser",
function() { this.$emit("update:user", this.mutableUser) },
{ deep: true }
);
}
};
</script>
虽然按照死理(必须使用emit或commit修改共享状态),这样应该是符合的.但是,总感觉哪里怪怪的??
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我觉得你后面那种写法相对这个情景下完全没必要,除非父组件每次
update
都执行一次cloneDeep
这明显有效率问题并不是个好主意,否则emit
触发一次之后user
跟mutableUser
马上又指向同一个对象。你可以试下不用
v-model
语法糖,而用原生方法来处理你若不想用难看的
$event.target.value
也可以多写几行代码借助计算属性当然父组件必须监听这个事件来触发更新
这样是否可以适度减轻你对单向数据流的执念?