Vue2 ,v-model,以及利用 v-model 实现组件props双向绑定的解决方案
一、v-model?
https://segmentfault.com/a/1190000009492595
v-model 其实是一个语法糖,这背后其实做了两个操作
-
v-bind 绑定一个 value 属性
-
v-on 指令给当前元素绑定 input 事件
在原生表单元素中
[code]<input v-model='something'>
就相当于
[code]<input v-bind:value="something" v-on:input="something = $event.target.value">
在自定义组件中
[code]<my-component v-model='something'></my-componment>
相当于
[code]<my-component v-bind:value='something' v-on:input='something = arguments[0]'></my-component>
这时候,something接受的值就是input是事件的回掉函数的第一个参数
所以在自定义的组件当中,要实现数据绑定,还需要使用[$emit]去触发input的事件。
[code]this.$emit('input', value)
二、利用 v-model 实现组件props双向绑定的解决方案?
https://segmentfault.com/a/1190000008662112
https://cn.vuejs.org/v2/guide/components.html#%E4%BD%BF%E7%94%A8%E4%BA%8B%E4%BB%B6%E6%8A%9B%E5%87%BA%E4%B8%80%E4%B8%AA%E5%80%BC
在项目中使用vue2来构建项目,跟 vue1 很大的一处不同在于2 取消了props 的双向绑定,改成只能从父级传到子级的单向数据流,初衷当然是好的,为了避免双向绑定在项目中容易造成的数据混乱。
解决方案一、
参考网上与github上,解决方案都是这样:
1、在父组件中,用data对象中创建一个props属性的副本
2、在子组件中,watch props属性,并赋予data副本,同步组件外对props的修改
3、在子组件中,watch data副本,emit一个方法,通知到组件外。
最常见的 modal为例子:
modal挺合适双向绑定的,外部可以控制组件的 显示或者隐藏,组件内部的关闭可以控制 visible属性隐藏,同时visible 属性同步传输到外部。
[code]///modal.vue 组件 <template> <div class="modal" v-show="visible"> <div class="close" @click="cancel">X</div> </div> </template> <script> export default { name:'modal', props: { value: { type: Boolean, default:false } }, data () { return { visible:false } }, watch:{ value(val) { this.visible = val; }, visible(val) { this.$emit("visible-change",val); } }, methods:{ cancel(){ this.visible = false; } }, mounted() { if (this.value) { this.visible = true; } } } </script> ///调用modal组件 <modal :value="isShow" @visible-change="modalVisibleChange"></modal> export default { name: 'app', data () { return { isShow:true, } }, methods:{ modalVisibleChange(val){ this.isShow = val; } } }
这样就解决了 组件props 双向绑定的问题。 但是这样有一个不是太美观的现象就是 在父级调用 modal组件的时候,还需要写一个 modalVisibleChange 的methods. 总是显得这部分代码是多余的。 特别是写一个让别人用的公共组件,这样调用太麻烦了。
能不能不写method来实现props的双向绑定呢,答案是可以的。
优美解决方案、
那就是利用 v-model, 然后使用value来保存v-model的值,进行双向绑定
[code]<template> <div class="modal" :value="value" v-show="visible"> <div class="close" @click="cancel">X</div> </div> </template> <script> export default { props: { value: { type: Boolean, default:false } }, data () { return { visible:false } }, watch:{ value(val) { this.visible = val; }, visible(val) { this.$emit('input', val); } }, methods:{ cancel(){ this.visible = false; } }, mounted() { if (this.value) { this.visible = true; } } } </script> ///调用modal组件 <modal v-model="isShow"></modal> export default { name: 'app', data () { return { isShow:false } } } </script>
只要设置 isShow 就可以控制 modal 组件的显示或者隐藏,同时 如果是modal 组件内部关闭按钮关闭的,状态也会传到 isShow。
实例:实现公共组件
[code]<template> <transition name="fade"> <div v-show="visible"> <div v-if="showModal"></div> <div @click="handleWrapClick"> <div> <div> <slot name="tips"></slot> <div @click="close" v-if="showClose"> <img src="../../assets/images/intent/close.png"> </div> </div> <slot name="footer"></slot> </div> </div> </div> </transition> </template> <script> export default { name: 'confirm', props: { showModal: { type: Boolean, default: false }, showClose: { type: Boolean, default: false }, value: { type: Boolean, default: false }, closable: { type: Boolean, default: true }, maskClosable: { type: Boolean, default: false }, authClose: { type: Boolean, default: true }, model: { type: String, default: '' } }, data(){ return { visible: this.value, timer: null } }, watch: { value(val){ this.visible = val }, visible(val){ if(val === false){ if(this.timer){ clearTimeout(this.timer) } return } if(this.authClose){ this.timer = setTimeout(() => { this.close() }, 2500) } } }, methods: { close(){ this.visible = false if(this.model){ this.$parent[this.model] = false } }, mask(){ if(this.maskClosable){ this.close() } }, handleWrapClick(event){ if(event.target == event.currentTarget){ this.mask() } } } }
[code]<confirm v-model="showConfirm" model="showConfirm" maskClosable showModal :showClose="showClose" :authClose="authClose"> <div slot="tips"> <div :class="confirmImgClass"></div> <div v-html="confirmTips"></div> </div> <div slot="footer" v-if="confirmBtnList && confirmBtnList.length"> <div v-for="btn in confirmBtnList" :key="btn.btnText" @click="btn.btnCallBack" :class="{active: btn.active}">{{btn.btnText}}</div> </div> </confirm> data () { return { flag: true, showOptTips: false, optTips: '', showConfirm: false, showClose: false, authClose: false, confirmTips: '备注仅能添加一次,请确定已经完善内容。', confirmImgClass: 'confirm-yellow-warning', confirmBtnList: [] } }, submit() { this.confirmBtnList = [ { btnText: '提交', btnClass: '', active: false, btnCallBack: () => { this.showConfirm = false; this.isSubmit (true) } }, { btnText: '取消', btnClass: '', btnCallBack: () => { this.showConfirm = false; this.isSubmit (false) } } ] if (this.flag) { this.showConfirm = true; } else { this.showConfirm = false; } }, isSubmit (msg) { if (msg) { this.flag = false; //处理部分 } else { this.flag = true; //处理部分 }
阅读更多
- Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案
- 详解如何在Vue2中实现组件props双向绑定
- Vue2实现组件props双向绑定
- Vue2实现组件props双向绑定
- Vue2实现组件props的双向绑定
- 如何在Vue2中实现组件props双向绑定
- AngulaJS 中$watch()的应用以及ng-model实现数据双向绑定
- vue.js学习笔记(六)--利用v-model实现父子组件间的双向通信
- 利用定时器实现双向数据绑定效果
- vue自定v-model实现表单数据双向绑定问题
- Vue实现双向绑定的原理以及响应式数据的方法
- 阿里云学生优惠Windows Server 2012 R2安装IIS,ftp等组件,绑定服务器域名,域名解析到服务器,域名备案,以及安装期间错误的解决方案
- 【干货】利用MVC5+EF6搭建博客系统(四)(上)前后台页面布局页面实现,介绍使用的UI框架以及JS组件
- 利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法
- JS组件系列——BootstrapTable+KnockoutJS实现增删改查解决方案(三):两个Viewmodel搞定增删改查
- Windows Server 2012 R2安装IIS,ftp等组件,绑定服务器域名,域名解析到服务器,域名备案,以及安装期间错误的解决方案
- 解决Vue2.x父组件与子组件之间的双向绑定问题
- 【VUE】.NET实现Tree组件双向绑定数据(2)
- vue父子组件传值,实现深度监听对象,双向绑定
- 利用Vue v-model实现一个自定义的表单组件