vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)
1. v-model
实现自定义组件双向绑定
v-model
其实是个语法糖,如果没按照相应的规范定义组件,直接写v-model
是不会生效的。再说一遍,类似于v-on:click
可以简写成@click
,v-model
是两个表达式合在一起的简写。记住这个,下面具体说明。
1.1 input
双向绑定
子组件MyInput.vue
:
<template>
<div>输入
<input :value="value" @input="input"/>
</div>
</template>
<script>
export default {
name: "MyInput",
props: {
value: {type: [String, Number]}
},
methods: {
input(e) {
this.$emit('input', e.target.value)
}
}
}
</script>
父组件App.vue
中使用:
<template>
<div id="app">
<my-input v-model="haha" />
<div>{{haha}}</div>
</div>
</template>
<script>
import MyInput from '@/components/MyInput'
export default {
name: 'App',
components: { MyInput },
data() {
return {
haha: '66666',
}
}
}
</script>
<style>
#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;
}
</style>
<my-input v-model="haha" />
是一个语法糖(简写),它相当于:
<my-input
:value="haha"
@input="onInput"
/>
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
代码:
<template>
<div>
<input type="checkbox" :checked="checked" @change="change"/>
</div>
</template>
<script>
export default {
name: "MyCheckBox",
model: {
prop: 'checked',
event: 'zhuangbi'
},
props: {
checked: Boolean
},
methods: {
change(e) {
this.$emit('zhuangbi', e.target.checked)
}
}
}
</script>
父组件App.vue
中使用:
<template>
<div id="app">
<my-check-box v-model="changeV"></my-check-box>
<div>{{changeV}}</div>
</div>
</template>
<script>
import MyCheckBox from '@/components/MyCheckBox'
export default {
name: 'App',
components: { MyCheckBox },
data() {
return {
changeV: true,
}
}
}
</script>
除了绑定的
value
变成了checked
,@input
变成了@change
,传到父组件的参数是e.target.checked
注意: 绝大多数例子中,
$emit
中抛出的事件都是change
,我这里写的是zhuangbi
,其实只要和model
模块中event
属性值一样即可。
此外,外面的props
也不可少。
2. .sync
方式实现双向绑定
如果需要对一个prop
进行双向绑定,可以使用.sync
语法糖。举一个使用场景的例子:别人封装好的 CheckBox 组件,需要做一些样式修改或者功能组合再使用,这就需要对 v-model 的值再来一次双向绑定。拿上面的 MyCheckBox 来说,<my-check-box v-model="checked"/>
,给这个checked
传值可以用 props
,但想把checked
的值传给父组件并赋值给props
的值,就有点麻烦,需要定义一个方法,使用$emit
,父组件监听事件并作赋值操作。现在用.sync
可以一句搞定。
子组件DiyCheckBox
代码:
<template>
<div>
<my-check-box v-model="diyCheck" @change="dChange"/>
</div>
</template>
<script>
import MyCheckBox from './MyCheckBox'
export default {
name: "DiyCheckBox",
components: {MyCheckBox},
props: {
diyCheck: Boolean,
test: String
},
methods: {
dChange(e) {
this.$emit('update:diyCheck', e)
}
}
}
</script>
父组件App.vue
中使用:
<template>
<div id="app">
<diy-check-box :diyCheck.sync="dCheck" />
<div>{{dCheck}}</div>
</div>
</template>
<script>
import DiyCheckBox from '@/components/DiyCheckBox'
export default {
name: 'App',
components: { DiyCheckBox },
data() {
return {
dCheck: true,
}
}
}
</script>
: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
---> <DiyCheckBox> at src/components/DiyCheckBox.vue
<App>
<Root>
避免直接改变props
,使用data or computed
代替。所以优化一下,换个写法:
<template>
<div>
<my-check-box v-model="comDiyCheck"/>
</div>
</template>
<script>
import MyCheckBox from './MyCheckBox'
export default {
name: "DiyCheckBox",
components: {MyCheckBox},
props: {
diyCheck: Boolean,
test: String
},
computed: {
comDiyCheck: {
get() {
return this.diyCheck
},
set(e) {
this.$emit('update:diyCheck', e)
}
}
}
}
</script>
使用计算属性后,@change
事件都可以不要了,get()
就是获取props
传值,set(e)
是MyCheckBox
的v-model
值改变了会触发的方法,这里面做法是直接把改变后的值通过$emit
方式发出去。父组件中仍然通过.sync
绑定,代码没有变化。
.sync
可不光能用来做checkbox
的双向绑定,涉及到props
双向绑定的场景都可以用sync
实现。
.sync
传整个对象
如果有许多props
属性需要做双向绑定操作,标签写起来就很长,像这样:
<coverage-charge
v-for="(item, index) in chargingPiles"
:key="index + 'index'"
:code.sync="item.code"
:address.sync="item.address"
:addressType.sync="item.addressType"
:kind.sync="item.kind"
:yearLimitType.sync="item.yearLimitType"
>
</coverage-charge>
官方文档说可以简写成这样:
<text-document v-bind.sync="doc"></text-document>
<!--对应我们的例子就是:-->
<coverage-charge
v-for="(item, index) in chargingPiles"
:key="index + 'index'"
v-bind.sync='item'
>
</coverage-charge>
官方还说:
这样会把
doc
对象中的每一个property
(如title
) 都作为一个独立的prop
传进去,然后各自添加用于更新的v-on
监听器。
按照这个说法,item
的 5 个属性,都会通过 prop
传到子组件,我再在子组件中添加不同的computed
属性即可:
<script>
export default {
name: 'CoverageCharge',
props: {},
computed: {
code: {
get() {
return this.code
},
set(val) {
this.$emit('update:code', val)
}
},
address: {
get() {
return this.address
},
set(val) {
this.$emit('update:address', val)
}
}
... // 其他属性值
}
}
</script>
真这样写,会发现,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)
}
}
}
<!--父组件-->
<coverage-charge
v-for="(item, index) in chargingPiles"
:key="index + 'index'"
v-bind.sync='item'
:zb='item'
>
</coverage-charge>
2.2.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)
}
}
}
}
<!--父组件-->
<coverage-charge
v-for="(item, index) in chargingPiles"
:key="index + 'index'"
v-bind.sync='item'
v-model='item'
>
</coverage-charge>
注意
model
中event
值是update
。
3. 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
组件中使用:<my-check-box v-model="MyChecked"/>
- 父组件中使用:
<diy-check-box v-model=suibian" />
,suibian
是父组件data
中定义的变量
可见,v-model
适用于双向绑定单个props
(一个标签中不能有多个v-model
),.sync
适用于双向绑定一到多个props
(一个标签中允许使用多个:xxx.sync=yyy
)。
源码
vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)的更多相关文章
- vue.js初级入门之最基础的双向绑定操作
首先在页面引入vue.js以及其他需要用到的或者可能要用到的插件(这里我多引用了bootstrap和jquery) 引用的时候需要注意文件的路径,准备工作这样基本就完成了,下面正式开始入门. vue. ...
- 【vue】跟着老马学习vue-数据双向绑定
学习了node.js教程,只能说是有了一定的了解,之前也了解了webpack和es6的核心内容,也看过vue2.0的官网教程,并结合视频看过项目,但是理解和运用仍然存在很多问题,接下来的一段时间,跟着 ...
- Vue.js之Vue计算属性、侦听器、样式绑定
前言 上一篇介绍了Vue的基本概念,这一篇介绍一下Vue的基本使用. 一.搭建一个Vue程序 1.1 搭建Vue环境 搭建Vue的开发环境总共有三种方法: 引入CDN <script src=& ...
- Vue.js的类Class 与属性 Style如何绑定
Vue.js的类Class 与属性 Style如何绑定 一.总结 一句话总结:数据绑定一个常见需求是操作元素的 class 列表和它的内联样式.因为它们都是属性,我们可以用 v-bind 处理它们:我 ...
- 理解ASP.NET Core - 模型绑定&验证(Model Binding and Validation)
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 模型绑定 什么是模型绑定?简单说就是将HTTP请求参数绑定到程序方法入参上,该变量可以是简单类 ...
- vue中如何在自定义组件上使用v-model和.sync
自定义事件 tips 推荐始终使用 kebab-case 的事件名.(v-on会将事件名自动转换为小写,避免匹配不到) changeData × change-data √ 自定义组件的v-model ...
- v-bind绑定属性样式——class的三种绑定方式
1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{‘class-a‘:isA ,‘class-b‘:isB ...
- input绑定datapicker控件后input再绑定blur或者mouseout等问题
input绑定datapicker控件后input再绑定blur或者mouseout等问题 问题描述:今天在修改一个东西的时候需要给一个input输入域绑定blur事件,从而当它失去焦点后动态修改其中 ...
- python tips:类的绑定方法(bound)和非绑定方法(unbound)
类属性只有类及其实例能够访问,可以理解为一个独立的命名空间. Python中类属性的引用方式有两种: 1. 通过类的实例进行属性引用,称为绑定方法(bound method),可以理解为方法与实例绑定 ...
随机推荐
- Python - 基础数据类型 dict 字典
字典简介 字典在 Python 里面是非常重要的数据类型,而且很常用 字典是以关键字(键)为索引,关键字(键)可以是任意不可变类型 字典由键和对应值成对组成,字典中所有的键值对放在 { } 中间,每一 ...
- SaltStack 任意文件读写漏洞(CVE-2020-11652)
漏洞影响 SaltStack < 2019.2.4 SaltStack < 3000.2 同CVE-2020-11651 poc git clone https://github.com/ ...
- 使用Fileupload完成文件的上传下载
目录 使用Fileupload完成文件的上传下载 为什么需要进行文件上传下载? 引入jar包 文件上传 注意事项 编写一个简单的文件上传jsp页面 编写Servlet Student类用于封装数据,后 ...
- 抄书抄博客毒害社区的Writer几时休?
曾几何时,博客园用户也渐渐分成了两类人:Writer和Coder. 何为Coder?就是认认真真写代码,平时分享工作中的一些问题.好的解决方案,或者写一些实用的原理技术文.答疑解惑的教程技术文. 何为 ...
- Vue 脚手架学习
首先就是安装脚手架 npm install @vue/cil -g 全局安装 在这里我遇到一个问题:安装不了脚手架,报错显示: 通过苦逼的查找原因就是 以前使用的taobao镜像 导致的,删除镜像换成 ...
- Java流程控制01——用户交互Scanner
用户交互Scanner sacnner对象 之前的语法并没有实现程序与人的交互.java.util.Scanner是Java5的新特征,我们可以通过Scanner类来获取用户的输入. 基本语法: S ...
- 干了快3年Android了,感觉自己的职业生涯已经快凉了
背景 首先我是个菜鸡,工资也低的一笔. 刚毕业时候在一家国企上班干 app 开发,干了快两年的时候,跳槽到了一家伪大厂干安全.投了不少简历都没有回音,只有这加伪大厂要我就来了.当时说好了会接触一些底层 ...
- 解决win10快速访问不能取消固定
最近发现win10的快速访问不能取消固定,比如ftp和smb之类的都不能取消固定 最后百度了一下发现一个简易的方法: 在文件资源管理器地址栏输入:%APPDATA%\Microsoft\Windows ...
- 【笔记】SVM思想解决回归问题
使用svm思想解决回归问题 使用svm思想解决是如何解决回归问题,其中回归问题的本质就是找一条线,能够最好的拟合数据点 怎么定义拟合就是回归算法的关键,线性回归算法就是让预测的直线的MSE的值最小,对 ...
- 【XSS-labs】level 6-10
Level 6 查看源码:对URL中的传参进行了HTML实体化转义,搜索框中的值对 src\onxxxxx\data\href进行了限制. 采用大小写绕过,在搜索框输入payload,注意闭合inpu ...