1.自己实现一个v-model
Index.vue
<template>
<div>
<p>vue高级特性</p>
<hr>
<!-- 自定义 v-model -->
<p>{{name}}</p>
<CustomVModel v-model="name"></CustomVModel>
</div>
</template>
<script>
import CustomVModel from './VModel'
export default {
components: {
CustomVModel
},
data () {
return {
name: '夹心'
}
}
}
</script>
<style>
</style>
VModel.vue
<template>
<input type="text"
:value = "text"
@input = "$emit('change', $event.target.value)">
</template>
/* 1.上面的input使用了:value而不是v-model
2.上面的change和model.event要对应起来
3.text属性要对应起来
*/
<script>
export default {
model: {
prop: 'text',
event: 'change'
},
props: {
text: String,
default () {
return ''
}
}
}
</script>
<style>
</style>
2.V-model作用
v-model本质上不过是语法糖, 可以用v-model指令在表单上及元素上创建双向数据绑定
- 它会根据控件类型自动选取正确的方法来更新元素
- 它负责监听用户的输入数据以更新数据,并对一些极端场景进行一些特殊处理
- v-model会忽略所有表单元素的value, checked, selected特性的初始值,而总是将Vue实例的数据作为数据来源,因此我们应该通过Javascript在组件的data选项中声明初始值
- 4.v-model在内部为不同的输入元素使用不同的属性并抛出不同的事件
- text和textarea元素使用value属性和input事件
- checkbox和radio使用checked属性和change事件
- select字段将value作为prop并将change作为事件
3.V-Model的实现原理
v-model只不过是一个语法糖而已,真正实现靠的还是
- v-bind: 绑定响应式数据
- 触发oninput事件并传递数据
<input v-model="sth" />
<input :value="sth" @input="sth = $event.target.value" />
- 自html5开始, input每次输入都会触发oninput事件, 所以输入时input的内容会被绑定到sth中, 于是sth的值就被改变
$event 指代当前触发的事件对象
$event.target指代当前触发的事件对象的dom
$event.target.value就是当前dom的value值
在@input方法中, value => sth
在:value中, sth => value
4.Vue2.0双向绑定的缺陷
Vue2.0的数据响应式采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter、getter,但是它并算是实现数据的响应式的完美方案,主要有以下缺陷:
1.Vue实例创建后, 无法检测到对象属性的新增或者删除, 只能追踪到数据是否修改
2.不能监听数组变化
vue 实例创建后,无法检测到对象属性的新增或删除,只能追踪到数据是否被修改(Object.defineProperty只能劫持对象的属性)。
1.当创建一个Vue实例时,将遍历所有DOM对象,并为每个数据属性添加了get和set。get和set 允许Vue观察数据的更改并触发更新。但是,如果在Vue实例化后添加(或删除)一个属性,这个属性不会被vue处理,改变get和set。
解决方案:
Vue.set(obj, propertName/index, value)
// 响应式对象的子对象新增属性,可以给子响应式对象重新赋值
data.location = {
x: 100,
y: 100
}
data.location = {...data, z: 100}
2.不能监听数组的变化
Vue在实现数组的响应式时,使用了一些hack,把无法监听数组的情况通过重写数组的部分方法来实现响应式,这也只限制在数组的push/pop/shift/unshift/splice/sort/reverse七个方法,其他数组方法及数组的使用则无法检测到。
5. Vue3.0 实现数据双向绑定的方法
vue3.0 实现数据双向绑定是通过Proxy
Proxy是 ES6 中新增的一个特性,翻译过来意思是"代理"。 Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
使用 Proxy 的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。