Vue 如何使用props、emit实现自定义双向绑定的实现

2020-06-16 06:59:18易采站长站整理

下面我将使用Vue自带的属性实现简单的双向绑定。

下面的例子就是利用了父组件传给子组件(在子组件定义props属性,在父组件的子组件上绑定属性),子组件传给父组件(在子组件使用$emit()属性定义一个触发方法,在父组件上的子组件监听这个事件)。


import Vue from 'vueEsm'

var Com = {
name:'Com',
props:['val'],
template:`<input type='text' @input='handleInput'/>`,
methods: {
handleInput(e){
this.$emit("input",e.target.value);
}
},
}

new Vue({
el:'#app',
data() {
return {
value:''
}
},
components:{
Com
},
template:`
<div>
<Com @input='post' :val='value'></Com>
</div>
`,
methods:{
post(data){
this.value=data;
}
}
})

上面这个例子,在input标签上每次输入时触发原生事件input,在这个事件上绑定了一个handleInput方法,事件每次触发都会执行方法里的$emit属性。该属性里面第一个参数可以定义一个事件名,第二个参数可以传一个参数。这里我们把每次输入的值e.target.value传进去。在父组件的子组件上监听这个事件,定义一个post方法,方法的参数就是传入的数据。然后我们在父组件的data属性里定义一个存储值的变量value。将刚才传入的参数赋给这个变量value。最后在父组件的子组件上绑定一个自定义属性,比如val。将value传给val。在子组件定义一个props属性接受这个val。

这个例子对于理解父组件与子组件传值特别重要。

下方举例说明了我的一个自定义mySelect的实现过程:


<template>
<div class="select">
<div class="input" @click="collapse=!collapse">
<span v-if="currentValue">{{currentLabel||currentValue}}</span>
<span v-else class="placeholder">{{placeholder}}</span>

<span :class="collapse?'arrow-down':'arrow-up'"></span>
</div>

<div class="option-list" v-show="!collapse">
<div class="option-item" v-for="item in data" :key="item.id" @click="chooseItem(item)">{{item[itemLabel?itemLabel:'name']}}</div>
</div>
</div>
</template>

<script>
export default {
name: "mySelect",
props: [
'value',
'placeholder',
'data',
'itemLabel',
'itemValue'
],
data() {
return {
collapse: true,
currentValue: '',
currentLabel: '',
}
},
watch: {
value: {
immediate: true,
handler(value) {
this.currentValue = value;