先看这一段代码

    1. // 拿到数组的原型
    2. const oldArrayProperty = Array.prototype
    3. // 创建一个新的对象,原型指向oldArrayProperty,这么做为的是不污染全局的Array原型
    4. // Object.create 和 new Objcet() 的区别在知识库 前端知识点中有
    5. const arrProto = Object.create(oldArrayProperty)
    6. // 给arrProto增加方法,例如push
    7. arrProto.push = function() {
    8. updateView() //这里触发更新视图
    9. Array.prototype.push.call(this, ..arguments) // 这里才是真正执行push方法
    10. }

    然后修改1-4中的代码

    1. /* 模拟更新视图 -- 这个不变 */
    2. function updateView() {
    3. console.log('视图更新')
    4. }
    1. const oldArrayPrototype = Array.prototyoe
    2. const arrProto = Object.create(oldArrayPrototype)
    3. // 这里没写全所有的数组方法
    4. !!['push', 'pop', 'shift', 'unshift', 'splice', 'slice'].forEach(methodName => {
    5. arrProto[methodName] = function() {
    6. updateView() // 更新视图
    7. oldArrayPrototype[methodName].call(this, ...arguments)
    8. }
    9. })
    10. /* 监听对象属性 */
    11. function observer(target) {
    12. // 只监听对象和数组
    13. if (typeof target !== 'object' || target == null) {
    14. return target
    15. }
    16. // 对数组进行特殊处理
    17. // 这样,操作target是数组的时候,就是使用的是我们自定义的方法了
    18. if(Array.isArray(target)) {
    19. target.__proto__ = arrProto
    20. }
    21. // 重新定义各个属性
    22. for (let key in target) {
    23. defineReactive(target, key, target[key])
    24. }
    25. }
    1. /* 对属性重新定义,并且监听 -- 这个也不变 */
    2. function defineReactive(target, key, val) {
    3. // 深度监听
    4. observer(val) // 因为val不一定是值,也可能是一个对象或数组
    5. Object.defineProperty(target, key, {
    6. get() {
    7. return val
    8. },
    9. set(newVal) {
    10. if (newVal !== val) {
    11. // 深度监听 新增加的如果是对象和数组也要加入监听
    12. observer(newVal)
    13. // 设置新值
    14. val = newVal
    15. }
    16. // 更新视图
    17. updateView()
    18. }
    19. })
    20. }