关于双向绑定


想实现双向绑定是为了避免下面的情况:比如子组件更新数据后,父组件没有对应的更新,造成错误。或者页面比较复杂的时候,遗漏手动更新。
所以需要双向同步,核心就是自动更新值到父组件

常见的双向绑定

常见的双向绑定,就是input中的v-model

<input v-model="searchText" />

这个searchText在data中声明,然后使用v-model绑定,效果就是:在input值改变的时候,searchText的值同步改变;手动改变searchText值的时候,input中的显示也跟随改变

实现原理:

根据官网的介绍,实现原理是,这个代码被编译的时候,编译器对代码进行了展开,等价于

<input
  :value="searchText"
  @input="searchText = $event.target.value"
/>

:value指向的是input展示的属性,手动改变属性值,会改变input的展示内容
input输入值的时候,触发input的事件,会将输入结果赋值给input展示的属性searchText,改变input的展示内容

所以当主动改变searchText,或者使输入内容的时候,都会改变input的展示内容。实现了双向绑定

父子组件属性的双向绑定

在组件定义prop属性,接收父组件传递的值,是单向的,子组件不能修改prop属性,否则会警报
那么要想父子同步,常用的方式

$emit

子组件prop接收值,data中声明自定义变量接收prop属性的值
在需要改变的时候,通过$emit方法,触发指定的父组件的函数,将变化后的值传递过去,父组件更新值

简单来说,可以这么实现双向绑定,比如

  1. 父组件通过prop传递给子组件初始值
  2. 子组件自定义属性接收初始值,当需要改变的时候,改变自定义属性的值,然后通过$emit传递给父组件
  3. 父组件拿到新值,更新自己传递给子组件的值

这样,双方的数据就是一致的了

其他方式

参考文章

.sync

vue2中提供了.sync的方式来进行双向同步

原理与上面的$emit是一样的,只不过不需要在父组件写指定的函数,自己更新数据了,而是只需要在子组件中指定函数与新值

例子如下:

父组件

父组件写法与之前不同的是,在需要双向绑定的数据后追加.sync,比如

<child :name="childName" :sdata.sync="syncData"></child>

<script>
	export default {
		data() {
			return {
				syncData: 'ppp',
			}
		},
...

其中sdata就是子组件在prop中声明的要接收父组件传递值的字段,.sync表示这个字段是要双向绑定的

子组件

子组件中,写法基本不变,$emit函数变化

1: 在props中声明要接收的数据

props:{
	sdata:{
		type: String,
		default: ''
	}
},

2:在数据变化后,指定更新函数,该函数会自动更新同步父组件关联的属性值。

changeValue(){
	this.sdata = 'ttt'
	this.$emit('update:sdata', this.sdata)
}

注意函数的写法:this.$emit(‘update:xxx’: newValue)

组件v-model

官方文档

vue2

与.sync的表现是一样的,不需要在父组件写指定的函数,自己更新数据了,只是写法变化了一些
例子:

子组件中:

<button class="btn" @click="changeValue">{{childValue}}</button>
...
props:{
	// 声明要从父组件传递过来的属性
	fatherValue:{
		type:String,
		default:"",
	}
},
// 自定义model
model:{
	prop: 'fatherValue',  // 属性
	event: 'childValueChange' // 触发事件,触发这个事件,会将传递的value赋值给指定的属性prop
},
data(){
	return{
		childValue: this.fatherValue // 初始化接收的值
	}
},
methods:{
	changeValue(){
		this.childValue = 'childChange'
		this.$emit('childValueChange', this.childValue)  // 触发指定事件,传递value,会更新父组件的值
	}
}

父组件中:

<child v-model="fatherValue"></child>

效果,在浏览器的vue插件中查看数据

按钮点击前:

在这里插入图片描述
点击按钮后
在这里插入图片描述
说明父组件的数据同步更新了

通过后续的尝试,发现,v-model的值是Object类型的也可以

v-model与.sync写法的一些区别

主要体现在:

  1. 父组件中,引用数据一个是v-model,一个是:xxx.sync
  2. 子组件中,v-model的方式,需要创建一个自定义model,指定要同步的属性和触发函数名称
  3. 使用this.$emit()指定触发的函数不同,.sync中的是 ‘update:xxx’,而v-model中的是自定义model中指定的函数名称

最后,在vue2中,v-model只能写一个,而.sync可以有多个

vue3

父组件使用v-moel,vue2中只允许写一个v-model,在vue3中,允许写多个v-model

父组件中使用: v-model:xxx来绑定值

<UserName
  v-model:first-name="first"
  v-model:last-name="last"
/>

子组件声明的时候,不使用props+model了,而是使用props+emits:

export default {
  props: {
    firstName: String,
    lastName: String
  },
  emits: ['update:firstName', 'update:lastName']
}

触发原理与vue2中的一样,指定事件会将传递的value赋值给指定的属性prop

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值