重点介绍自定义组件的 v-model
实现
如何开发一个Vue组件
当你会开始一个理想的,且合理的vue组件时,你方才可以说,你会玩vue了。
如何开发一个子组件呢,开发vue组件需要考虑的几个关键问题是什么?
这里,我们使用的vue-element-ui 的vue-element-template
作为基础框架,进行举例
vue-element-template
的源代码git库
.git仓库
1、如何引用子组件
引用局部引用vue组件很简单,如下
<template>
<div>
<h3>当前为父组件</h3>
<!-- 使用子组件 -->
<child-comp abc="text comp" :val=1 @ok="show" />
</div>
</template>
<script>
// 引入组件
import ChildComp from './ChildComp.vue'
export default {
// 务必记得将ChildComp在 components中添加
components:{
ChildComp
},
methods: {
show(e){
alert(e)
}
}
}
</script>
注意: 组件在模块中使用时,需要建议使用小写字组,并将驼峰命,转为如上所示的短横杆式命名
2、如何开发子组件
2.1 定义属性
组件定义的关键,是声明属性,只有声明过的属性,方可在模板中与普通html元素一个使用属性赋值
如 abc
、val
这些属性都应在子组件中声明,如下子组件如示
<template>
<div>
<h3>这是子组件</h3>
<span>属性abc {{abc}} </span>
<span>属性val: {{val}} </span>
<input v-model="childValue" v-on:change="isChangeShow" />
</div>
</template>
<script>
export default {
props: {
abc: String,
val: Number
},
data(){
childValue:null,
},
methods: {
isChangeShow(e){
this.$emit('ok',this.childValue)
}
}
}
</script>
关于属性prop的定义 见官方文档
2.2 如何在子组件中调用事件
如上所示,使用组件中调用父定义的事件回调需要使用this.$emit(eventName, data)
2.3 如何实现v-model双向绑定
我们在使用el-input
时,通常都会使用v-model="var"
进进动态绑定数据,用起来特别爽。但是,当我们自己开发了组件时,有时在子组件中也封装了一个input
或,也需要实现子组件与父组件都可双向修改的属性
怎么办呢?
首先我们需要了,为什么el-input
中,使用v-model="var"
就能实现对var变量的双向绑定呢?
其实v-model
可以看成是
<el-input v-bind:value="var" v-on:input="var = $event" />
或
<el-input :value="var" @input="var = $event" />
及一个单向绑定(实现父到子的数据传递)+ 加一个事件方法(实现子到父的数据传递)
v-bind
不用多说,就vue
的基本数据单向绑定语法
v-on
也不用多说,就是一个事件绑定的语法
这里我们看到了一个
$event
变量,实际上var = $event
等于在methods只定义的某个方法,如下所示的modifyVar
方法(var = $event
只是如下函数的便写)
<!-- 这里是父组件 -->
<template>
<el-input v-bind:value="var" v-on:input="modifyVar" />
</template>
<script>
export default {
data(){
return {
var: 220,
}
},
methods: {
modifyVar(e) {
this.var = e
}
}
}
</script>
而v-model
实际上就是 选则了一个特殊的属性value
进行单向绑定(假设绑定的变量名叫var
),及选择了一个特殊的事件input
进行事件绑定,而该特殊的事件input的方法的功能就是改写绑定到value的变量var
的值。
el-input
组件中,则存在this.emit('input', data)
这样的代码,来实现对父中定义的modifyVar
的调用。实际上,el-input
this.emit()存在于 <el-input>
中封装的<input>
的默认input事件的回调中。
显然,如何设计这套vue框架的人要是乐意,可以考虑选择aaa
作为特殊属性而不是value,;选择bbb
作为特殊的事件,而不是input事件。这时v-model="var"
就相当于如下:
<!-- 父组件 -->
<el-input v-bind:aaa="var" v-on:bbb="var = $event" />
当然上而存属于假设,但是,我们貌似发现了个自己开发组件,实现v-model
双向绑定的思路,同时,也可以自定义某些别的属性,进行双向绑定的实现途径,如上aaa
属性,bbb
事件。当然,vue并不推荐对普通属性进行双向绑定设计(属性都是不可直接修改的),尽管你可以参考上面轻易实现这样的需求
而子组件中,必然存在 this.emit('bbb', data)
来实现,对"var = $ event"
这段代码的调用
2.4 关于动态元素的数据双向绑定
在使用v-for
指令生成的动态元素,有时动态元素需要动态变量动态绑定v-model
,这时v-model绑定的变量无法双向关联,需要this.$set(Object, key, value)
来进行添加变量见这里