18910140161

Vuejs 3里一个关于自定义组件watch v-model的困惑

2021-10-20 18:03:22

508

现在我有这么一个自定义组件,v-model接受多种数据类型,常见的整数、字符串、对象(json) 等等组件内部会用一个watch对这个modelValue的值进行处理,得到一个数据,同时自定义组件内部有个表单可以对这个数据进行修改,最后通过update:modelValue更新v-model的值,更新以后v-model的值一定是字符串,而且这个字符串带有随机部分,类似时间戳(所以导致和原v-model的值一定不同)。


顺晟科技:

父组件的 yourModel 也会自动响应。父组件也不需要watch。

同时自定义组件里面有个表单会对这个test的属性进行修改(除了data还有其他属性),所以当表单修改以后,同样也会调用context.emit(‘update:modelValue’,test);来更新modelValue的值。

所以,你的思维被固化了,被误导了。写程序最重要的是啥?灵活!

然后你可以把 _model 当做子组件的 data 来使用。不需要watch,也不需要emit。

还有个办法,就是在update:modelValue之前把更新的值保存起来,watch的回调会首先把modelValue的新值跟保存的值比较,如果完全相同就直接返回,也能达到类似的效果。

非常感谢您的回答,可能我主题里没有描述清楚,简单来说,我没办法直接用props的响应式特性。因为我组件对这个model值没有直接用,而是先判断其不同类型,然后根据不同类型把modelValue的值进行处理,处理后的值才是我实际渲染到模板或者表单修改的值,我用伪代码写吧。下面是setup()里:const test = reactive({})const temp = props.modelValueswitch(typeof(temp)){case ‘string’:test.data=func1(temp)+时间戳();break;case ‘object’:test.data=reactive(func2(temp));break;}context.emit(‘update:modelValue’,test);

但是感觉这样很乱,新增了一个额外变量,不知道有没有更优雅的办法。我感觉vue3应该有已有的工具来解决这个问题,只是我没在文档里找到?

上述对组件的描述是我简化以后的描述,其实类似场景应该很常见,比如一个自定义时间表单,v-model可以接受各种格式的时间,可能是Date可能是时间戳,也可能是 字符串,组件内部可能通过watch或者computed把初始值归化成固定格式的值,而且这个值会随着时间1秒1秒地变化,所以会同时触发update:modelValue更新,然后又触发了watch或者computed,进入死循环。

我现在的做法就是,用一个变量isUpdatedByMyself作为标记,触发update:modelValue之前把这个标记设置为true,然后watch modelValue的回调函数里,检测这个标记如果为true就把它再设置为false,然后不做任何操作。这样就避免了陷入死循环。

子组件

是你被误导了。正确的做法是这样:(会被说成是错误的,但是其实才是正解)

好了,搞定。

我不知道我表述清楚没。简单来说就是,有没有一种办法,让watch监听modelValue的时候,如果modelValue的更新是因为组件自身触发update:modelValue而导致的modelValue更新,就忽略。

我这个实际组件要复杂得多,可能有人会说这种场景根本不适合v-model,而应该用普通事件来处理,但实际情况不得不让我用v-model,具体展开就很复杂了。

====================================================

vue3:双向绑定 vs 单向数据流 - 简书 具体原理

父组件

父组件直接传递一个对象(reactive)进来,然后子组件直接使用这个对象(reactive)。其他的我也不多说了。基础知识,然后灵活使用,不要僵化

所以您说的用一个中间变量来保存,并没有影响到结果。如果不用watch,就没办法做到 需求1 ,而用了watch 就会导致死循环。

父组件定义一个reactive ,然后子组件接收

现在有个问题,更新v-model值以后会触发watch,然后watch的回调函数又会经过一系列复杂的逻辑,然后触发update:modelValue更新v-model值,然后就进入死循环了~

然后要做到以下需求:1.父组件修改了modelValue的值以后,我的自定义组件能够响应这个修改,也就是要把上面的代码执行一遍。2.我的自定义组件会加工modelValue的值,并且通知父组件更新,也就是使用update:modelValue事件。

相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航