最近 Ant Design Vue 作者 - 唐金州,在某平台开课了,在整个课程中系统的讲述了Vue的开发实战。在第八讲中介绍了Vue双向绑定的问题,这里我整理一些资料客观的分析一下 Vue数据响应原理到底是不是双向绑定


很多同学在理解 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函数改为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))])])
}
复制代码

最终转化为:

<inputv-bind:value="message"v-on:input="message=$event.target.value">
复制代码

动态绑定了 inputvalue 指向了 messgae 变量,并且在触发 input 事件的时候去动态把 message 设置为目标值,这样实际上就完成了数据双向绑定了,所以说 v-model 实际上就是语法糖。

ustbhuangyi 在Vue.js 技术揭秘中也详细的介绍v-model在组件中的实现原理,这里就不过多的陈述了。

总结

我们了解到 v-model 是 Vue 双向绑定的真正实现,但本质上就是一种语法糖,它即可以支持原生表单元素,也可以支持自定义组件。在组件的实现中,我们是可以配置子组件接收的 prop 名称,以及派发的事件名称。

最后有一个问题 v-model.sync 都可以实现数据双向绑定的效果,那到底用哪种更合理呢?欢迎回复阐述你的观点。

祝学习进步

邓文斌

2019年3月21日

转载于:https://juejin.im/post/5c9351135188252d9b376152

【重学Vue】数据响应原理真的是双向绑定吗?相关推荐

  1. Vue源码解读一:Vue数据响应式原理

    这方面的文章很多,但是我感觉很多写的比较抽象,本文会通过举例更详细的解释.(此文面向的Vue新手们,如果你是个大牛,看到这篇文章就可以点个赞,关掉页面了.)通过阅读这篇文章,你将了解到: 1.Vue数 ...

  2. 彻底理解Vue数据响应式原理

    彻底理解Vue数据响应式原理 当创建了一个实例后,通过将数据传入实例的data属性中,会将数据进行劫持,实现响应式,也就是说当这些数据发生变化时,对应的视图也会发生改变. const data = { ...

  3. Vue数据响应式原理:Observe、Dep、Watcher

    在Vue中,数据响应式Observe是通过使用闭包来实现的.简单来说,就是利用了JavaScript中函数作用域链的特性,将数据对象以及相关的数据操作函数保存在闭包内部,从而达到对数据的监听.更新等操 ...

  4. vue process.env获取不到_从文档开始,重学vue(下)源码级别

    此篇文章主要是从应用及源码层面讲解vue部分常用api,阅读起来可能略有难度,新手可以看<从文档开始,重学vue(上)> 示例代码均在vue-cli3中完成 Vue.extend() 可以 ...

  5. php可以实现响应式吗,怎么实现Vue数据响应式

    这次给大家带来怎么实现Vue数据响应式,实现Vue数据响应式的注意事项有哪些,下面就是实战案例,一起来看一下. 前言 Vue的数据响应主要是依赖了Object.defineProperty(),那么整 ...

  6. Vue数据响应式与双向数据绑定原理区分

    很多小伙伴搞不清楚数据响应式与双向数据绑定这两个原理,还有人自然的认为它们两者是相同的,接下来我们来看看它们二者的区分吧! 数据响应式是Vue的核心特性之一,而双向数据绑定是通过指令或修饰符实现的一种 ...

  7. 理解Vue深度响应原理

    Vue核心原理之数据的深度响应 1.问题的引入 为什么点击下面的button界面会出现自增? <div id="example-2"> <simple-count ...

  8. vue源码深入解读MVVM(视图模板引擎),你真的了解双向绑定(v-model),数据劫持(observe),发布订阅模式吗?带你手鲁mvvm引擎。源码奉上(详细注释)!

    文章目录 #1.vue的强大之处不必细说,vue的核心v-model的实现原理,网上都有很多.但是真正自己实现双向绑定,mvvm的源码却几乎没见过. #1.2本人根据源码的解读,理解,以及借鉴网上的视 ...

  9. 探讨Vue 数据监测原理-第四节-Vue.Set() API 介绍应用

    文章目录 探讨一下Vue 数据监测的原理 本次探讨共的第四个章节 第四节:Vue.Set() API 介绍应用 1. 案例 2. 需求1 给学生添加性别 2.1 获取对象添加性别 2.2. 添加响应式 ...

最新文章

  1. matlab中的mkdir函数_科学网—Matlab中计算函数运行时间的三种方法及判断新建文件夹 - 张伟的博文...
  2. 前端、云与人工智能的碰撞 | GDG广州
  3. Oracle的REGEXP_INSTR再mysql中实现
  4. 书多嚼不烂,看书的方法
  5. [C++调试笔记]求电势posi.cpp
  6. mysql合并表中的数据
  7. 微型计算机c240,PC微机原理实验.doc
  8. 手把手教你做产品经理1.0
  9. Java实验输出希腊字母表
  10. 除了专业技能,Web前端工程师需要具备哪些基本素质?
  11. 洛谷P3376【模板】网络最大流
  12. 简单线性回归R和Python预测身高体重国内生产总值二氧化碳排放量
  13. 全网最全斗音短视频新老账号起号技巧
  14. arduino上传项目总是出错,串口通信或TX/RX显示上传项目出错
  15. 国内CDN加速哪个好?
  16. Python遍历目录下的文件(os.walk 、os.listdir的用法)
  17. Springboot +AOP日志系统
  18. CAD编辑器中CAD线型怎么修改?
  19. iOS JS与OC交互
  20. AD18中安装自己绘制的原件库

热门文章

  1. 9岁去读博!全球最年轻的大学毕业生火了:4岁上小学,8岁进入荷兰“中科大”,智商145...
  2. 微软10亿美元投资的OpenAI如何组织员工学习新知识?这里有一份课程与书籍清单...
  3. 2.pandas数据清洗
  4. Windows 7安装MySQL最后一步提示错误“mysql 终结点映射器中没有更多的终结点可用的” 解决方法...
  5. 了解一下MongoDB中的写关注(write concern)
  6. C# 利用WMI对象获取物理内存和可用内存大小
  7. 4安装-企业级 Hyper-v 群集部署实验方案
  8. 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag
  9. C51汇编伪指令 CSEG DSEG
  10. SecureCRT错误:The client has