Vue2实现原理
# 响应式原理
导出vue
构造函数
import { initMixin } from "./init";
function Vue(options) {
this._init(options);
}
initMixin(Vue); // 给原型上新增_init方法
export default Vue;
1
2
3
4
5
6
7
2
3
4
5
6
7
init
方法中初始化Vue
状态
import { initState } from "./state";
export function initMixin(Vue) {
Vue.prototype._init = function (options) {
const vm = this;
vm.$options = options;
// 初始化状态
initState(vm);
};
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
根据不同属性进行初始化操作
export function initState(vm) {
const opts = vm.$options;
if (opts.props) {
initProps(vm);
}
if (opts.methods) {
initMethod(vm);
}
if (opts.data) {
// 初始化data
initData(vm);
}
if (opts.computed) {
initComputed(vm);
}
if (opts.watch) {
initWatch(vm);
}
}
function initProps() {}
function initMethod() {}
function initData() {}
function initComputed() {}
function initWatch() {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 1.初始化数据
import { observe } from "./observer/index.js";
function initData(vm) {
let data = vm.$options.data;
data = vm._data = typeof data === "function" ? data.call(vm) : data;
observe(data);
}
1
2
3
4
5
6
2
3
4
5
6
# 2.递归属性劫持
class Observer {
// 观测值
constructor(value) {
this.walk(value);
}
walk(data) {
// 让对象上的所有属性依次进行观测
let keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let value = data[key];
defineReactive(data, key, value);
}
}
}
function defineReactive(data, key, value) {
observe(value);
Object.defineProperty(data, key, {
get() {
return value;
},
set(newValue) {
if (newValue == value) return;
observe(newValue);
value = newValue;
},
});
}
export function observe(data) {
if (typeof data !== "object" && data != null) {
return;
}
return new Observer(data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 3.数组方法的劫持
import { arrayMethods } from "./array";
class Observer {
// 观测值
constructor(value) {
if (Array.isArray(value)) {
value.__proto__ = arrayMethods; // 重写数组原型方法
this.observeArray(value);
} else {
this.walk(value);
}
}
observeArray(value) {
for (let i = 0; i < value.length; i++) {
observe(value[i]);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 重写数组原型方法
let oldArrayProtoMethods = Array.prototype;
export let arrayMethods = Object.create(oldArrayProtoMethods);
let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];
methods.forEach((method) => {
arrayMethods[method] = function (...args) {
const result = oldArrayProtoMethods[method].apply(this, args);
const ob = this.__ob__;
let inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
default:
break;
}
if (inserted) ob.observeArray(inserted); // 对新增的每一项进行观测
return result;
};
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 增加ob属性
class Observer {
constructor(value) {
Object.defineProperty(value, "__ob__", {
enumerable: false,
configurable: false,
value: this,
});
// ...
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
给所有响应式数据增加标识,并且可以在响应式上获取
Observer
实例上的方法
# 4.数据代理
function proxy(vm, source, key) {
Object.defineProperty(vm, key, {
get() {
return vm[source][key];
},
set(newValue) {
vm[source][key] = newValue;
},
});
}
function initData(vm) {
let data = vm.$options.data;
data = vm._data = typeof data === "function" ? data.call(vm) : data;
for (let key in data) {
// 将_data上的属性全部代理给vm实例
proxy(vm, "_data", key);
}
observe(data);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
编辑 (opens new window)
上次更新: 2023/03/27, 21:41:56