赞
踩
initProxy
Vue.prototype._init = function(options) {
// 选项合并
...
{
// 对vm实例进行一层代理
initProxy(vm);
}
...
}
initProxy
// 代理函数 var initProxy = function initProxy (vm) { //是否支持Proxy if (hasProxy) { var options = vm.$options; //当使用类似webpack这样的打包工具时,通常会使用vue-loader插件进行模板的编译,这个时候options.render是存在的,并且_withStripped的属性也会设置为true(关于编译版本和运行时版本的区别可以参考后面章节),所以此时代理的选项是hasHandler //在其他场景下,代理的选项是getHandler var handlers = options.render && options.render._withStripped ? getHandler : hasHandler; // 代理vm实例到vm属性_renderProxy vm._renderProxy = new Proxy(vm, handlers); } else { vm._renderProxy = vm; } };
hasProxy
var hasProxy =
typeof Proxy !== 'undefined' && isNative(Proxy);
hasHandler
var hasHandler = {
// key in obj或者with作用域时,会触发has的钩子
has: function has (target, key) {
···
}
};
触发代理
Vue.prototype._render = function () { ··· // 调用vm._renderProxy vnode = render.call(vm._renderProxy, vm.$createElement); } ========================================= var vm = new Vue({ el: '#app' }) console.log(vm.$options.render) //输出, 模板渲染使用with语句 ƒ anonymous() { with(this){return _c('div',{attrs:{"id":"app"}},[_v(_s(message)+_s(_test))])} }
数据过滤
var hasHandler = { has: function has (target, key) { var has = key in target; // isAllowed用来判断模板上出现的变量是否合法。 var isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data)); // _和$开头的变量不允许出现在定义的数据中,因为他是vue内部保留属性的开头。 // 1. warnReservedPrefix: 警告不能以$ _开头的变量 // 2. warnNonPresent: 警告模板出现的变量在vue实例中未定义 //has判断是否是target对象中的变量 if (!has && !isAllowed) { if (key in target.$data) { warnReservedPrefix(target, key); } else { warnNonPresent(target, key); } } return has || !isAllowed } }; // 模板中允许出现的非vue实例定义的变量 var allowedGlobals = makeMap( 'Infinity,undefined,NaN,isFinite,isNaN,' + 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' + 'require' // for Webpack/Browserify );
在浏览器不支持proxy的情况下的数据过滤
function initData(vm) {
vm._data = typeof data === 'function' ? getData(data, vm) : data || {}
if (!isReserved(key)) {
// 数据代理,用户可直接通过vm实例获取返回data数据
proxy(vm, "_data", key);
}
}
function isReserved (str) {
var c = (str + '').charCodeAt(0);
// 首字符是$, _的字符串
return c === 0x24 || c === 0x5F
}
proxy
function proxy (target, sourceKey, key) {
sharedPropertyDefinition.get = function proxyGetter () {
// 当访问this[key]时,会代理访问this._data[key]的值
return this[sourceKey][key]
};
sharedPropertyDefinition.set = function proxySetter (val) {
this[sourceKey][key] = val;
};
Object.defineProperty(target, key, sharedPropertyDefinition);
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。