分享

VUE3.0-手写实现组合API

 印度阿三17 2021-03-28

1.shallowReactive 与 reactive

1.1shallowReactive-浅监听

// 定义一个shallowReactive函数,传入一个目标对象
    function shallowReactive(target) {  // 判断当前的目标对象是不是object类型(对象/数组)
      if (target && typeof target === 'object') {return new Proxy(target, {  // 获取属性值
          get(obj, key) {console.log('拦截了get');
            if(key=='_is_reactive'){return true
            };
            return Reflect.get(obj, key);
          },
          // 修改属性值或者添加属性
          set(obj, key, value) {console.log('拦截了set');
            return Reflect.set(obj, key, value);
          },
          // 删除某个属性
          deleteProperty(obj, key) {console.log('拦截了deleteProperty');
            return Reflect.deleteProperty(obj, key);
          }
        })
      }
      // 如果传入的是基本数据类型,那么就直接返回
      return target;
    };

     let user = shallowReactive({   name: '张三',
       wife: { name: '张三老婆'
       }
     });
    // 拦截到了读和写的数据
     console.log(user.name);
     user.name = '李四';
     console.log(user.name);


    // 拦截到了读取的数据,但是拦截不到写的数据
     user.wife.name = '张三媳妇';
     console.log(user.wife.name);

    // 拦截到了删除数据
     delete user.name;

    // 只拦截到了读,但是拦截不到删除
     delete user.wife.name

1.2reactive-深监听

// 定义一个reactive函数,传入一个目标对象
    function reactive(target) {  // 判断当前的目标对象是不是object类型(对象/数组)
      if (target && typeof target === 'object') {// 对数组/对象中所有的数据进行reactive的递归处理
        // 判断当前的数据是不是数组
        if (Array.isArray(target)) {  target.forEach((item, index) => {// 数组的数据要进行遍历操作
            target[index] = reactive(item);
          })
        } else {  // 判断当前的数据是不是对象
          Object.keys(target).forEach(key => {target[key] = reactive(target[key]);
          })
        }
        return new Proxy(target, {  // 获取属性值
          get(obj, key) {console.log('拦截了get');
            if(key=='_is_reactive'){return true
            };
            return Reflect.get(obj, key);
          },
          // 修改属性值或者添加属性
          set(obj, key, value) {console.log('拦截了set');
            return Reflect.set(obj, key, value);
          },
          // 删除某个属性
          deleteProperty(obj, key) {console.log('拦截了deleteProperty');
            return Reflect.deleteProperty(obj, key);
          }
        })
      }
      // 如果传入的是基本数据类型,那么就直接返回
      return target;
    };
    
    let user = reactive({  name: '张三',
      wife: {name: '张三老婆'
      }
    });

    // 拦截到了读写的数据
     console.log(user.name);
     user.name = '李四';
     console.log(user.name);

    // 拦截到了读写的数据
     console.log(user.wife.name);
     user.wife.name = '张三媳妇';
     console.log(user.wife.name);

    // 拦截到了删除的数据
     delete user.name;

    // 拦截到了删除的数据
    delete user.wife.name

shallowReadonly 与 readonly

shallowReadonly

    // 定义一个shallowReadonly函数
    function shallowReadonly(target) {  // 判断当前的数据是不是对象
      if (target && typeof target === 'object') {return new Proxy(target, {  get(obj, key) {console.log('拦截到get了');
            if(key=='_is_readonly'){return true
            };
            return Reflect.get(obj, key);
          },
          set(obj, key, value) {console.warn('只能读取数据,不能修改数据或者添加数据');
            return true;
          },
          deleteProperty(obj, key) {console.log('只能读取数据,不能删除数据');
            return true;
          }
        })
      };
      return target;
    };

