网站首页 > 技术文章 正文
很多同学在理解 Vue 的时候都把 Vue 的数据响应原理理解为双向绑定,但实际上这是不准确的,我们之前提到的数据响应,都是通过数据的改变去驱动 DOM 视图的变化,而双向绑定除了数据驱动 DOM 外, DOM 的变化反过来影响数据,是一个双向关系,在 Vue 中,我们可以通过 v-model 来实现双向绑定。
在Vue中体现出双向绑定作用的方式有两种,在分析之前我们先介绍这两种使用方式有什么区别。
1)v-model 属性
2).sync 修饰符
v-model
2.2.0+ 新增
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目的。model 选项可以用来避免这样的冲突:
ChildBox.vue
<template> <input type="checkbox" :checked="checked" @change="$emit('change', $event.target.checked)"/> </template> <script> export default { model: { prop: 'checked', event: 'change' }, props: { checked: Boolean } } </script>
Index.vue
<template> <div> <ChildBox v-model="val"/> <!-- 解析后 --> <ChildBox :value="val" @change="data => (val = data)"/> </div> </template>
分析一下上面的代码。ChildBox.vue文件对checkbox做了简单的封装,提供了checked参数。Index.vue文件为父组件,引用了ChildBox作为自己的子组件,这里需要注意一下。val值的绑定使用的v-model而并不是v-bind:checkbox。一开始我们有说到双向绑定方式有两种一种是v-model,另一种是.sync(这个后面讲)。如果使用v-model,子组件的props应该设置value值,而向上传递应该为$emit('input')才对。所以这里还有一个重点,model的作用。
model
2.2.0 新增
允许一个自定义组件在使用 v-model 时定制 prop 和 event。默认情况下,一个组件上的 v-model 会把 value 用作 prop 且把 input 用作 event,但是一些输入类型比如单选框和复选框按钮可能想使用 value prop 来达到不同的目的。使用 model 选项可以回避这些情况产生的冲突。
.sync 修饰符
2.3.0+ 新增
在有些情况下,我们可能需要对一个 prop 进行“双向绑定”。不幸的是,真正的双向绑定会带来维护上的问题,因为子组件可以修改父组件,且在父组件和子组件都没有明显的改动来源。
这也是为什么我们推荐以 update:myPropName 的模式触发事件取而代之。举个例子,在一个包含 title prop 的假设的组件中,我们可以用以下方法表达对其赋新值的意图:
ChildBox.vue
<template> <input type="checkbox" :checked="checked" @change="$emit('update:checked', $event.target.checked)"/> </template> <script> export default { props: { checked: Boolean } } </script>
Index.vue
<template> <div> <ChildBox :checked.sync="val"/> <!-- 解析后 --> <ChildBox :checked="val" @update:checked="data => (val = data)"/> </div> </template>
分析一下上面的代码有什么变化,父组件v-model被 :checked.sync替换掉。子组件因不适用v-model,所以不需要model配置。change函数改为$emit'update:checkde',$event.target.checked)。
v-model源码分析
借助ustbhuangyi Vue.js技术揭秘。这里只做总结比对,详细分析过程可查看链接。
以下面代码为例:
let vm = new Vue({ el: '#app', template: '<div>' + '<input v-model="message" placeholder="edit me">' + '<p>Message is: {{ message }}</p>' + '</div>', data() { return { message: '' } } })
在 input 元素上设置了 v-model 属性,绑定了 message,当我们在 input 上输入内容时,message 也会同时发生变化。
源码generate函数:
function generate ( ast, options ) { var state = new CodegenState(options); var code = ast ? genElement(ast, state) : '_c("div")'; return { render: ("with(this){return " + code + "}"), staticRenderFns: state.staticRenderFns } }
对我们的例子而言,最终生成的 render 代码如下:
with(this) { return _c('div',[_c('input',{ directives:[{ name:"model", rawName:"v-model", value:(message), expression:"message" }], attrs:{"placeholder":"edit me"}, domProps:{"value":(message)}, on:{"input":function($event){ if($event.target.composing) return; message=$event.target.value }}}),_c('p',[_v("Message is: "+_s(message))]) ]) }
最终转化为:
<input v-bind:value="message" v-on:input="message=$event.target.value">
动态绑定了 input 的 value 指向了 messgae 变量,并且在触发 input 事件的时候去动态把 message 设置为目标值,这样实际上就完成了数据双向绑定了,所以说 v-model 实际上就是语法糖。
ustbhuangyi 在Vue.js 技术揭秘中也详细的介绍v-model在组件中的实现原理,这里就不过多的陈述了。
总结
我们了解到 v-model 是 Vue 双向绑定的真正实现,但本质上就是一种语法糖,它即可以支持原生表单元素,也可以支持自定义组件。在组件的实现中,我们是可以配置子组件接收的 prop 名称,以及派发的事件名称。
最后有一个问题 v-model 和 .sync 都可以实现数据双向绑定的效果,那到底用哪种更合理呢?欢迎回复阐述你的观点。
最后
以下是总结出来最全前端框架视频,包含: javascript/vue/react/angualrde/express/koa/webpack 等学习资料。
【领取方式】
关注头条 前端全栈架构丶第一时间获取最新前端资讯学习
手机用户可私信关键词 【前端】即可获取全栈工程师路线和学习资料!
猜你喜欢
- 2024-10-12 学习Vue的数据绑定语法,实现动态的用户界面(四)
- 2024-10-12 Vue前端框架:绑定单个复选框。 vue复选框默认选中
- 2024-10-12 vue2响应式原理 vue2.0响应式原理
- 2024-10-12 vue数据绑定语法 vue样式绑定语法
- 2024-10-12 【Vue】第5章 Vue数据绑定和计算属性详解
- 2024-10-12 Vue数据及事件绑定、filter过滤器
- 2024-10-12 Vue开发:组件绑定自定义事件及其应用
- 2024-10-12 vue.js实战之表单绑定-单选按钮 vue表格单选
- 2024-10-12 跟神一起学前端-初识vue、数据绑定
- 2024-10-12 vue.js 动态绑定class的几种方式 vue动态绑定类
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)