关于vue的单向数据流问题?

发布于 2022-09-11 21:56:06 字数 1053 浏览 19 评论 0

当一个组件接收一个“引用类型”的状态, 如果只是修改这个状态的属性(不触发这个对象的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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

提笔书几行 2022-09-18 21:56:06

我觉得你后面那种写法相对这个情景下完全没必要,除非父组件每次update都执行一次cloneDeep 这明显有效率问题并不是个好主意,否则emit触发一次之后usermutableUser马上又指向同一个对象。

你可以试下不用v-model语法糖,而用原生方法来处理

<input :value="user.name" @input="$emit('update-name', $event.target.value)">

你若不想用难看的$event.target.value也可以多写几行代码借助计算属性

<template>
  <input v-model="userName">
</template>
<script>
  export default {
    props: ['user'],
    computed: {
      userName:{
        get(){
          return this.user.name
        },
        set(name){
          this.$emit('update-name', name)
        }
      }
    },

当然父组件必须监听这个事件来触发更新

<ChildInput
    :user="user"
    @update-name="name => user.name = name"
>
</ChildInput>

这样是否可以适度减轻你对单向数据流的执念?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文