vue3 手写组合 API

index.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>

<body>
<script src="./index.js"></script>
<script text="text/javascript">
let proxyUser1 = shallowReactive({
name: 'he',
age: 32,
car: {
color: 'blue'
}
})
// set
// 拦截了修改数据或添加属性 name true
// proxyUser1.name = '小红'

// get set
// 拦截了读取数据 name he
// 拦截了修改数据或添加属性 name true
// proxyUser1.name += '=='

// 只拦截到读取数据,没有拦截到修改数据【只拦截get,拦截不到set】
// 拦截了读取数据 car {color: 'blue'}
// proxyUser1.car.color += '=='
// 拦截了删除数据
// delete proxyUser1.name
// 拦截get,拦截不了删除数据 【浅的监视,浅的劫持】
// delete proxyUser1.car.color

let proxyUser2 = Reactive({
name: 'he',
age: 32,
car: {
color: 'blue'
}
})
// get【拦截了读取数据car,以及car的属性color】set:拦截了修改数据或添加属性
// proxyUser2.car.color += '=='
// 拦截了读取数据 拦截了删除数据
// delete proxyUser2.car.color


// ==========================================

// 测试 shallowReadonly 与 readonly
let readonly1 = shallowReadonly({
name: '小明',
age: 12,
boll: {
color: 'blue'
}
})
// 只能读取数据,不能修改数据
// readonly1.name = '小刘'
// 深层可以修改
// readonly1.boll.color = 'red'
// 只能读取数据,不能删除数据
// delete readonly1.name

// 可以修改深层数据
// readonly1.boll.color = 'red'
// delete readonly1.boll.color
// console.log(readonly1);

let readonly2 = readonly({
name: '小明',
age: 12,
boll: {
color: 'blue'
}
})
// 不可以修改深层数据
// readonly2.boll.color = 'red'
// delete readonly2.boll.color
// console.log(readonly2);

let refData1 = shallowRef({
name: '李白',
age: 45,
car: ['奔驰','宝马']
})
// refData1.value
// 深层数据变化,不能劫持到【深层数据变化,不能实现数据响应式】
// refData1.value.age = '--'
// console.log(refData1);

let refData2 = Ref({
name: '李白',
age: 45,
car: ['奔驰','宝马']
})
// 深层数据变化,能劫持到【深层数据变化,也能实现数据响应式】
// refData2.value.car[0] = '--'
// console.log(refData2);

// =====================================
// console.log(isRef(Ref({})));
// console.log(isReactive(Reactive({})));
// console.log(isReadonly(readonly({})));
// console.log(isProxy(Reactive({})));
console.log(isProxy(readonly({})));





</script>
</body>

</html>

index.js

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
// shallowReactive(浅的监视,浅的劫持,浅的响应数据) 与 reactive(深的)
// shallowReadonly 与 readonly
// shallowRef 与 ref
// isRef, isReactive 与 isReadonly isProxy



// 定义一个handle对象
let handler = {
// Reflect.get()方法与从对象 ( target[propertyKey]) 中读取属性类似,
// 但它是通过一个函数执行来操作的。
// Reflect.get方法允许你从一个对象中取属性值
// Reflect.set 方法允许你在对象上设置属性

get(target, prop) {
if(prop === '_is_reactive') return true
let result = Reflect.get(target, prop)
console.log('拦截了读取数据', prop, result);
return result
},
// prop:将被设置的属性名或Symbol。 value:新属性值
set(target, prop, value) {
let result = Reflect.set(target, prop, value);
console.log('拦截了修改数据或添加属性', prop, result);
return result
},
// target:目标对象 property:待删除的属性名
// deleteProperty必须返回一个Boolean类型的值,表示该属性是否被成功删除
deleteProperty(target, prop) {
let result = Reflect.deleteProperty(target, prop)
console.log('拦截了删除数据', prop, result);
return result
}
}

// 定义一个 shallowReactive 函数,传入一个目标对象
function shallowReactive(target) {
// 判断target类型是不是一个object类型(可能会传普通数据)
// target instanceof Object
if (target && typeof target === 'object') {
return new Proxy(target, handler)
}
// 如果是基本数据类型,直接返回
return target
}
// 定义一个 reactive 函数,传入一个目标对象
function Reactive(target) {
if (target && typeof target === 'object') {
// 对数组或是对象中所有的数据进行 reactive 的递归处理(原因:reactive是深度响应式数据)
// 1. 当前的数据是不是数组
// Array.isArray(target)
if (target instanceof Array) {
target.forEach((item, index) => {
target[index] = Reactive(item)
})
} else {
// 2.再判断当前的数据是不是对象
// 对象的数据也要进行遍历操作
Object.keys(target).forEach(key => {
target[key] = Reactive(target[key])
})
}
return new Proxy(target, handler)
}
// 如果是基本数据类型,直接返回
return target
}

// =============================
// 定义一个handlerReadonly 处理器
let handlerReadonly = {
get(target, prop) {
if(prop === '_is_readonly') return true
let result = Reflect.get(target, prop)
console.log('Readonly:拦截了读取数据', prop, result);
return result
},
set(target, prop, value) {
// let result = Reflect.set(target, prop, value);
console.warn('只能读取数据,不能修改数据');
return true
},
deleteProperty(target, prop) {
// let result = Reflect.deleteProperty(target, prop)
console.warn('只能读取数据,不能删除数据');
return true
}
}

// 定义一个 shallowReadonly 函数
function shallowReadonly(target) {
if (target && typeof target === 'object') {
return new Proxy(target, handlerReadonly)
}
return target
}
// 定义一个 readonly 函数
function readonly(target) {
if (target && typeof target === 'object') {
if (target instanceof Array) {
target.forEach((item, index) => {
// 递归处理item
target[index] = readonly(item)
})
} else {
Object.keys(target).forEach(key => {
target[key] = readonly(target[key])
})
}
return new Proxy(target, handlerReadonly)
}
return target
}

// ==========================================

// 定义一个 shallowRef 函数
function shallowRef(target) {
return {
// 保存target
_value: target,
get value() {
console.log('劫持到读取数据');
return this._value
},
set value(val) {
console.log('劫持到修改数据,准备更新界面',val);
this._value = val
},
}
}
// 定义一个 Ref 函数
function Ref(target) {
target = Reactive(target)

return {
_is_ref:true, //标识当前对象为ref对象
// 保存target
_value: target,
get value() {
console.log('劫持到读取数据');
return this._value
},
set value(val) {
console.log('劫持到修改数据,准备更新界面',val);
this._value = val
},
}
}
// ==========================================




// 定义一个 isRef ,判断当前的对象是不是 ref 对象
function isRef(obj) {
return obj && obj._is_ref

}
// 定义一个 isReactive ,判断当前的对象是不是 reactive 对象
function isReactive(obj) {
return obj && obj._is_reactive

}
// 定义一个 isReadonly ,判断当前的对象是不是 readonly 对象
function isReadonly(obj) {
return obj && obj._is_readonly

}
// 定义一个 isProxy ,判断当前的对象是不是 readonly 对象 或 reactive 对象
function isProxy(obj) {
return isReactive(obj) || isReadonly(obj)

}

-------------本文结束感谢您的阅读-------------

我的传送门:个人网站GithubGitee