数据双向绑定
讲一下什么是数据双向绑定
- v-model(语法糖)
是Vue框架的一种内置的API指令,本质是一种语法糖写法。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理
<input type="text" v-model="msg"/>
// 等于下面代码
<input type="text" :value="msg" @input="msg = $event.target.value" />
通过上面这两段代码片段可以看出来 v-model="msg" 是 :value="msg" @input="msg = $event.target.value"的缩写
解析一下代码
- $event 当前触发的事件对象。
- $event.target 当前触发的事件对象的dom
- $event.target.value 当前dom的value值
- 在@input方法中,value => msg
- 在:value中:msg => value
- 如此,形成了一个闭环,也就是所说的数据的双向绑定。
那么就有人提问了, vue中的自定义组件能不能实现双向绑定
<my-Input v-model="msg"></my-Input>
//我们可以根据规则来拆解
<my-Input :value="msg" @input="msg = $event.target.value"></my-Input>
解析还原一下组件封装的过程
<template>
<div>
<input type="text" :value="value" @input="$emit('input', $event.target.value)"></input>
</div>
</template>
<script>
export default {
props:{
value:String
}
}
</script>
看完以后突然恍然大悟, 这是父子组件的来回传值!!
那么可以在思考一个问题就是代码里props的value里的值可不可以随便写一个呢? input可不可以随便定义一个事件呢?当我们在自定义组件使用v-model的时候并不能实现双向的数据绑定, 因为自定义的组件没有默认value和input事件,在使用的时候我们就得按照刚刚所写的一样去生命定义这些东西这时候,model的选项就派上用场了,在定义组件的时候,指定prop的值和监听的事件。
组件的用法不变,子组件这样写(里面事件就随便填了)
<template>
<div>
<input type="text" :value="xx" @input="$emit('xx', $event.target.value)"></input>
</div>
</template>
<script>
export default {
model: {
value:'xx',
event:'xx', // 代表自定义的事件名称
}
props: {
xx: String //代表自定义的变量名成
}
}
</script>
上面就是整理的一些vue2的双向绑定以及一些用法
vue3双向数据绑定
vue3与vue2的双向数据绑定区别并不是很大,他是跟vue2的sync进行了合并,所以在vue3的就移除了sync,不多说,上代码!
// 自定义一个Input组件
<template>
<div>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
modelValue: {
type: String
}
}
}
</script>
//在vue3中默认的不在是value 而是modelValue
然后在其他页面使用
<template>
<h1>{{ msg }}</h1>
<Input v-model="msg"></Input>
//等同于下面语法 默认传入一个modelValue然后在子组件接收
<Input :modelValue="msg" @update:modelValue="msg = $event"></Input>
</template>
<script>
import { ref } from "vue";
import Input from "@/components/Input"
export default {
components:{ Input },
setup(props){
const msg = ref('')
return { msg }
}
}
</script>
那么这个默认的modelValue就无法改变了吗?当然不是
// 父组件
<template>
<h1>vue3中使用v-model {{msg}}</h1>
<testModel v-model:msg="msg"></testModel>
</template>
这时候子组件接收的props就要换成msg了
// 子组件
<template>
<div>
<input type="text" :value="msg" @input="$emit('update:msg', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
msg: {
type: String
}
}
}
</script>
当然提到双向绑定,你可能第一时间就会想到表单元素,双向绑定不一定是表单元素,你可以定义各种各样的组件,比如通过click事件改变父组件的值
// 父组件
<template>
<div>{{count}}</div>
<testModel v-model="content" :content="content"></testModel>
</template>
<script>
export default {
components: {
testModel
},
setup(){
const count = ref(0)
return { count }
}
}
</script>
// 子组件
<template>
<!-- 一定是+1 不是+=1 或者++ 否则vue会触发一个不让子组件直接改变props的警告 -->
<div @click="$emit('update:count', count + 1)">click me count + 1!</div>
</template>
<script>
export default {
props: {
count: {
type: Number
}
}
}
</script>
评论 (0)