定义
访问或者修改对象的某个属性时,在访问和修改属性值时,除了执行基本的数据获取和修改操作意外,还基于数据的操作行为,以数据为基础去执行额外的操作
为什么要进行数据劫持
减少dom操作
demo:实现input输入的时候,改变p标签的值
1 | <input type="text" id="text"> |
普通方法:
在input输入的时候,获取p的值,发现改变再操作dom修改p标签的值
使用数据劫持,定义对象,对象属性值发生改变,在操作dom修改p标签的值
实现原理
defineProperty,此方法详解见此章节
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37var text = document.getElementById('text')
var show = document.getElementById('show')
var oData = {
name: '1'
}
text.oninput = function() {
oData.name = this.value
}
function upData() {
show.innerHTML = oData.name
}
upData()
function Observer(data) {
if(!data || typeof data != 'object') {
return data
}
// Object.keys(data)不能获取数组的索引,所以Observer无法实现数组数据监听
Object.keys(data).forEach(item => {
definedReactive(data, item, data[item])
})
}
function definedReactive(data, key, val) {
Observer(val) //递归深度监听数据变化
Object.defineProperty(data, key, {
get() {
return val
},
set(newValue) {
if(val == newValue) {
return
}
val = newValue
upData()
}
})
}
Observer(oData)Proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24var text = document.getElementById('text')
var show = document.getElementById('show')
var oData = {
name: '1'
}
var handler = {
get() {
},
set: function(obj, prop, value) {
// obj[prop] = value
Reflect.set(obj, prop, value);
upData()
return true
}
}
upData()
var proxy = new Proxy(oData, handler)
text.oninput = function() {
proxy.name = this.value
}
function upData() {
show.innerHTML = oData.name
}
两种方法优缺点,defineProperty不能处理数组,proxy时es6的语法兼容性有要求,并且不能递归处理