let user = shallowReadonly({  name: '张三',
      likes: ['篮球', '足球']
    });
    // 可以读取
    console.log(user.name);
    // 不能修改
    user.name = '李四';
    // 不能删除
    delete user.name;

    // 可以读取
    console.log(user.likes[0]);
    // 拦截到了读取,可以修改
    user.likes[0] = '羽毛球';
    // 拦截到了读取,可以删除
    delete user.likes[0];

readonly

    // 定义一个readonly函数
    function readonly(target) {  // 判断当前的数据是不是对象
      if (target && typeof target === 'object') {if (Array.isArray(target)) {// 判断是不是数组
          target.forEach((item, index) => {target[index] = readonly(item);
          })
        } else {// 判断是不是对象
          Object.keys(target).forEach(key => {target[key] = readonly(target[key])
          })
        }
        return new Proxy(target, {  get(obj, key) {console.log('拦截到get了');
            if(key=='_is_readonly'){return true
            };
            return Reflect.get(obj, key);
          },
          set(obj, key, value) {console.warn('只能读取数据,不能修改数据或者添加数据');
            return true;
          },
          deleteProperty(obj, key) {console.log('只能读取数据,不能删除数据');
            return true;
          }
        })
      };
      return target;
    };

    let user = readonly({  name: '张三',
      likes: ['篮球', '足球']
    });
    // 可以读取
    console.log(user.name);
    // 不能修改
    user.name = '李四';
    // 不能删除
    delete user.name;

    // 可以读取
    console.log(user.likes[0]);
    // 拦截到了读取,不可以修改
    user.likes[0] = '羽毛球';
    // 拦截到了读取,不可以删除
    delete user.likes[0];

shallowRef 与 ref

shallowRef

  // 定义一个shallowRef函数
    function shallowRef(target) {  return {_is_ref: true, // 用来标识是ref对象
        // 保存target数据
        _value: target,
        get value() {  console.log('劫持到了读取数据');
          return this._value;
        },
        set value(val) {  console.log('劫持到了修改/设置数据');
          this._value = val;
        }
      }
    };
    let user = shallowRef({  name: '张三',
      wife: {name: '张三老婆'
      }
    });

    // 劫持到了读取数据
    console.log(user.value);

    // 劫持到了修改数据
    user.value = {  name: '李四',
      wife: {name: '李四老婆'
      }
    };

    // 劫持到了读取数据,劫持不到修改数据
    user.value.wife = '张三媳妇'

ref

// 定义一个reactive函数,传入一个目标对象
    function reactive(target) {  // 判断当前的目标对象是不是object类型(对象/数组)
      if (target && typeof target === 'object') {// 对数组/对象中所有的数据进行reactive的递归处理
        // 判断当前的数据是不是数组
        if (Array.isArray(target)) {  target.forEach((item, index) => {// 数组的数据要进行遍历操作
            target[index] = reactive(item);
          })
        } else {  // 判断当前的数据是不是对象
          Object.keys(target).forEach(key => {target[key] = reactive(target[key]);
          })
        }
        return new Proxy(target, {  // 获取属性值
          get(obj, key) {console.log('拦截了get');
            return Reflect.get(obj, key);
          },
          // 修改属性值或者添加属性
          set(obj, key, value) {console.log('拦截了set');
            return Reflect.set(obj, key, value);
          },
          // 删除某个属性
          deleteProperty(obj, key) {console.log('拦截了deleteProperty');
            return Reflect.deleteProperty(obj, key);
          }
        })
      }
      // 如果传入的是基本数据类型,那么就直接返回
      return target;
    };

    // 定义一个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('劫持到了修改/设置数据');
          this._value = val;
        }
      }
    };

    let user = ref({  name: '张三',
      wife: {name: '张三老婆'
      }
    });

    // 劫持到了读取数据
    console.log(user.value);

    // 劫持到了修改数据
    user.value = {  name: '李四',
      wife: {name: '李四老婆'
      }
    };

    // 劫持到了读取数据
    user.value.wife = '张三媳妇'

isRef , isReactive , isReadonly , isProxy

isRef

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

isReactive

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

isReadonly

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

isProxy

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


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多