1: 钩子函数 自定义策略
2: 资源选项 自定义策略
3: 选项 watch 合并策略
(function(global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.Vue = factory()); })(this, function() { var warn = function(msg) { console.error("[Vue Warn]: " + msg); } var LIFECYCLE_HOOKS = [ 'beforeCreate', 'created', 'beforeMount', 'mounted', 'beforeUpdate', 'updated', 'beforeDestroy', 'destroyed', 'activated', //内置组件 激活 keep-alive 'deactivated', // 停用 keep-alive 'errorCaptured' ]; var ASSET_TYPES = [ //选项components directives filters 'component', 'directive', 'filter' ]; function isPlainObject(obj){ return toString.call(obj) === "[object Object]"; } function assertObjectType(name, vaule, vm ){ if(!isPlainObject(vaule)){ warn("选项"+name+"的值无效:必须是个对象"); } } function extend(to, _from){ //childVal for( var key in _from){ to[key] = _from[key]; } return to; } var hasOwnProperty = Object.prototype.hasOwnProperty; var hasOwn = function(obj, key) { hasOwnProperty.call(obj, key); } var uid = 0; function resolveConstructorOptions(Con) { var options = Con.options; /* 判断 Con.super == Vue */ return options; } function checkComponents(options) { for (var key in options.components) { validataComponentName(key); } } //检测key 是否在makeMap function makeMap(str, toLowerCase) { var map = {}; var list = str.split(","); //["slot","component"] for (var i = 0; i < list.length; i++) { map[list[i]] = true; } return toLowerCase ? function(val) { return map[val.toLowerCase()]; } : function(val) { return map[val]; } } var isHTMLTag = makeMap( 'html,body,base,head,link,meta,style,title,' + 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' + 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + 'embed,object,param,source,canvas,script,noscript,del,ins,' + 'caption,col,colgroup,table,thead,tbody,td,th,tr,' + 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + 'output,progress,select,textarea,' + 'details,dialog,menu,menuitem,summary,' + 'content,element,shadow,template,blockquote,iframe,tfoot' ); //保留标签不能注册为组件 var isSVG = makeMap( 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' + 'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' + 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view', true ); //配置对象 var config = { //自定义的策略 optionMergeStrategies: {} } var strats = config.optionMergeStrategies; strats.el = function(parent, child, vm, key) { if (!vm) { // warn("选项" + key + "只能Vue在实例中使用"); } return defaultStrat(parent, child); } function mergeData(to, form) { if (!form) { return to; } //终极合并 待续: } function mergeDataorFn(parentVal, childVal, vm) { if (!vm) { //合并处理 parentVal childVal 对应的值都应该是函数 if (!childVal) { return parentVal; } if (!parentVal) { return childVal; } return function mergeDataFn(parentVal, childVal, vm) { //只是一个函数 什么样的情况下调用 加入响应式系统 //合并 子组件data对应的函数 父组件data对应的函数 return mergeData( typeof childVal === "function" ? childVal.call(this, this) : childVal, typeof parentVal === "function" ? parentVal.call(this, this) : parentVal ); } } else { //Vue的实例 return function mergedInstanceDataFn() { var instenceData = typeof childVal === "function" ? childVal.call(vm, vm) : childVal; var dafaultData = typeof parentVal === "function" ? parentVal.call(vm, vm) : parentVal; if (instenceData) { return mergeData(instenceData, dafaultData); } else { return dafaultData; } } } } //自定义策略 Vue.options.data options vm strats.data = function(parentVal, childVal, vm) { if (!vm) { //子组件 子类 if (childVal && typeof childVal !== "function") { warn("data选项的值应该为function 返回组件中每个实例值"); } return mergeDataorFn(parentVal, childVal); //数据的合并 } return mergeDataorFn(parentVal, childVal, vm); } function mergeHook(parentVal, childVal) { //undefined function return childVal ? parentVal ? //有值 parentVal.concat(childVal) : Array.isArray(childVal) ? childVal : [childVal] : parentVal; } // 钩子函数自定义策略 LIFECYCLE_HOOKS.forEach(function(hook) { strats[hook] = mergeHook; }) function mergeAssets(parentVal, childVal, vm, key){ //Vue.options.components var res = Object.create(parentVal||null); if(childVal){ assertObjectType(key, childVal, vm); return extend(res,childVal); //对象 res.__proto__ == Vue.options.components } return res; } //资源选项 自定义策略 ASSET_TYPES.forEach(function(type) { strats[type + "s"] = mergeAssets; }) //wacth选项自定义策略 strats.watch = function(parentVal, childVal, vm, key){ if(!childVal){ return Object.create( parentVal || null); } assertObjectType(key, childVal, vm); if(!parentVal){ return childVal; } var res = {}; extend(res, parentVal); for(var key in childVal){ var parent = res[key]; //有可能是为undefined var child = childVal[key]; if(parent && !Array.isArray(parent)){ parent = [parent]; } res[key] = parent ? parent.concat(child) : Array.isArray(child) ? child : [child] } return res; } //内置标签 var isbuiltInTag = makeMap("slot,component", true); var isReservedTag = function(tag) { return isSVG(tag) || isHTMLTag(tag); } function defaultStrat(parent, child) { return child === undefined ? parent : child; } function validataComponentName(key) { //1:不能使用Vue内置标签 slot component 2: 不能使用html || svg属性名称 //2: 规范组件的名称必须是由字母或中横线组成, 且必须是由字母开头 if (!/^[a-zA-Z][\w-]*$/.test(key)) { warn("组件的名称必须是由字母或中横线组成, 且必须是由字母开头"); } if (isbuiltInTag(key) || isReservedTag(key)) { warn("不要把内置组件或者保留的html ||svg 元素作为组件的id: " + key); } } //选项合并 返回新的对象 function mergeOptions(parent, child, vm) { //规范的检测 components props inject directives checkComponents(child); var options = {}; var key; for (key in parent) { mergeField(key); //components directives _base } for (key in child) { //自定义的选项配置 created if (!hasOwn(parent, key)) { mergeField(key); //components el data name } } //默认策略 自定义的策略 function mergeField(key) { //components directives _base created var result = strats[key] || defaultStrat; options[key] = result(parent[key], child[key], vm, key); // parent.options.created 1 } return options; } function initMixin(Vue) { Vue.prototype._init = function(options) { var vm = this; //有多少个Vue的实例对象 vm._uid = uid++; vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options, vm); } } function Vue(options) { //安全机制 if (!(this instanceof Vue)) { warn("Vue是一个构造函数 应该用new关键字调用") } this._init(options); //初始化 } initMixin(Vue); // 初始化选项: 1:规范 2:合并策略 //全局API Vue.options = { components: { //内置组件 keepAlive:{}, transition:{}, transitionGroup:{} }, directives: {}, _base: Vue } //初始化全局配置 function initExtend(Vue) { Vue.extend = function(extendOptions) { //参数对象 extendOptions = extendOptions || {}; var Super = this; //Vue var Sub = function VueComponent(options) { //构造函数 this._init(options); //Sub 实例对象 } Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; //第一次调用Super.options == Vue.options //第二次调用Super.options == sub.options Super === Sub Sub.options = mergeOptions(Super.options, extendOptions); Sub.extend = Super.extend; return Sub; } } initExtend(Vue); return Vue; }); //Sub 实例对象 __proto__ => Sub.prototype => __proto__ => Super.prototype == Vue.prototype