vue2中为什么可以直接使用 this.属性,this.方法,本文提供源码教学地址,与自己实现的简化版代码
源码教学地址
简化版
// 检测属性是否为对象的自有属性
var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn (obj, key) {
return hasOwnProperty.call(obj, key)
}
// 空函数,占个位
function noop(a,b,c){}
// Object双向绑定的描述
var sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: noop,
set: noop
};
// 自定义代理
function proxy (target, sourceKey, key) {
sharedPropertyDefinition.get = function proxyGetter () {
return this[sourceKey][key]
};
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
// 渲染视图
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
// 初始化data值
function initData(vm){
// vm._data,直接将data数据拉平在vm下?
// 不行,这样就没法Object.defineProperty双向绑定值了,set中修改自己会报错
// function set(v){
// this.name = v
// }
// 为什么要双向绑定?
// 修改修改数据后需要重新渲染视图
let data = vm._data = vm._option.data
let keys = Object.keys(data)
let len = keys.length
while(len-- > 0){
proxy(vm,'_data',keys[len])
}
}
// 初始化methods值
function initMethod(vm){
let methods = vm._option.methods
let data = vm._option.data
for(let k in methods){
if(data && hasOwn(data,k)){
throw Error('data与methods中存在重复属性')
return
}
// 不修改this执指向,this = Person,“this.name" 也就获取不到值了。
vm[k] = typeof methods[k] !== 'function' ? noop : methods[k].bind(vm);
}
}
function Person(option){
let vm = this
vm._option = option
if(option.data){
initData(vm)
}
if(option.methods){
initMethod(vm)
}
}
const h = new Person({
data:{
name: 'Tom',
age: 25
},
methods:{
say(){
console.log(`My name is ${this.name}`)
}
}
})
h.say()
总结
生成一个新的对象,用object.defineProperty 做代理,将data,methods中的值拉平到第一层。
// h的结构
//Person {
// _option: { data: { name: 'key', age: 25 }, methods: { say: [Function: say] } },
// _data: { name: 'key', age: 25 },
// age: [Getter/Setter],
// name: [Getter/Setter],
// say: [Function: bound say]
//}