VueUse如何封装v-model

介绍

v-model 可以在组件上使用以实现双向绑定, v-model 本质上是语法糖,经过模版编译器后会对 v-model 转换为:

上面是表单元素 v-model 的转换,而自定义组件会转换为:

那么在自定义组件 <CustomInput> 中实现 v-model 需要:

  • 获取 prop 中的 modelValue
  • 值改变需要触发 update:modelValue 自定义事件

为了方便开发,VueUse 提供了 useVModel 来实现自定义组件的 v-model

useVModel

v-model 的封装实现

使用

配置项

源码

watchcomputed 方式实现 v-model

源码中 passivetrue 采用了 watch 的方式实现 v-model,false 采用 computed,两者有什么区别呢?

watch 实现方式:

这种方式是在组件内部声明了一个 currentValue 变量,通过监听 props.modelValue 赋值给 currentValue 变量,currentValue 值改变触发 update:modelValue 自定义事件。这种方式的优点组件内部有个自己的状态,不会受父组件的传值影响。但相对 computed 的方式复杂了一点。

props.modelValue 值改变时会触发监听执行 currentValue.value 值改变又会触发 currentValue 的监听函数,但不需要触发update:modelValue ,因此需要添加 if (val === props.modelValue) return

这里我们可以将 watch 替换成 watchEffect,让代码更简洁:

这里需要注意的是 currentValue 的监听不能换成 watchEffect,因为换了之后就是 props.modelValuecurrentValue 其中一个值改变就会触发执行。

代码可以进一步优化:不用 v-model 绑定 currentValue

:value@input 可以更加灵活的在触发 update:modelValue 之前做一些逻辑处理。也避免了 currentValue的监听多次触发的情况。

computed 的实现方式:

这种方式相对简单,但有个问题,如果引用该组件时没有绑定 v-model 时,组件中 input 的 v-model 也就会失效。在依赖v-model 绑定的变量做一些处理时会受影响。

第二个问题是如果 v-model 绑定的是一个对象,当对象中的属性值改变时不会触发 computed 的 set 方法:

上面例子对象的属性值也会随着输入的内容而改变,不过这个改变的原因的不是因为执行了 set 方法,而是因为对象是引用类型。我们在实际开发中会尽量避免这种情况,因为这样会导致组件间的数据流变复杂,很难跟踪位数据,因此开发中尽量保持单向数据传递。有两种方式解决:

一是为 modelValue 对象的每个属性都声明一个 computed,这种就比较繁琐。

还有一种方式是 get 方法返回一个 Proxy 对象

这种方式每次执行 get 方法会重新实例化一个 Proxy 对象,因此就不会有上面对象引用而修改了父级组件传来的对象。并且 Proxy 对象属性值改变时会触发 set 方法而执行 emits("update:modelValue"),从而实现双向绑定。但个人认为这不是一个好的方案:

第一:这里并没有兼容 modelValue 是值类型的时候,也就说在 computed get 方法中要加个判断处理值类型和对象两个分支逻辑。

第二:computed get 方法每次都会新建一个 Proxy 对象,当然这个对性能的影响很小。

第三:Proxy 并不是一点缺点都没有的,在数组的处理上还是有很多需要注意的地方。

总结

v-model 的实现可以采用 watchcomputed 两种方式,computed 的方式更简单,在特定场景下会有问题,大部分场景不会有问题,因此 VueUse 默认采用 computed 的方式。

相关推荐
铁皮饭盒2 分钟前
用bunjs代码讲解XSS/CSRF/SQL注入/DDos等10种前后端安全防护
前端·后端
hhb_6187 分钟前
TypeScript泛型实战:企业级请求封装全解析
javascript·ubuntu·typescript
琹箐10 分钟前
chrome 插件下载安装;Manifest file is missing or unreadable
前端·chrome
云飞云共享云桌面10 分钟前
面向机械研发:双服务器架构搭配云飞云运行 SolidWorks 方案详解
运维·服务器·前端·网络·架构·制造
乐兮创想 小林24 分钟前
B2B 内容营销的工程化运营:从内容矩阵建模到 SEO/GEO 联动的完整体系
前端·线性代数·矩阵·网站建设·北京网站建设公司
2501_9400417424 分钟前
全栈开发提速指南:可以直接用的项目生成提示词
前端·prompt
BomanGe226 分钟前
NSK直线导轨LH55EL与NH55EM替代指南
前端·javascript·数据库·经验分享·规格说明书
云水一下26 分钟前
Vue.js从零到精通系列(四):前端路由与Vue Router——打造多页单页应用
前端·javascript·vue.js
糯米导航28 分钟前
浏览器解析HTML头部的底层逻辑:从字节流到渲染树的关键一步
前端·html
baozj29 分钟前
把徒步轨迹做成 3D 地形模型:开源工具「印迹 TrailPrint 3D」
前端·vue.js·github