vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)
1. v-model
实现自定义组件双向绑定
v-model
其实是个语法糖,如果没按照相应的规范定义组件,直接写v-model
是不会生效的。再说一遍,类似于v-on:click
可以简写成@click
,v-model
是两个表达式合在一起的简写。记住这个,下面具体说明。
1.1 input
双向绑定
子组件MyInput.vue
:
输入
父组件
App.vue
中使用:
{{haha}}#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
是一个语法糖(简写),它相当于: onInput(e) {
this.haha = e
}
两者效果一样,v-model
减少了很多代码,不用你手动把传过来的值赋值给haha
了,少定义了一个方法。作用还是挺明显的。
MyInput
组件中的value
不可以叫别的名字,$emit
中抛出的方法也只能叫input
,否则都不可以用v-model
语法糖,用了也没啥效果。 另外,获取 input 输入值的的方式是:
$event.target.value
,写成方法的话,$event
实参省略了。1.2.
checkbox
双向绑定
到了checkbox
这,又有点不一样,首先,它绑定的值不叫value
,触发事件也不叫input
,具体看代码。子组件
MyCheckBox
代码:
父组件
App.vue
中使用:
{{changeV}}
除了绑定的此外,外面的value
变成了checked
,@input
变成了@change
,传到父组件的参数是e.target.checked
==注意:== 绝大多数例子中,$emit
中抛出的事件都是change
,我这里写的是zhuangbi
,其实只要和model
模块中event
属性值一样即可。
props
也不可少。2.
.sync
方式实现双向绑定
如果需要对一个prop
进行双向绑定,可以使用.sync
语法糖。举一个使用场景的例子:别人封装好的 CheckBox 组件,需要做一些样式修改或者功能组合再使用,这就需要对 v-model 的值再来一次双向绑定。拿上面的 MyCheckBox 来说,
,给这个checked
传值可以用 props
,但想把checked
的值传给父组件并赋值给props
的值,就有点麻烦,需要定义一个方法,使用$emit
,父组件监听事件并作赋值操作。现在用.sync
可以一句搞定。子组件
DiyCheckBox
代码:
父组件
App.vue
中使用:
{{dCheck}}
:diyCheck.sync="dCheck"
这句代码相当于::diyCheck="dCheck"
@update:diyCheck="dCheck = $event"
语法糖作用很明显,大大简化了代码。上面代码可以实现想要的功能,只是控制台会有一个警告:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "diyCheck"found in---> at src/components/DiyCheckBox.vue
避免直接改变
props
,使用data or computed
代替。所以优化一下,换个写法:
使用计算属性后,
@change
事件都可以不要了,get()
就是获取props
传值,set(e)
是MyCheckBox
的v-model
值改变了会触发的方法,这里面做法是直接把改变后的值通过$emit
方式发出去。父组件中仍然通过.sync
绑定,代码没有变化。.sync
可不光能用来做checkbox
的双向绑定,涉及到props
双向绑定的场景都可以用sync
实现。.sync
传整个对象
如果有许多props
属性需要做双向绑定操作,标签写起来就很长,像这样:
官方文档说可以简写成这样:
官方还说:
这样会把按照这个说法,doc
对象中的每一个property
(如title
) 都作为一个独立的prop
传进去,然后各自添加用于更新的v-on
监听器。
item
的 5 个属性,都会通过 prop
传到子组件,我再在子组件中添加不同的computed
属性即可:
真这样写,会发现,
this.code
、this.address
这些都是undefined
,这里需要在子组件的props
中再定义一遍属性名才行,可以省略各属性的type
和default
值: props: [ 'code', 'address', 'addressType', 'kind', 'yearLimitType' ]
这样就可以了,
.sync
功能强大,用的地方也挺多的。props
里面东西太多的话,也可以统一定义成一个对象,然后父组件通过v-bind
或者v-model
传进来:2.1.1
v-bind
方式
props: {
zb: {
type: Object,
default: () => {}
}
},
computed: {
code: {
get() {
return this.zb.code
},
set(val) {
this.$emit('update:code', val)
}
},
address: {
get() {
return this.zb.address
},
set(val) {
this.$emit('update:address', val)
}
}
}
2.1.2
v-model
方式
export default {
model: {
prop: 'zb',
event: 'update'
},
props: {
zb: {
type: Object,
default: () => {}
}
},
computed: {
code: {
get() {
return this.zb.code
},
set(val) {
this.$emit('update:code', val)
}
},
address: {
get() {
return this.zb.address
},
set(val) {
this.$emit('update:address', val)
}
}
}
}
注意3.model
中event
值是update
。
v-model
和.sync
比较
上面第 2 节第一个例子目的就是把v-model
再包一层,照着第 1 节,用v-model
的方法也能做到。这里只写主要点,不贴源码了:- 定义
model
模块:model: {prop: 'checked', event: 'zhuangbi' }
props
中定义checked
属性computed
中定义MyChecked: { get(){ return this.checked},set(val) { this.$emit('zhuangbi', val) } }
DiyCheckBox
组件中使用:- 父组件中使用:
,suibian
是父组件data
中定义的变量
v-model
适用于双向绑定单个props
(一个标签中不能有多个v-model
),.sync
适用于双向绑定一到多个props
(一个标签中允许使用多个:xxx.sync=yyy
)。源码 【vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)】点击查看源码
推荐阅读
- vue-cli|vue-cli 3.x vue.config.js 配置
- 2020-04-07vue中Axios的封装和API接口的管理
- VueX--VUE核心插件
- 7、前端--jQuery简介、基本选择器、基本筛选器、属性选择器、表单选择器、筛选器方法、节点操作、绑定事件
- vue组件中为何data必须是一个函数()
- 用npm发布一个包的教程并编写一个vue的插件发布
- 事件解绑与解绑的兼容代码
- vuex|vuex 基础结构
- Vue源码分析—响应式原理(二)
- VueX(Vuex|VueX(Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式)