通过Object.defineProperty来实现响应式
const obj = {name: 'zxt',age: '18',sex: 'nan',son: {name: 'zzz',sex: 'nan'},arr: [1, 2, 3],}/*** 监听对象每一项的读取与写入* @param {*} obj 对象* @param {*} prop 属性* @param {*} value 值*/function defineReactive(obj, prop, value) {if (typeof value === "object") {forIn(obj[prop]);}Object.defineProperty(obj, prop, {get() {console.log('读');return value;},set(nowValue) {console.log('写');value = nowValue;render();}})}/*** 迭代对象的每一个属性* @param {*} obj*/function forIn(obj) {/*** 当为数组是,为其绑定数组异变方法*/if (Array.isArray(obj)) {obj.__proto__ = arrMethods;return;}if (typeof obj == 'object') {for (const key in obj) {defineReactive(obj, key, obj[key]);};}}function render() {console.log('页面渲染啦');}/*** 数据的变异方法*/let arrProto = Array.prototype;let arrMethods = Object.create(arrProto);['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach((ele) => {arrMethods[ele] = function () {arrProto[ele].call(this, ...arguments)render();}})/*** $set*/function $set(who, revise, value) {if (Array.isArray(who)) {who.splice(revise, 1, value);return value;}defineReactive(who,revise,value)return value;// render();}/*** $delete*/function $delete(obj ,target){if(Array.isArray(obj)){obj.splice(target,0);return;}delete obj[target] ;return;}forIn(obj);obj.son.name = 123;
利用Object.defineProperty实现响应式的劣势
- 天生就需要进行递归
- 监听不到数组不存在的索引的改变
- 监听不到数组长度的改变
- 监听不到对象的增删
