【js】vue 2.5.1 源码学习(二) 策略合并
一、 整体思路
1 首先是代码的大体构造,先判断引入代码的环境,即对应amd 和cmd的处理
2 vue_init 需要借助 initMinxin ==>>> // 初始化选项1: 规范 2: 合并策略。
3 mergeOptions 选项合并 一个或者多个对象合并,并且生成一个新的对象
==> resloveConstructorOptions 返回vm的optios 判断是否是vue对象有可能是vue子类。不一定指向options。
parent 自定义的options的选项 child 用户自定义的options
==> checkComonpents // 规范的检测 validataComponentsName(key)
检测component的名称是否规范(不能使用内置标签slot component 关于html的标签名称 svg的子类的名称)
(规范:组件的名称必须是字母或中横线,必须由字母开头)
isbuiltInTag 检测是都是内置标签 isReservedTag是否是html的标签
===> makeMap 检测key是否在makeMap里面
==> mergeField 默认策略 // 以默认为优先。用户定义为覆盖
defaultStrat(parent,chhild) 合并策略 child === undefined ? parent : child;
==> var config = { // 配置对象
// 内置对象自定义策略
optionMergeStrategies:{}
}
var strats = config.optionMergeStrategies;
4 Vue.options = {} vue的全局api
1 // 大体思路 2 // 1 首先是代码的大体构造,先判断引入代码的环境,即对应amd 和cmd的处理 3 // 2 vue_init 需要借助 initMinxin // 初始化选项1: 规范 2: 合并策略。 4 // 3 mergeOptions 选项合并 一个或者多个对象合并,并且生成一个新的对象 5 // resloveConstructorOptions 返回vm的optios 判断是否是vue对象又k 6 // 有可能是vue子类。不一定指向options。 7 // parent 自定义的options的选项 8 // child 用户自定义的options 9 /* checkComonpents // 规范的检测 validataComponentsName(key) 10 检测component的名称是否规范(不能使用内置标签slot component 关于html的标签名称 svg的子类的名称)自称) 11 (规范:组件的名称必须是字母或中横线,必须由字母开头) 12 isbuiltInTag 检测是都是内置标签 isReservedTag是否是html的标签 13 makeMap 检测key是否在makeMap里面 14 */ 15 /* mergeField 默认策略 // 以默认为优先。用户定义为覆盖 16 defaultStrat(parent,chhild) 17 child === undefined ? parent : child; 18 */ 19 /* 20 var config = { 21 optionMergeStrategies:{} 22 } 23 var strats = config.optionMergeStrategies; 24 */ 25 // 4 Vue.options = {} vue的全局api 26 27 (function(global,factory){ 28 // 兼容 cmd 29 typeof exports === 'object' && module !== 'undefined' ? module.exports = factory(): 30 // Amd 31 typeof define === 'function' && define.amd ? define(factory) : global.Vue = factory(); 32 })(this,function(){ 33 var uip = 0; 34 function warn(string){ 35 console.error('Vue Wran:' + string) 36 } 37 38 function resolveConstructorOptions(Con){ 39 var options = Con.options; 40 // 判断是否为vm的实例 或者是子类 41 return options 42 } 43 var hasOwnPropeerty = Object.prototype.hasOwnProperty 44 function hasOwn(obj , key){ 45 return hasOwnPropeerty.call(obj,key) 46 } 47 function makeMap(str, expectsLoweraseC){ 48 if(expectsLoweraseC){ 49 str = str.toLowerCase() 50 } 51 var map = Object.create(null) 52 var list = str.split(',') 53 for(var i = 0 ; i < list.length; i++){ 54 map[list[i]] = true 55 } 56 return function(key){ 57 return map[key] 58 59 } 60 } 61 var isbuiltInTag = makeMap('slot,component',true) 62 var isHTMLTag = makeMap( 63 'html,body,base,head,link,meta,style,title,' + 64 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' + 65 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' + 66 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' + 67 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' + 68 'embed,object,param,source,canvas,script,noscript,del,ins,' + 69 'caption,col,colgroup,table,thead,tbody,td,th,tr,' + 70 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' + 71 'output,progress,select,textarea,' + 72 'details,dialog,menu,menuitem,summary,' + 73 'content,element,shadow,template,blockquote,iframe,tfoot' 74 ); 75 var isSVG = makeMap( 76 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' + 77 'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' + 78 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view', 79 true 80 ); 81 var isReservedTag = function(key){ 82 return isHTMLTag(key) || isSVG(key) 83 } 84 function validataComponentName(key){ 85 //检测component 的自定义名称是否合格 86 // 只能是字母开头或下划线,必须是字母开头 87 if(!(/^[a-zA-Z][\w-]*$/g.test(key))){ 88 warn('组件的名称必须是字母或中横线,必须由字母开头') 89 } 90 // 1. 不能为内置对象,2.不能是html ,和avg的内部标签 91 if( isbuiltInTag(key) || isReservedTag(key)){ 92 warn('不能为html标签或者avg的内部标签') 93 } 94 } 95 function checkComonpents(child){ 96 for(var key in child.component){ 97 validataComponentName(key) 98 } 99 } 100 // 配置对象 101 var config = { 102 // 自定义的策略 103 optionMergeStrategies:{} 104 } 105 var strats = config.optionMergeStrategies 106 strats.el = function(parent,child , key , vm){ 107 108 if(!vm){ 109 warn('选项'+key+'只能在vue实例用使用') 110 } 111 return defaultStrat(parent,child , key , vm) 112 } 113 function defaultStrat(parent,child , key , vm){ 114 return child === undefined ? parent :child ; 115 } 116 function mergeOptions(parent,child,vm){ 117 var options = {} 118 // 检测是component 是否是合法的 119 120 checkComonpents(child) 121 122 // console.log(parent, child) 123 for(key in parent){ 124 magerField(key) 125 } 126 for(key in child){ 127 if(!hasOwn(parent ,key)){ // parent 中循环过地方不进行循环 128 magerField(key) // ----忘记写 129 } 130 131 } 132 // 默认合并策略 133 function magerField(key){ 134 // 自定义策略 默认策略 135 // console.log(key) 136 var result = strats[key] || defaultStrat // ---忘记写 137 options[key] = result(parent[key],child[key] , key , vm) 138 } 139 console.log(options) 140 return options 141 } 142 function initMinxin(options){ 143 Vue.prototype._init = function(options){ 144 var vm = this 145 // 记录生成的vue实例对象 146 vm._uip = uip++ // //-------忘记写 147 148 mergeOptions(resolveConstructorOptions(vm.constructor),options,vm) 149 } 150 } 151 function Vue(options){ 152 // 安全机制 153 if(!(this instanceof Vue)){ //-------忘记写 154 warn('Vue是一个构造函数,必须是由new关键字调用') 155 } 156 this._init(options) 157 } 158 initMinxin() // 初始化选项1: 规范 2: 合并策略。 159 Vue.options = { 160 components: {}, 161 directives:{}, 162 _bash: Vue 163 } 164 return Vue 165 })
1 <body> 2 <div id="app"> 3 <huml></huml> 4 </div> 5 <script src="vue.js"></script> 6 <!-- <script src="vue2.5.1.js"></script> --> 7 <script type="text/javascript"> 8 var componentA = { 9 el: "#app" 10 } 11 var vm = new Vue({ 12 el:"#app", 13 data: { 14 message: "hello Vue", 15 key: "wodow" 16 }, 17 components:{ 18 huml: componentA 19 } 20 21 }) 22 console.log(vm.$options) 23 </script> 24 </body>
以上仅为个人学习上的笔记,如有问题,欢迎评论。