Appearance
双向绑定
模拟控制一个值
javascript
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue</title>
</head>
<body>
<div id="content"></div>
<input type="text" id="input">
</body>
<script>
let obj = {}
let temp = {};
document.getElementById("content").innerHTML = obj.name
// 'name' 代表属性
Object.defineProperty(obj,'name',{
configurable:false, //是否可删除
// writable:true,// 是否可赋值(如果使用set方法,则不能使用)
enumerable:true, // 是否可枚举,也是就for..in..
// value:1,// 值(如果使用get方法,则不能使用)
get(){ // 取obj的name会触发get方法
return temp['name']
},
set(val){// 给obj赋值会触发get方法
// console.log(val);
temp['name'] = val // 改变temp的结果
input.value = val // 将值赋值给输入框
}
});
input.value = obj.name // 页面一加载,会将调用get方法
input.addEventListener('input',function(){ // 等待输入框的变化
obj.name = this.value // 当值变化时会调用set方法
document.getElementById("content").innerHTML = obj.name
})
</script>
</html>
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
37
38
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
37
38
vue会循环data中的数据(数据劫持) 依次的增加getter和setter
javascript
let vm = new Vue({
el:'#content',
data:{
a:{}
}
})
1
2
3
4
5
6
2
3
4
5
6
但是这时候我想添加一个school方法,发现没有产生getter和setter
1.1 方法一 $set
使用变量时 先要初始化,否则新加的属性不会导致页面刷新
javascript
vm.$set(vm.a,"school",'1')// 此方法可以给对象添加响应式的变化
1
1.2 方法二 替换原对象
javascript
vm.a = {"school":"heihei",age:8};
1
1.3 数组问题
去改变数组中的某一项监控不到的,也不能改变数组的长度方法
javascript
let vm = new Vue({
el:'#content',
data:{
a:[1,2,3,4,5,6]
}
})
1
2
3
4
5
6
2
3
4
5
6
错误方法
javascript
vm.a[0] =100
vm.a.length -=2
1
2
2
变异方法:pop push shift unshit sort reserve splice
javascript
vm.a = vm.a.map(item=>item*3)
1
双向绑定手写
思考为什么vue2中的数组不可以直接操作
采用Object.defineProperty去实现
javascript
let obj = {
name: "wjw",
info: {
age: 12,
height: 100,
},
};
function render() {
console.log("====================================");
console.log("数据更新了");
console.log("====================================");
}
function objsever(obj) {
if (typeof obj === "object") {
for (const key in obj) {
if (Object.hasOwnProperty.call(obj, key)) {
defineReactive(obj, key, obj[key]);
}
}
}
}
function defineReactive(data, key, value) {
objsever(value);
Object.defineProperty(data, key, {
get() {
return value;
},
set(newValue) {
objsever(newValue);
if (value !== newValue) {
render();
value = newValue;
}
},
});
}
objsever(obj);
obj.name = "myq";
function $set(data,key,value){
defineReactive(data,key,value);
}
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
37
38
39
40
41
42
43
44
45
46
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
37
38
39
40
41
42
43
44
45
46
- 如果给对象新增属性 是不会被监听的$set
- 如果想给对象增加一个不存在的属性 obj.info =
javascript
function render() {
console.log("====================================");
console.log("数据更新了");
console.log("====================================");
}
let obj = [1,2,3]
let methods = ['pop','shift','unshift','sort','reverse','splice','push'];
// 先获取到原来原型上的方法
let arrayProto = Array.prototype;
// 创建一个自己的原型,并且重写methods这些方法
let proto = Object.create(arrayProto);
methods.forEach(method=>{
proto[method] = function(){ // AOP
render();
arrayProto[method].call(this,...arguments);
}
})
function observer(obj){
if(Array.isArray(obj)){
obj.__proto__ = proto;
return;
}
}
observer(obj)
obj.push(123)
console.log('====================================');
console.log(obj);
console.log('====================================');
function $set(data,key,value){
if(Array.isArray(data)){
return data.splice(key,1,value);
}
}
$set(obj,0,100);
// 不支持数据长度变化,也不支持数组的内容发现变化 必须通过上面的方法
来触发更新 或者替换一个数组
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
37
38
39
40
41
42
43
44
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
37
38
39
40
41
42
43
44
使用proxy去实现
javascript
function render() {
console.log('====================================');
console.log("视图更新");
console.log('====================================');
}
// 可以支持数组,而且不会区分是对象还是数组
// 兼容性vue 3.0 会采用如果支持proxy 就使用proxy 不支持还是使用Object.definePropert
let obj = {
name:'wjw',
age: 9
}
let hander = {
get(target, key) {
if (typeof target[key] == 'object' && typeof target[key] !== null) {
return new Proxy(target[key], hander);
}
return Reflect.get(target, key);
},
set(target, key, value) {
if(key==='length') return true;
render();
return Reflect.set(target, key, value);
},
}
let proxy = new Proxy(obj, hander);
proxy.age = 100;
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
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