代理模式
由于一个对象不能直接引用(或者不方便引用)另一个对象,所以需要通过代理对象在这俩个对象之间起中介的作用。
虚拟代理
虚拟代理并不会减少重复的代码和提高对象的模块性,只有在资源创建或报错有很大开销,需要通过代理来控制他们的创建时间和方式。
图片懒加载中
<img src="lazy.jpg" data-src="xxxx.jpg" />
远程代理
跨域请求:通过node或者别的服务代理到
// koa代理
var proxy = require('koa2-proxy');
// 转发请求到指定host
proxy.when('/api', function(ctx) {
ctx.request.host = 'www.test.com';
ctx.request.protocol = 'http';
});
再看Vue源码中的代理
const app = new Vue({
el: '#app',
data:{
message: 'Hello Vue!'
}
})
console.log(app._data.message) // Hello Vue!
console.log(app.message); // Hello Vue!
我们可以直接通过 '.' 获取到data中的属性,Vue是怎么实现的呢?
const 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);
}
proxy(vm, '_data', key);
具体代码
function initData(vm) {
var data = vm.$options.data;
// 将data参数赋值给 vm._data
data = vm._data = typeof data === 'function'
? getData(data, vm)
: data || {};
//xxx
var keys = Object.keys(data);
var props = vm.$options.props;
var methods = vm.$options.methods;
var i = keys.length;
// 遍历data
while (i--) {
var key = keys[i];
// 判断是否在methods 和props定义过,提示错误
if (methods && hasOwn(methods, key)) {
warn(
('Method "' + key + '" has already been defined as a data property.'),
vm,
);
}
if (props && hasOwn(props, key)) {
warn(
'The data property "' + key + '" is already declared as a prop. ' +
'Use prop default value instead.',
vm,
);
} else if (!isReserved(key)) {
proxy(vm, '_data', key);
}
}
}