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>
以上僅爲我的學習上的筆記,若有問題,歡迎評論。javascript