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 相关文章推荐
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
Jan 15 Javascript
jquery不会自动回收xmlHttpRequest对象 导致了内存溢出
Jun 18 Javascript
jquery简单实现鼠标经过导航条改变背景图
Dec 17 Javascript
JQuery each()嵌套使用小结
Apr 18 Javascript
使用javascript实现简单的选项卡切换
Jan 09 Javascript
js中开关变量使用实例
Feb 24 Javascript
JavaScript中object和Object的区别(详解)
Feb 27 Javascript
Vue基于NUXT的SSR详解
Oct 24 Javascript
jQuery实现的淡入淡出与滑入滑出效果示例
Apr 18 jQuery
基于javascript实现碰撞检测
Mar 12 Javascript
node.js 如何监视文件变化
Sep 01 Javascript
vue切换菜单取消未完成接口请求的案例
Nov 13 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中的多种加密技术及代码示例解析
2016/10/20 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
2017/08/28 PHP
关于laravel后台模板laravel-admin select框的使用详解
2019/10/03 PHP
JS 操作符整理[推荐收藏]
2011/11/15 Javascript
关于JavaScript中string 的replace
2013/04/12 Javascript
JSON+HTML实现国家省市联动选择效果
2014/05/18 Javascript
node.js中的http.response.setHeader方法使用说明
2014/12/14 Javascript
Juery解决tablesorter中文排序和字符范围的方法
2015/05/06 Javascript
javascript 用函数实现继承详解
2016/05/28 Javascript
angular基于路由控制ui-router实现系统权限控制
2016/09/27 Javascript
jquery easyui如何实现格式化列
2017/07/30 jQuery
JQuery中queue方法用法示例
2019/01/31 jQuery
javascript 内存模型实例详解
2020/04/18 Javascript
Python cookbook(数据结构与算法)从序列中移除重复项且保持元素间顺序不变的方法
2018/03/13 Python
Python爬取数据保存为Json格式的代码示例
2019/04/09 Python
python画图--输出指定像素点的颜色值方法
2019/07/03 Python
Python笔记之观察者模式
2019/11/20 Python
Python计算矩阵的和积的实例详解
2020/09/10 Python
python3定位并识别图片验证码实现自动登录功能
2021/01/29 Python
Html5 实现微信分享及自定义内容的流程
2019/08/20 HTML / CSS
HTML5 Web Database 数据库的SQL语句的使用方法
2012/12/09 HTML / CSS
Marriott中国:万豪国际酒店查询预订
2016/09/02 全球购物
香港演唱会订票网站:StubHub香港
2019/10/10 全球购物
电子商务毕业生求职信
2013/11/10 职场文书
应届毕业生求职信
2013/11/30 职场文书
应届医学毕业生求职信分享
2013/12/02 职场文书
写给女生的道歉信
2014/01/14 职场文书
关于梦想的演讲稿
2014/05/05 职场文书
体育教师求职信
2014/06/30 职场文书
竞选班干部演讲稿500字
2014/08/20 职场文书
高中学生会竞选演讲稿
2014/08/25 职场文书
2014国庆节商场促销活动策划方案
2014/09/16 职场文书
2014群众路线学习笔记
2014/11/06 职场文书
公司文体活动总结
2015/05/07 职场文书
民事答辩状格式范文
2015/05/21 职场文书
消费者投诉书范文
2015/07/02 职场文书