- Vue.js 是一款 MVVM 框架:核心实现就是响应式系统;理解这里的响应式指的是数据的响应式
模拟视图更新
- 使用
Object.defineProperty
封装方法
function cb(val) { /* 渲染视图 */
console.log("视图更新啦~");
}
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
/* 属性可枚举 */
configurable: true,
/* 属性可被修改或删除 */
get: function reactiveGetter() {
console.log(val)
return val; /* 实际上会依赖收集,下一小节会讲 */
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
console.log(newVal)
}
});
}
上面的Object.defineProperty()
用法解读
- 功能:方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。如果不指定configurable, writable, enumerable ,则这些属性默认值为false,如果不指定value, get, set,则这些属性默认值为undefined
- 语法:
Object.defineProperty(obj, prop, descriptor)
- obj: 需要被操作的目标对象
- prop: 目标对象需要定义或修改的属性的名称
- descriptor: 将被定义或修改的属性的描述符
var obj = new Object();
Object.defineProperty(obj, 'name', {
configurable: false,
writable: true,
enumerable: true,
value: '张三'
})
console.log(obj.name) //张三
另一种相似的Object.defineProperties()
- 功能:方法直接在一个对象上定义一个或多个新的属性或修改现有属性,并返回该对象。
- 语法:
Object.defineProperties(obj, props)
- obj: 将要被添加属性或修改属性的对象
- props: 该对象的一个或多个键值对定义了将要为对象添加或修改的属性的具体配置
var obj = new Object();
Object.defineProperties(obj, {
name: {
value: '张三',
configurable: false,
writable: true,
enumerable: true
},
age: {
value: 18,
configurable: true
}
})
console.log(obj.name, obj.age) // 张三, 18
封装一层observer
- 这个函数传入一个 value(需要「 响应式」化 的对象),通过遍历所有属性的方式对该对象的每一个属性都通过
defineReactive
方法
function cb(val) { /* 渲染视图 */
console.log("调用set方法视图更新啦~");
}
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
enumerable: true,
/* 属性可枚举 */
configurable: true,
/* 属性可被修改或删除 */
get: function reactiveGetter() {
console.log("调用get方法,打印值为:"+val);
return val;
},
set: function reactiveSetter(newVal) {
if (newVal === val) return;
cb(newVal)
}
});
}
function observer(value) {
if (!value || (typeof value !== 'object')) {
return;
}
Object.keys(value).forEach((key) => {
defineReactive(value, key, value[key]);
});
}
// 定义一个对象
var aobj = {
'name': 'wyh',
'sex': 'man',
};
// 观察aobj
observer(aobj)
// 查看数据调用get方法
aobj.name
// 修改调用set 方法
aobj.name = '123';
以上浏览器的打印:
模拟封装成VUE的方式
- 在 Vue 的构造函数中,对 的 进行处理,这里的 想必大家很熟悉,就是平时我们在写 Vue 项目时组件中的 属性(实际上是一个函数,这里当作一个对象来简单处理)。
class Vue {
/* Vue 构造类 */
constructor(options) {
console.log(options)
this._data = options.data;
observer(this._data);
}
}
let vue = new Vue({
data: {
test: "I am test."
},
methods:"function list"
});
// 修改test的值 等价于vue的this.XXX=XXX;
vue._data.test = "hello,world."; /* 视图更新啦~ */
// 打印值
console.log(vue._data.test)
此文为最近学习小册“剖析VueJS内部运行机制”的学习总结;