Vue2.0实现组件数据的双向绑定问题


Posted in Javascript onMarch 06, 2018

通过上一节的学习,我们了解到了在Vue的组件中数据传递: prop 向下传递,事件向上传递 。意思是父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息。但Vue中, props 是单向数据绑定,虽然在Vue 1.0版本中,通过 .sync 能实现双向数据绑定。但 .sync 在几个版本中被移除,尽管在2.3版本重新引入 .sync 修饰符,可这次引入只是作为一个编译时的语法糖存在。如果直接使用 .sync 修饰符来做双向数据绑定,会报警告信息。那么我们如何在组件中实现双向数据绑定呢?这一节我们就来学习这方面的相关知识。

实现组件双向数据绑定

在上一节中最后的示例使用的是Vue 1.0版本中的 .sync 实现数据双向绑定。那我们先来看看抛弃 .sync 修饰符来实现组件双向数据绑定的工作: 通过Vue提供的机制,绕开直接修改 prop 来实现组件双向数据绑定 。

其思路大致是这样:

  • 在数据渲染时使用 prop 渲染数据
  • 将 prop 绑定到子组件自身的数据上,修改数据时修改自身数据来替代 prop
  • watch 子组件自身数据的改变,触发事件通知父组件更改绑定到 prop 的数据

这样做的好处是: 父组件数据改变时,不会修改存储 prop 的子组件数据,只是以子组件数据为媒介,完成对 prop 的双向修改 。

继续拿上一节的示例来举例,只不过接下来的示例,并没有使用 .sync 来实现双向数据绑定的效果。

修改的代码如下:

<div id="app">
 <div class="parent">
  <h3>父组件Parent数据</h3>
  <ul>
   <li>
    <label>姓名:</label>
    <span>{{ name }}</span>
    <input type="text" v-model="name" />
   </li>
   <li>
    <label>年龄:</label>
    <span>{{ age }}</span>
    <input type="number" v-model="age" />
   </li>
  </ul>
 </div>
 <child :my-name="name" :my-age="age" @update:my-name="val => name = val" @update:my-age="val => age = val"></child>
</div>
<template id="child">
 <div class="child">
  <h3>子组件child数据</h3>
  <ul>
   <li>
    <label>姓名</label>
    <span>{{ myName }}</span>
    <input type="text" v-model="childMyName" />
   </li>
   <li>
    <label>年龄</label>
    <span>{{ myAge }}</span>
    <input type="number" v-model="childMyAge" />
   </li>
  </ul>
 </div>
</template>

在上面的这个示例中,我们并没有使用 .sync 修饰符,但在调用子组件的时候使用了 @update :

<child :my-name="name" :my-age="age" @update:my-name="val => name = val" @update:my-age="val => age = val"></child>

子组件中渲染到HTML模板的数据是用的 prop 数据,但监听 input 是使用的子组件自身定义的数据作为 v-model 。这样一来就不会直接修改 prop 。简单来说, 一切 prop 的改变从本质上来说都由父组件完成 。JavaScript的代码如下:

let parent = new Vue({
 el: '#app',
 data () {
  return {
   name: 'w3cplus',
   age: 7
  }
 },
 components: {
  'child': {
   template: '#child',
   props: ['myName', 'myAge'],
   data () {
    return {
     childMyName: this.myName,
     childMyAge: this.myAge
    }
   },
   watch: {
    childMyName: function (val) {
     this.$emit('update:my-name', val)
    },
    childMyAge: function (val) {
     this.$emit('update:my-age', val)
    }
   }
  }
 }
})

最终效果如下:

上面的示例效果,不管是修改父组件的数据还是子组件的数据,都会相互影响:

Vue2.0实现组件数据的双向绑定问题 

因为子组件中 props 的 myName 和 myAge 不可写,所以在 data 中创建一个副本 childMyName 和 childMyAge 。初始值为 props 属性 myName 和 myAge 的值,同时在组件内所有需要调用 props 的地方调用 data 中的 childMyName 和 childMyAge 。

components: {
 'child': {
  template: '#child',
  props: ['myName', 'myAge'],
  data () {
   return {
    childMyName: this.myName,
    childMyAge: this.myAge
   }
  },
  ...
 }
}

接下来在子组件中通过 watch 来对 props 属性的 myName 和 myAge 进行监听。当 props 修改后对应 data 中的副本 childMyName 和 childMyAge 也要同步数据。

...
watch: {
 childMyName: function (val) {
  this.$emit('update:my-name', val)
 },
 childMyAge: function (val) {
  this.$emit('update:my-age', val)
 }
}
...

接下来要做的事情就是当组件内的 props 属性发生变化时,需要向组件外(父组件)发送通知,通知组件内属性变更,然后由外层(父组件)自己来决定是否变更他的数据。

接下来我们按上面的方案来改造上一节示例中的switch按钮。

至此,实现了组件内部数据与组件外部的数据的双向绑定,组件内外数据的同步。简而言之: 组件内部自已变了告诉外部,外部决定要不要变更 。

Vue2.0实现组件数据的双向绑定问题 

什么样的 props 适合做双向绑定

