v-model和双向绑定 原理
1. v-model原理 :是基于@input/change和v-bind:value封装的语法糖@input/change底层是 JS事件监控 V同步Mv-bind:value底层是JS的Object.defineProperty监控 M同步V2.VUE双向绑定/响应式原理通过触发事件打印vue模型数据,发现每个模型数据都有getter、setter方法,代表使用了Object.definePr
·
1. v-model原理 :是基于@input/change和v-bind:value封装的语法糖
@input/change底层是 JS事件监控 V同步M
v-bind:value底层是 JS的 Object.defineProperty监控 M同步V
<div id="root">
<h1>v-model</h1>
<input type="text" v-model="msg" />
<h1>【v-bind:value】和【@input】 好理解版本</h1>
<input type="text" v-bind:value="msg2" @input="changeMsgFn" />
<h1>【v-bind:value】和【@input】 简写</h1>
<input type="text" v-bind:value="msg3" @input="msg3 = $event.target.value" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const vm = new Vue({
el: '#root',
data: {
msg: '你好',
msg2: '你好2',
msg3: '你好3'
},
methods: {
changeMsgFn(evt) {
// console.log(evt.target.value)
this.msg2 = evt.target.value
}
}
})
</script>
2.VUE双向绑定/响应式原理
通过触发事件打印vue模型数据,发现每个模型数据都有getter、setter方法,代表使用了 Object.defineProperty进行数据劫持
①语法: 仅监控你写的属性,数组对象监控不到里面键的变化
语法单词 | configurable | enumerable | value | writable | get | set |
---|---|---|---|---|---|---|
作用 | 能否删除 | 能否枚举/遍历 | 重置默认值 | 能否修改值 | 劫持获取 | 劫持更新 |
数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
数据描述符:
<script>
// 1 定义模型
let data = {
uname: '张三',
sex:'男'
}
// 2 数据劫持 监控data中的uname属性并进行操作
Object.defineProperty(data, 'uname', {
configurable: false, // 能否删除:true是,false否
enumerable: false, // 能否枚举/遍历:true是,false否
value: '你好', // 重置uname默认值
writable: true, // 能够修改值:true是,false否
})
// 3 练习 数据描述符(也就是劫持 控制数据后期的操作
console.log('能否删除,删前', data)
delete data.uname
console.log('能否删除 删后', data)
for (let key in data){
console.log('枚举结果:', key, data[key]) // data.uname、data.sex
}
console.log('最新数据:', data)
data.uname = '李四'
console.log('更新后的数据:', data)
</script>
存取数据描述符:
<script>
// 1 定义模型
let data = {
uname: '李焕英',
sex: '女',
}
// 2 数据劫持
let tmp = data.uname // 留心传值 互不影响 否则无限死循环
Object.defineProperty(data, 'uname', {
configurable: true,
enumerable: true,
get() { // 获取uname数据时运行get方法 V-M
// 发现:console.log(data.uname) 居然返回undefined
// 原因:因为uname属性被监控了,遇到打印获取动作先走get过滤,然后再返回
// 留心:get返回什么就是什么,因为它是数据劫持者
// 所以:你没写return 就是undefined打印出来
// 思考:return什么呢
// 回答:data.uname
// return data.uname
// 发现:上述语法死循环
// 原因:第一次get外面使用,触发get方法,然后get方法自己用,触发get方法; 自己用 触发get方法....
// 解决:在外面定义临时变量存放数据 get里面返回
return tmp
},
set(newval) { // 更改数据时运行set方法 同步到视图 M-V
console.log(`键被set修改成:`, newval)
// 发现:更新数据,可以触发set方法
// 但是:更新完了之后,外面打印还是旧数据
// 原因:为了避免死循环,不能直接操作监控的数据,所以我们返回的tmp
// 因此:更新后也得同步tmp
tmp = newval
// 发现:好了
// 铺垫:后期我们就在set方法中劫持数据更新同步到视图
// document.querySelector(选择器).value = newval
}
})
console.log(data.uname) //李焕英
data.uname = '来试试更新'
console.log(data.uname) //来试试更新
</script>
更多推荐
已为社区贡献1条内容
所有评论(0)