vue v-model语法糖(一)
最近封装select组件的时候有一个需求,创建两个组件。要求子组件child绑定一个value值。要求在使用父组件(自定义组件)的时候,实现这个select的值和dom元素的双向绑定。
父传子:
是通过parent组件的props属性,将值传递给子组件,修改了子组件的value属性,vue的响应式原理,页面dom也会同步修改了。这里是生效的。
问题出在子传父:
但是我发现通过修改dom select值,想要同步修改到父组件的props指向的变量,是行不通的。
这是因为props不支持双向传递,只能是子组件中使用父组件的数据。
如果要实现,要怎么做?
其实父组件用子组件的数据,可以通过事件暴露来给父组件发消息
第一版本-用props + $emit('event',传递值):
子组件
<template>
<select name="" id="" v-model="selectVal" @input="$emit('input',$event.target.value)">
<option v-for="item in selectData" :key="item.value">
{{ item.value }}
</option>
</select>
</template>
<script>
export default {
name:"etSelect",
data() {
return {
};
},
props: {
selectVal:{
type:Object,
default:null
}
},
};
</script>
<style>
</style>
父组件
<template>
<div id="content">
<div class="box">
<etSelect
:selectVal = "selectVal"
@input="(val) => (selectVal = val)"
>
</etSelect>
</div>
<p>{{ selectVal }}</p>
<!-- <p>有什么问题吗</p> -->
</div>
</template>
<script>
import etSelect from "./sweetselect.vue";
export default {
data() {
return {
selectVal: null,
],
};
},
mounted() {},
components: {
etSelect: etSelect,
},
};
</script>
<style>
</style>
这里值得推敲的是在父组件中的第二种写法,就下面这个模式
:selectVal = "selectVal"
@input="(val) => (selectVal = val)"
其实有一个更简单的方式实现,就是我们vue的v-model
当v-model使用在自定义组件中时候,实际上就相当于上面的这两句代码,效果,性能完全相同。
相当于我们在 input 表单元素上动态绑定了 value,又添加事件处理,相当于在 input 上绑定了 input 事件。动态绑定input的value,并将value指向selectVal,然后当触发输入事件的时候,将输入的目标值设置到selectVal上。实现数据的双向绑定
第二种版本:父组件使用v-model
父组件修改即可:
<template>
<div id="content">
<div class="box">
<etSelect
v-model="selectVal"
>
</etSelect>
</div>
<p>{{ selectVal }}</p>
</div>
</template>
<script>
import etSelect from "./sweetselect.vue";
export default {
data() {
return {
selectVal: null,
],
};
},
mounted() {},
components: {
etSelect: etSelect,
},
};
</script>
<style>
</style>
发散一下,vue其实也有其它的语法糖:
语法糖,就是语法的糖,他不是基础的技术,而是为了编程的便利提供的糖。在其它技术栈也有的。
例子1:
v-on 简化写法 @
v-bind :
还有解构赋值
var a = 1,b= 2
相当于
var a ,b
[a,b]=[1,2]
注意:怎么判断一个技术是不是语法糖,可以看看这个有没有其它的写法,实现完全一样的功能。
请注意这里,完全一样。因此,箭头函数就不是语法糖,因为他和function的功能有差异,他的能力替代不了function,他没有上下文的this。