事实上,在Vue中,双向绑定的 props 是不利于组件间的数据状态管理,尤其是较为复杂的业务当中,因此在实际项目中应该尽量少用双向绑定,过于复杂的数据处理,建议使用 Vuex 。但很多时候又避免不了使用双向绑定。那么什么场景之下使用 props 来做双向绑定呢?

如果在你的项目中,同时满足下面的条件时,我们就可以考虑使用 props 来做双向绑定:

  • 组件内部需要修改 props
  • 组件需要可以由外部在运行时动态控制,而非单纯的初始化
  • 组件父部需要读取组件内的状态来进行处理

虽然上面的示例展示了我们怎么在Vue 2.0中实现 props 的双向绑定,但如果项目中有更多这样的双向绑定,那么就会让你做一些重复的事情,而且代码也很冗余,事情也会变得复杂。为了改变这样的现象,可以借助Vue的 mixin 来自动化处理 props 的双向绑定的需求。不过在这节中,我们不会学习这方面的知识,后面我们在学习 mixin 时,可地再回过头来实现这样的功能。

在Vue中除了上述介绍的组件通讯之外,还有其他一些方法,在下一节中,咱们将会继续学习这方面的知识。

总结

以上所述是小编给大家介绍的Vue2.0实现组件数据的双向绑定问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
Oct 20 Javascript
Javascript 八进制转义字符(8进制)
Apr 08 Javascript
jquery插件制作 自增长输入框实现代码
Aug 17 jQuery
JS文本框不能输入空格验证方法
Mar 19 Javascript
JS实现在页面随时自定义背景颜色的方法
Feb 27 Javascript
nw.js实现类似微信的聊天软件
Mar 16 Javascript
JavaScript实现点击单选按钮改变输入框中文本域内容的方法
Aug 12 Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
Mar 05 Javascript
浅析vue数据绑定
Jan 17 Javascript
利用原生JS与jQuery实现数字线性变化的动画
Feb 24 Javascript
js防刷新的倒计时代码 js倒计时代码
Sep 06 Javascript
Vue源码解析之Template转化为AST的实现方法
Dec 14 Javascript
轻松搞定jQuery+JSONP跨域请求的解决方案
Mar 06 #jQuery
Vue2.0 http请求以及loading展示实例
Mar 06 #Javascript
浅析Vue中method与computed的区别
Mar 06 #Javascript
浅谈Koa2框架利用CORS完成跨域ajax请求
Mar 06 #Javascript
JavaScript基础心法 深浅拷贝(浅拷贝和深拷贝)
Mar 05 #Javascript
JavaScript基础心法 数据类型
Mar 05 #Javascript
js获取html页面代码中图片地址的实现代码
Mar 05 #Javascript
You might like
无数据库的详细域名查询程序PHP版(3)
2006/10/09 PHP
基于PHP实现等比压缩图片大小
2016/03/04 PHP
JS提交并解析后台返回的XML的代码
2008/11/03 Javascript
JavaScript中的运算符种类及其规则介绍
2013/09/26 Javascript
JQuery给元素绑定click事件多次执行的解决方法
2014/05/29 Javascript
jquery引用方法时传递参数原理分析
2014/10/13 Javascript
DOM基础教程之使用DOM设置文本框
2015/01/20 Javascript
JavaScript实现的圆形浮动标签云效果实例
2015/08/06 Javascript
jQuery获取cookie值及删除cookie用法实例
2016/04/15 Javascript
JavaScript 拖拽实例代码
2016/09/21 Javascript
完美解决jQuery的hover事件在IE中不停闪动的问题
2017/02/10 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
浅谈Vue SSR 的 Cookies 问题
2017/11/20 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
React router动态加载组件之适配器模式的应用详解
2018/09/12 Javascript
JQuery的加载和选择器用法简单示例
2019/05/13 jQuery
在vue中使用Echarts画曲线图的示例
2020/10/03 Javascript
[05:26]2014DOTA2西雅图国际邀请赛 iG战队巡礼
2014/07/07 DOTA
Python 正则表达式操作指南
2009/05/04 Python
python批量生成本地ip地址的方法
2015/03/23 Python
python数据结构之链表的实例讲解
2017/07/25 Python
Python中optparser库用法实例详解
2018/01/26 Python
python简单商城购物车实例代码
2018/03/15 Python
解决python彩色螺旋线绘制引发的问题
2019/11/23 Python
浅谈keras中的batch_dot,dot方法和TensorFlow的matmul
2020/06/18 Python
应届生船舶驾驶求职信
2013/10/19 职场文书
文秘专业大学生求职信
2013/11/10 职场文书
岳父生日宴会答谢词
2014/01/13 职场文书
思想品德课教学反思
2014/02/10 职场文书
家长对孩子的感言
2014/03/10 职场文书
最美孝心少年事迹材料
2014/08/15 职场文书
暑期社会实践心得体会
2014/09/02 职场文书
2016年心理学教育培训学习心得体会
2016/01/12 职场文书
古诗之感恩老师
2019/10/24 职场文书
深入讲解数据库中Decimal类型的使用以及实现方法
2022/02/15 MySQL
Python按顺序遍历并读取文件夹中文件
2022/04/29 Python