跳转到内容
返回

vue原理学习1-响应式

开头

响应式

概念

解释

...
<body>
  <div id="name"></div>
  <script>
    let div = document.querySelector("#name");
    let name = "刷新";
    // 渲染数据到页面
    let render = (dom, val) => {
      dom["textContent"] = val;
    };
    // 初始化
    render(div, name);
    // 修改name后再次渲染
    name = "shuaxin";
    render(div, name);
  </script>
</body>
...
...
<body>
  <div id="app">{{name}}</div>
  <script src="./vue.js"></script>
  <script>
    let app = new Vue({
      el: "#app",
      data: {
        name: "刷新",
      },
    });
  </script>
</body>
...

关于vue的工作流程

在通过Vue构造函数实例化对象的过程中,vue同时做了2件事

1.数据拦截

2.编译

数据驱动

关于响应式的原理

代码实现

// 可以操作数组本身内容的api
const methodsToPatch = [
  "push",
  "pop",
  "shift",
  "unshift",
  "splice",
  "sort",
  "reverse",
];
// 创建一个新的数组对象,继承Array
let newArr = Object.create(Array.prototype);
// 遍历methodsToPatch,拦截每一个方法
methodsToPatch.forEach(method => {
  // 保存的是原Array的对应调用的方法
  let oldMethod = newArr[method];
  Object.defineProperty(newArr, method, {
    // 不可以枚举,不可被for in循环到
    enumerable: false,
    // 可以被删除
    configurable: true,
    // 可被重写
    writable: true,
    // 将访问的元素换成函数,在这里执行通知watcher更新视图的操作
    value: function mutator(...rest) {
      // (3) [1, 2, 3]  4
      console.log(this, ...rest);
      // 将函数的this指向绑定到当前操作的数组上,然后把调用该函数的参数一并传递过去
      let res = oldMethod.apply(this, rest);
      return res;
    },
  });
});
// 测试
let data = {
  name: "vuejs",
  sx: {
    sex: "",
    name: "shuaxin",
  },
  arr: [1, 2, 3],
};
// 实现对数据的拦截
let defineReactive = (obj, key, value) => {
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      // 下面代码替代增加watcher操作
      console.warn("get");
      return value;
    },
    set(newVal) {
      // 以下代替通知watcher更新视图操作
      console.warn("set");
      value = newVal;
    },
  });
};
// 判断传递的data的每个属性的类型
// 这里会有三种类型:对象,基本数据类型,数组
let observe = obj => {
  if (!obj || typeof obj !== "object") {
    return;
  }
  Object.keys(obj).forEach(key => {
    // 还是一个对象,递归调用该函数
    if (typeof obj[key] === "object" && obj[key] instanceof Array !== true) {
      console.warn("对象");
      observe(obj[key]);
    } else if (obj[key] instanceof Array) {
      // 是数组的话,改变数组原型为我们新创建的数组对象newArr
      console.warn("数组");
      obj[key].__proto__ = newArr;
      // 对内部的元素执行拦截
      defineReactive(obj, key, obj[key]);
    } else {
      // 基本数据直接进行拦截
      console.warn("基本数据类型");
      defineReactive(obj, key, obj[key]);
    }
  });
};
// 初始化
observe(data);
// 执行该操作的时候,控制台会打印 get
data.arr.push(4);
console.log(data.arr);


上一篇
初探nginx
下一篇
资源推荐