一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
前情提要
我们都知道在vue中数据是响应式的,是双向绑定的。那么就有了疑问:v-model指令是响应式的吗?
答:不是。
什么是响应式?(简讲,后面会有文章深度剖析)
- 首先我们要了解响应式的概念是什么?
- 总结一句话就是:当视图模型(VM)中的数据模型(M)发生改变时, 视图(V)就会进行更新。
- 而实现原理是:利用 Object.defineProperty 进行 数据劫持 同时结合观察者模式(发布 / 订阅模式)来实现数据双向绑定。
- 数据劫持:利用Object.defineProperty 中的 getter/setter,数据改变就执行 watcher
- 发布/订阅模式:它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
v-model到底是什么?
- v-model实际只是一个语法糖而已。主要依赖value属性的绑定和input原生事件的触发来实现。
- 给组件添加v-model指令时,默认会把value作为组件的属性,然后把input值作为给组件绑定事件时的事件名。
- 等价代码:
<input v-model="str" />
// 等价于
<input :value="str" @input="$event.target.value" />
// input标签在HTML5中新增了oninput事件,与onchange事件不同的是,会在每次输入动作时触发。而onchange是在输入完成后才会触发。所以这样就能保证每次输入即页面展示。
复制代码
- 上面的那种是指在原生标签中的表现。还有一种是在自定义组件中的表现。主要是通过配置model实现v-model的prop属性与event事件的自定义
// 组件调用:
<customComponent v-model="test"></customComponent>
// 自定义组件内部
<template>
<div>
<div v-for="item in list" :key="item" @click="change(item)" :class="item == currentValue ? 'actived' : ''">
{{ item }}
</div>
</div>
</template>
<script>
export default {
//定义实现v-modal的属性与事件
model: {
prop: 'value',
event: 'change'
},
props: {
// 绑定的值
value: {
type: [String, Number],
defalut: ''
},
// 数据源
list: {
type: Array,
default: () => []
}
},
watch: {
value(newValue) {
this.currentValue = newValue;
}
},
data() {
return {
// 当前选中的值
currentValue: ''
}
},
created() {
// 组件初始化的时候先获取一次值
this.currentValue = this.value
},
methods: {
change(item) {
// 发送change事件,父组件会将接收到的值赋给组件定义的变量。
// 同时也可以在父组件里显示的调用change事件。
this.$emit('change', item)
}
}
}
</script>
<style scoped>
.actived {
background: red;
color: white;
}
</style>
复制代码