1. Vue v-model实现原理
VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
2. Object.defineProperty() 简单应用
- 简化版
var obj = { }
var name
//第一个参数:定义属性的对象。
//第二个参数:要定义或修改的属性的名称。
//第三个参数:将被定义或修改的属性描述符。
Object.defineProperty(obj, "data", {
//获取值
get: function () {
return name
},
//设置值
set: function (val) {
name = val
console.log(val)
}
})
//赋值调用set
obj.data = 'aaa'
//取值调用get
console.log(obj.data)
- 详细版
// 详细版
myVue.prototype._obverse = function (obj) { // obj = {number: 0}
var value;
for (key in obj) { //遍历obj对象
if (obj.hasOwnProperty(key)) {
value = obj[key];
if (typeof value === 'object') { //如果值是对象,则递归处理
this._obverse(value);
}
Object.defineProperty(this.$data, key, { //关键
enumerable: true,
configurable: true,
get: function () {
console.log(`获取${value}`);
return value;
},
set: function (newVal) {
console.log(`更新${newVal}`);
if (value !== newVal) {
value = newVal;
}
}
})
}
}
}
3. 如何实现v-model 双向绑定?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>双向绑定</title>
</head>
<body>
手写一个简单双向绑定<br/>
<input type="text" id="model"><br/>
<div id="modelText"></div>
</body>
<script>
var model = document.querySelector("#model");
var modelText = document.querySelector("#modelText");
var defaultName = "defaultName";
var userInfo = {}
model.value = defaultName;
Object.defineProperty(userInfo, "name", {
get: function () {
return defaultName;
},
set: function (value) {
defaultName = value;
model.value = value;
console.log("-----value");
console.log(value);
modelText.textContent = value;
}
})
userInfo.name = "new value";
var isEnd = true;
model.addEventListener("keyup", function () {
if (isEnd) {
userInfo.name = this.value;
}
}, false)
//加入监听中文输入事件
model.addEventListener("compositionstart", function () {
console.log("开始输入中文");
isEnd = false;
})
model.addEventListener("compositionend", function () {
isEnd = true;
console.log("结束输入中文");
})
</script>
</html>