Vue 子组件双向绑定父组件数据对象内部多个属性,应该用什么方式实现?

2022-10-29 11:09:10 +08:00
 ignor

假设父组件数据对象 parentData 的结构为:

{
  a: xxx,
  b: yyy,
(后续会添加其他属性)
}

现在需要写一个可以编辑 parentData 的 component ,能像这样使用:

<EditorComponent v-model:parent-data="parentData"/>

在 EditorComponent 里,有两个 input 可以修改 a 、b 这两个属性。由于子组件不能直接修改父组件的数据,emit update 又只能对 parentData 做整块的赋值,所以目前的思路如下

先在 EditorComponent 内部复制一份 dataCopy:

data: {
  dataCopy = null
},
watch: {
  parentData: {
    deep: true,
    handler: function (val) {
      this.dataCopy = val
    }
  }
}

然后有两种处理方式:

1.
两个 input 绑定 dataCopy 的数据:

<input v-model="dataCopy.a"/>
<input v-model="dataCopy.b"/>

这样的话,如果要更新 parentData ,得在 dataCopy 上加一个 watcher ,然后

this.$emit('update:parentData', val)

但这似乎是不可取的,会造成来回无限更新

2.
把 input 的 v-model 拆开,加两个方法 updateA 、updateB:

<input :value="dataCopy.a" @input="updateA"/>
<input :value="dataCopy.b" @input="updateB"/>

然后在每个 update 里把 event 的值先赋给 dataCopy ,再

this.$emit('update:parentData', this.dataCopy)

这样属性一多就很麻烦很臃肿了

所以实现这样一个 EditorComponent 的规范思路应该是怎样的?(只看了基础教学就上手做了,不知道是否漏掉了什么重要概念……)

2708 次点击
所在节点    Vue.js
37 条回复
cuicuiv5
2022-10-29 14:06:54 +08:00
用 vuex
ignor
2022-10-29 14:30:09 +08:00
@leadfast 你这里 myData=props.parent ,似乎不会对 parent 的变化做出响应,所以没有死循环,得用两个 watcher 才能实现双向的响应吧
ignor
2022-10-29 14:33:12 +08:00
@Manweill 第一次尝试响应式框架,为了好上手选了 Vue ,所以这是……踩了坑了? react 是怎么规避这种问题的呢?
ignor
2022-10-29 14:35:50 +08:00
@cuicuiv5 这是不是有些重了…
ignor
2022-10-29 14:40:27 +08:00
@leadfast 补充一下,是对父组件里 parentData 这个对象的改变没有响应
ignor
2022-10-29 14:58:23 +08:00
@ignor #22 刚才又试了下,原来是因为在 watcher 里对新值做了改动才导致死循环……没事了
Manweill
2022-10-29 15:15:01 +08:00
@ignor react,,,没有这问题,react 基本是单向数据流模式
Garwih
2022-10-29 15:15:04 +08:00
正确的方法是用 computed ,get 的时候 return parentData ,set 的时候 this.$emit('update:parentData', value)。
并不需要 watch 。
dog82
2022-10-29 15:56:31 +08:00
我建议 vuex
ShayneWang
2022-10-29 16:01:16 +08:00
chenzhq2
2022-10-29 16:30:08 +08:00
1. 使用 slot 实现
2. 使用一个状态管理工具

为了做到不直接修改对象类型的 prop ,搞一堆 emit 和 watch ,我觉得挺闹心的。
vanillacloud
2022-10-29 20:57:32 +08:00
是否会觉得你的 model 在设计上就跟 Vue 的理念有所不同,导致做起来觉得各种麻烦?

我觉得思考一下「 Vue 建议怎么做这样的事」比较好。就像刚才你问「 react 怎么处理这类问题」,别人会说「 react 一般单向,没这个问题」。

有没有可能 Vue 其实也是这个答案?

我不是 expert ,但一般做的时候都是 #28 @Garwih 那样的处理方式。这似乎也是 Vue document 的方法。有什么情况是不能这样解决的吗?

当你觉得你的情况很复杂的时候,是时候回头想一想 data model / structure 的设计。
ignor
2022-10-29 21:14:40 +08:00
@vanillacloud #28 的问题我在#8 已经提到了,主楼的问题在#26 也解决了,主楼里方案 1 的做法其实可行,是我在 watcher 里加了赋值导致的死循环
kevin1
2022-10-29 21:57:35 +08:00
子组件维护自己的 input ,change 事件触发的时候拿到 value ,$emit 通知父组件(传递要修改的 key 和 value )直接修改 parentData 对应的 key ?
ignor
2022-10-29 23:11:12 +08:00
@kevin1 我帖子里没提到,a b 这些属性内部的结构也是不确定的,例如 a 可能是由数组构成的一串 input ,你的这个办法似乎需要针对不同的结构写不同的 emit
cjd6568358
2022-10-30 01:34:34 +08:00
v-bind.sync?
encro
2022-10-30 09:37:15 +08:00
找到现实中一个类似的功能,然后看它怎么实现的,研究 2-3 个后,思考下他们的适用场景,选择合适的。

这个有非常多类似案例,比如嵌套 select ,modal, richtext editor 。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/890909

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX