- 在js文件中首先要定义一个可观测的class类
- 然后使用constructor构造器来定义一个实例
- 判断这个数据是个什么类型的数据,并且每个数据类型对应的处理逻辑是什么样的(这里一般只有数组或者对象)
- 定义一个可以监测的方法对该数据进行监测
- 封装一个Object.defineProperty方法来对数据进行劫持
- 判断这个对象的值是不是一个对象,如果是则使用递归调用自身的class类即可
附上代码:
// 数据可观测类
export class Observer {
constructor(val) {
this.val = val
if (Array.isArray(val)) {
// 可观测的数据是个数组的逻辑
} else {
// 可观测的数据是个对象的逻辑
this.monitor(val)
}
}
monitor (obj) {
let keys = Object.keys(obj) //拿到对象中的每个键
for (let i = 0; i < keys.length; i++) {
defineReacte(obj, keys[i])
}
}
}
// 定义一个可观测的方法
function defineReacte (obj, key, val) {
if (arguments.length === 2) {
val = obj[key]
}
if (typeof val === 'object') {
new Observer(val)
}
Object.defineProperty(obj, key, {
get() {
console.log(`${key}被读取了,值为${val}`);
return val
},
set(newVal) {
if (val === newVal) {
return
}
val = newVal
console.log(`${key}被修改了,修改的值为${newVal}`);
}
})
}
注意:因为这里使用的是es6的语法写的,所以在htlm页面引用的时候就不能使用常规引用js的方法了,应该在script标签上申明类型是个module,则可以进行import引入
<script type="module">
import { Observer } from './_observer.js'
let obj = new Observer({
name: '旭陌小生',
age: 18,
demo: {
a: 111
}
})
console.log(obj.val.demo.a);
obj.val.age = 20
obj.val.demo.a = 2222
</script >
控制台的输出为:
所遇到的问题及解决办法:由于chrome新版本的特性,直接打开会报错,原因是跨域所导致的
解决办法也很简单就是在编辑器中安装一个Live Server的插件,然后在编辑器中的html代码片段中右击鼠标使用Live Server打开就可以了