1: 子类父类 切入点
2: Vue.extend() //创建的是Vue的子类
注:下面的代码是自定义,非官方源码,仅供参考,不可放到项目上使用,5月中旬将补充源码注释
(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 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); } //内置标签 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 data sub.options.data } for (key in child) { //自定义的选项配置 if (!hasOwn(parent, key)) { mergeField(key); //components el data name } } //默认策略 自定义的策略 function mergeField(key) { //components directives _base data var result = strats[key] || defaultStrat; options[key] = result(parent[key], child[key], vm, key); // function undefined } 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: {}, directives: {}, _base: Vue } //初始化全局配置 function initExtend(Vue) { Vue.extend = function(extendOptions) { //参数对象 extendOptions = extendOptions || {}; var Super = this; //sub var Sub = function VueComponent() { //构造函数 this._init(); //Vue.prototype._init } Sub.prototype = Object.create(Super.prototype); //Super sub Sub.prototype.constructor = Sub; //第一次调用Super.options == Vue.options //第二次调用Super.options == sub.options Sub.options = mergeOptions(Super.options, extendOptions); Sub.extend = Super.extend; return Sub; } } initExtend(Vue); return Vue; });