ソースを参照

响应式数据对于数组的处理讲解完成

HcySunYang 7 年 前
コミット
3df76e470a
1 ファイル変更64 行追加0 行削除
  1. 64 0
      note/7Vue的初始化之数据响应系统.md

+ 64 - 0
note/7Vue的初始化之数据响应系统.md

@@ -1664,6 +1664,70 @@ function copyAugment (target: Object, src: Object, keys: Array<string>) {
 
 我们知道 `copyAugment` 函数的第三个参数 `keys` 就是定义在 `arrayMethods` 对象上的所有函数的键,即所有要拦截的数组变异方法的名称。这样通过 `for` 循环对其进行遍历,并使用 `def` 函数在数组实例上定义与数组变异方法同名的且不可枚举的函数,这样就实现了拦截操作。
 
+总之无论是 `protoAugment` 函数还是 `copyAugment` 函数,他们的目的只有一个:**把数组实例与代理原型或与代理原型中定义的函数联系起来,从而拦截数组变异方法**。下面我们在回到 `Observer` 类的 `constructor` 函数中,看如下代码:
+
+```js
+if (Array.isArray(value)) {
+  const augment = hasProto
+    ? protoAugment
+    : copyAugment
+  augment(value, arrayMethods, arrayKeys)
+  this.observeArray(value)
+} else {
+  // 省略...
+}
+```
+
+可以发现在 `augment` 函数调用语句之后,还以该数组实例作为参数调用了 `Observer` 实例对象的 `observeArray` 方法:
+
+```js
+this.observeArray(value)
+```
+
+这句话的作用是什么呢?或者说 `observeArray` 方法的作用是什么呢?我们知道,当被观测的数据(`value`)是数组时,会执行 `if` 语句块的代码,并调用 `augment` 函数从而拦截数组的变异方法,这样当我们尝试通过这些变异方法修改数组时是会触发相应的依赖(`观察者`)的,比如下面的代码:
+
+```js
+const ins = new Vue({
+  data: {
+    arr: [1, 2]
+  }
+})
+
+ins.arr.push(3) // 能够触发响应
+```
+
+但是如果数组中嵌套了其他的数组或对象,那么嵌套的数组或对象却不是响应的:
+
+```js
+const ins = new Vue({
+  data: {
+    arr: [
+      [1, 2]
+    ]
+  }
+})
+
+ins.arr.push(1) // 能够触发响应
+ins.arr[0].push(3) // 不能触发响应
+```
+
+上面的代码中,直接调用 `arr` 数组的 `push` 方法是能够触发响应的,但调用 `arr` 数组内嵌套数组的 `push` 方法是不能触发响应的。为了使嵌套的数组或对象同样是响应式数据,我们需要递归的观测那些类型为数组或对象的数组元素,而这就是 `observeArray` 方法的作用,如下是 `observeArray` 方法的全部代码:
+
+```js
+/**
+  * Observe a list of Array items.
+  */
+observeArray (items: Array<any>) {
+  for (let i = 0, l = items.length; i < l; i++) {
+    observe(items[i])
+  }
+}
+```
+
+可以发现 `observeArray` 方法的实现很简单,只需要对数组进行遍历,并对数组元素逐个应用 `observe` 工厂函数即可,这样就会递归观测数组元素了。
+
+##### 数组的特殊性
+