大体思路 (三)
   1.钩子函数 自定义策略
      LIFECYCLE_HOOKS= []
     created = [function(){} , function(){}] 组装方法。
     ==> starts[hook]= mergeHook
           ==>  mergeHook(parent,child) // 合并parentVal 和childVal
 2.资源选项 自定义策略
        ==> ASSET_TYPES = []
              ==> starts[type] = mergeAssets
              mergeAssets  ==> Object.create(parentVal || null)
              ===> if(childVal) assetObjectType // 检测conponents 值是否是object
              ===> extend(res,childVal) // 合并
 3.选择watch 合并策略 监听vue实例数据的变化
    ==> strats.watch   
vue.js  如下
  1. // 大体思路 (三)
  2. // 1.钩子函数 自定义策略
  3. /** LIFECYCLE_HOOK= []
  4. * created = [function(){} , function(){}] 组装方法。
  5. * ==> starts.[hook]= mergeHook
  6. * mergeHook(parent,child) // 合并parentVal 和childVal
  7. */
  8. /* 2.资源选项 自定义策略
  9. * ==> ASSET_TYPES = []
  10. * ==> starts.[type] = mergeAssets
  11. * ==> Object.create(parentVal || null)
  12. ==> if(childVal) assetObjectType // 检测conponents 值是否是object
  13. ==> extend(res,childVal) // 合并
  14. *
  15. */
  16. // 3.选择watch 合并策略 监听vue实例数据的变化
  17. /* ==> strats.watch */
  18.  
  19. (function(global,factory){
  20. // 兼容 cmd
  21. typeof exports === 'object' && module !== 'undefined' ? module.exports = factory():
  22. // Amd
  23. typeof define === 'function' && define.amd ? define(factory) : global.Vue = factory();
  24. })(this,function(){
  25. var uip = 0;
  26. function warn(string){
  27. console.error('Vue Wran:' + string)
  28. }
  29. function resolveConstructorOptions(Con){
  30. var options = Con.options;
  31. // 判断是否为vm的实例 或者是子类
  32. return options
  33. }
  34. var hasOwnPropeerty = Object.prototype.hasOwnProperty
  35. function hasOwn(obj , key){
  36. return hasOwnPropeerty.call(obj,key)
  37. }
  38. function makeMap(str, expectsLoweraseC){
  39. if(expectsLoweraseC){
  40. str = str.toLowerCase()
  41. }
  42. var map = Object.create(null)
  43. var list = str.split(',')
  44. for(var i = 0 ; i < list.length; i++){
  45. map[list[i]] = true
  46. }
  47. return function(key){
  48. return map[key]
  49.  
  50. }
  51. }
  52. var isbuiltInTag = makeMap('slot,component',true)
  53. var isHTMLTag = makeMap(
  54. 'html,body,base,head,link,meta,style,title,' +
  55. 'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
  56. 'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
  57. 'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
  58. 's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
  59. 'embed,object,param,source,canvas,script,noscript,del,ins,' +
  60. 'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
  61. 'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
  62. 'output,progress,select,textarea,' +
  63. 'details,dialog,menu,menuitem,summary,' +
  64. 'content,element,shadow,template,blockquote,iframe,tfoot'
  65. );
  66. var isSVG = makeMap(
  67. 'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
  68. 'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
  69. 'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view',
  70. true
  71. );
  72. var ASSET_TYPES = [
  73. 'component',
  74. 'directive',
  75. 'filter'
  76. ];
  77.  
  78. var LIFECYCLE_HOOKS = [
  79. 'beforeCreate',
  80. 'created',
  81. 'beforeMount',
  82. 'mounted',
  83. 'beforeUpdate',
  84. 'updated',
  85. 'beforeDestroy',
  86. 'destroyed',
  87. 'activated',
  88. 'deactivated',
  89. 'errorCaptured'
  90. ];
  91.  
  92. var isReservedTag = function(key){
  93. return isHTMLTag(key) || isSVG(key)
  94. }
  95. function validataComponentName(key){
  96. //检测component 的自定义名称是否合格
  97. // 只能是字母开头或下划线,必须是字母开头
  98. if(!(/^[a-zA-Z][\w-]*$/g.test(key))){
  99. warn('组件的名称必须是字母或中横线,必须由字母开头')
  100. }
  101. // 1. 不能为内置对象,2.不能是html ,和avg的内部标签
  102. if( isbuiltInTag(key) || isReservedTag(key)){
  103. warn('不能为html标签或者avg的内部标签')
  104. }
  105. }
  106. function checkComonpents(child){
  107. for(var key in child.components){
  108. validataComponentName(key)
  109. }
  110. }
  111. // 配置对象
  112. var config = {
  113. // 自定义的策略
  114. optionMergeStrategies:{}
  115. }
  116. var strats = config.optionMergeStrategies
  117. strats.el = function(parent,child , key , vm){
  118.  
  119. if(!vm){
  120. warn('选项'+key+'只能在vue实例用使用')
  121. }
  122. return defaultStrat(parent,child , key , vm)
  123. }
  124. function mergeData(to,form){
  125. // 终极合并
  126. if(!form){
  127. return to
  128. }
  129. // 具体合并。
  130. }
  131. function mergeDataorFn(parentVal,childVal,vm){
  132. // 合并 parentVal childVal 都是函数
  133. if(!vm){
  134. if(!childVal){
  135. return parentVal
  136. }
  137. if(!parentVal){
  138. return childVal
  139. }
  140. return function mergeDataFn(parentVal,childVal,vm){//只是一个函数 什么样的情况下调用 加入响应式系统
  141. // 合并子组件对应的data 和 父组件对应的data
  142. return mergeData(
  143. typeof parentVal === 'function' ? parentVal.call(this,this) : parentVal, // -----忘记写
  144. typeof childVal === 'function' ? childVal.call(this,this): childVal) // -----忘记写
  145. }
  146. }else{ // vue实例
  147. return function mergeInstanceDataFn(parentVal,childVal,vm){//只是一个函数 什么样的情况下调用 加入响应式系统
  148. var InstanceData = typeof childVal === 'function' ? childVal.call(vm,vm): childVal; // -----忘记写
  149. var defaultData = typeof parentVal === 'function' ? parent.call(vm,vm): parentVal; // -----忘记写
  150. if(InstanceData){
  151. return mergeData(parentVal,childVal)
  152. }else{ // -----忘记写
  153. defaultData
  154. }
  155.  
  156. }
  157. }
  158. }
  159. strats.data = function(parent,child , key , vm){
  160. if(!vm){
  161. // console.log(typeof child === 'function')
  162. if(child && !(typeof child === 'function')){
  163. warn('data必须返回是一个function')
  164. }
  165. return mergeDataorFn(parent,child)
  166. }
  167. return mergeDataorFn(parent,child,vm)
  168. }
  169. // 生命周期策略的合并,值等于一个function 如果是有两个,放到一个数组里面。
  170. function mergeHook(parentVal,childVal,key,vm){
  171. // console.log(key)
  172. // console.log(parentVal.concat(childVal) )
  173. return childVal ? parentVal ? parentVal.concat(childVal):
  174. Array.isArray(childVal) ? childVal : [childVal] : parentVal
  175. }
  176. LIFECYCLE_HOOKS.forEach(function(key){
  177. strats[key] = mergeHook
  178. });
  179. // 检测是否为object
  180. function isPlainObject(obj){
  181. return Object.prototype.toString.call(obj) === '[object Object]'
  182. }
  183. function assetObjectType(obj){
  184. if(!isPlainObject(obj)){
  185. marn('选项的值'+obj+'无效:必须是一个对象的')
  186. }
  187. }
  188. // 对parent实现链式调用。
  189. function extend(to,form){
  190. for(key in form){
  191. to[key] = form[key]
  192. }
  193. return to
  194. }
  195. // 实现Assets 的策略合并 conmponents filter diretive
  196. function mergeAssets(parentVal,childVal,key,vm){
  197. var parent = Object.create(parentVal || null) // 保证子类的每个值的指向都是一个新的object。否则回出现相互引用的现象。
  198. if(childVal){
  199. assetObjectType(childVal)
  200. return extend(parent,childVal)
  201. }
  202. return parent
  203. }
  204. ASSET_TYPES.forEach(function(key){
  205. strats[key+'s'] = mergeAssets
  206. })
  207. // 实现watch的策略和并,将相同的属性放到一个数组里面。
  208. strats.watch = function(parentVal,childVal , key , vm){
  209. if(!childVal){
  210. return Object.create(parentVal)
  211. }
  212. var res = {}
  213. res = extend(res,parentVal)
  214. for(var key in childVal){
  215. var parent = res[key]
  216. var child = childVal[key]
  217. res[key] = parent ? Array.isArray(parent) ? parent.concat(child) : [parent].concat(child) :
  218. Array.isArray(child) ? child : [child] ;
  219. }
  220. return res
  221. }
  222. function defaultStrat(parent,child , key , vm){
  223. return child === undefined ? parent :child ;
  224. }
  225. function mergeOptions(parent,child,vm){
  226. var options = {}
  227. // 检测是component 是否是合法的
  228.  
  229. checkComonpents(child)
  230.  
  231. // console.log(parent, child)
  232. for(key in parent){
  233. magerField(key)
  234. }
  235. for(key in child){
  236. if(!hasOwn(parent ,key)){ // parent 中循环过地方不进行循环
  237. magerField(key) // ----忘记写
  238. }
  239.  
  240. }
  241. // 默认合并策略
  242. function magerField(key){
  243. // 自定义策略 默认策略
  244. // console.log(key)
  245. var result = strats[key] || defaultStrat // ---忘记写
  246. options[key] = result(parent[key],child[key] , key , vm)
  247. }
  248. // console.log(options)
  249. return options
  250. }
  251. function initMinxin(options){
  252. Vue.prototype._init = function(options){
  253. var vm = this
  254. // 记录生成的vue实例对象
  255. vm._uip = uip++ // //-------忘记写
  256.  
  257. vm.$options =mergeOptions(resolveConstructorOptions(vm.constructor),options,vm)
  258. }
  259. }
  260. function Vue(options){
  261. // 安全机制
  262. if(!(this instanceof Vue)){ //-------忘记写
  263. warn('Vue是一个构造函数,必须是由new关键字调用')
  264. }
  265. this._init(options)
  266. }
  267. initMinxin() // 初始化选项1: 规范 2: 合并策略。
  268. Vue.options = {
  269. components: {
  270. transtions: {},
  271. keepAlive:{},
  272. solt:{},
  273. transtionsGroup:{}
  274. },
  275. directives:{},
  276. _bash: Vue
  277. }
  278. function initExend(Vue){
  279. Vue.extend = function(extendOptions){
  280. extendOptions = extendOptions || {} // -----忘记写
  281. var Super = this
  282. var Child = function VueComponent(options) {
  283. this._init(options)
  284. }
  285. Child.prototype = Object.create(Super.prototype)
  286. Child.prototype.constructor = Child // 改变constructor 的指向
  287. Child.options = mergeOptions(Super.options,extendOptions)
  288. // 子类继承父类的静态方法。
  289. Child.extend = Vue.extend
  290. // console.log(new Child({}))
  291. return Child
  292. }
  293. }
  294. initExend(Vue)
  295. return Vue
  296. })

dome.html  代码如下

  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. humle: componentA
  19. }
  20.  
  21. })
  22. // console.log(Vue)
  23. var Parent = Vue.extend({
  24. data: function() {},
  25. components:{
  26. huml: componentA
  27. },
  28. created : function(){
  29.  
  30. },
  31. watch: {
  32. test: function(){}
  33. }
  34. })
  35. var Child = Parent.extend({
  36. components:{
  37. humlt: componentA
  38. },
  39. created: function(){
  40.  
  41. },
  42. watch: {
  43. aa: function(){},
  44. test: function(){}
  45. }
  46. });
  47. // console.log(vm.$options)
  48. console.log (Parent.options)
  49. console.log(Child.options)
  50. </script>
  51. </body>

以上仅为个人学习笔记,如有疑问,请评论回复

【js】vue 2.5.1 源码学习 (四) 钩子函数 资源选项 watch 的合并策略的更多相关文章

  1. 【js】 vue 2.5.1 源码学习(五) props directives规范化 props 合并策略

    大体思路 (四) 上节回顾: A: 对于生命周期函数将父子组件的函数放到一个数组里面,特定时间点调用,保证父子组件函数都调用到. B: 对于directive,filters,components 等 ...

  2. 如何实现全屏遮罩(附Vue.extend和el-message源码学习)

    [Vue]如何实现全屏遮罩(附Vue.extend和el-message源码学习) 在做个人项目的时候需要做一个类似于电子相册浏览的控件,实现过程中首先要实现全局遮罩,结合自己的思路并阅读了(饿了么) ...

  3. 【js】vue 2.5.1 源码学习 (三) Vue.extend 和 data的合并策略

    大体思路 (三)  1. 子类父类  2.Vue.extend()      //创建vue的子类 组件的语法器 Vue.extend(options) Profile().$mount('#app' ...

  4. 【js】vue 2.5.1 源码学习(二) 策略合并

     一.  整体思路     1 首先是代码的大体构造,先判断引入代码的环境,即对应amd 和cmd的处理     2 vue_init 需要借助 initMinxin    ==>>> ...

  5. 【js】 vue 2.5.1 源码学习(十二)模板编译

    大体思路(十) 本节内容: 1. baseoptions 参数分析 2. options 参数分析 3. parse 编译器 4. parseHTNL 函数解析 // parse 解析 parser- ...

  6. 【js】vue 2.5.1 源码学习 (十一) 模板编译compileToFunctions渲染函数

    大体思路(九) 本节内容: 1. compileToFunctions定位 1. compileToFunctions定位 ==> createCompiler = createCompiler ...

  7. 【js】vue 2.5.1 源码学习 (十) $mount 挂载函数的实现

    大体思路(九) 本节内容: 1. $mount 挂载函数的实现. // 将Vue.prototype.$mount 缓存下来 ==>mountComponet(this,el) { // 组建挂 ...

  8. 【js】vue 2.5.1 源码学习 (九) 响应数组对象的变

    大体思路(八) 本节内容: 1.Observe 如何响应数组的变化 代理原型 数组变异方法 shell cacheArrProto methods 新添加的数组需要加到显示系统里面,拦截 push等的 ...

  9. 【js】Vue 2.5.1 源码学习 (八)响应式入口observe

    大体思路(七) 本节内容: deps 依赖收集的数组对象 => Dep 构造函数 /** ==> observe() * var ob * ==> if --isObject * = ...

随机推荐

  1. CodePlus2017 12月月赛 div2火锅盛宴

    当时看到这道题感觉真是难过,我数据结构太弱啦. 我们来看看需要求什么: 1.当前熟了的食物的最小id 2.当前熟了的食物中有没有编号为id的食物 3.当前没熟的食物中有没有编号为id的食物 4.当前没 ...

  2. 移动项目到centos中运行报错:failed to open stream: Permission denied

    这是文件夹没有读写权限的错误: (注意:TP5.0权限给runtime文件夹就行了,官方文档在安装tp5的方法中有介绍到权限问题) 在需要赋予权限的文件夹的前一级输入: chmod -R 文件夹名字

  3. springboot security 安全

    spring security几个概念 “认证”(Authentication) 是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统) . “授权 ...

  4. Facebook POP动效库使用教程

    编者注:用Origami作iOS动效的同学如果愁怎么实现,可以把这个给开发看看作为参考哦 如果说Origami这款动效原型工具是Facebook Paper的幕后功臣,那么POP便是Origami的地 ...

  5. 简单的requestAnimationFrame动画

    html部分 <div id="test" style="width:1px;height:17px;background:#0f0;">0%< ...

  6. TensorFlow3学习笔记1

    1.简单实例:向量相加 下面我们通过两个向量相加的简单例子来看一下Tensorflow的基本用法. [1. 1. 1. 1.] + [2. 2. 2. 2.] = [3. 3. 3. 3.] impo ...

  7. cmd 命令重启远程服务器

    今天,连接服务器突然无法连接远程桌面,更无法重新启动机器,先进行了ping  操作: 机器运行正常... 后通过远程软件发现,可以用命令...这是一个新发现  …^ .^ 1.输入cmd  运行正常. ...

  8. 快速删除项目中的输出日志console.log

    项目开发时,控制台往往有许多忘记删除或注释掉的输出日志.但是上线后总不能一个一个删吧,最近总结出几个解决思路 重写console.log方法,使其失去 输出能力 这个最直接有效,用vue框架的话放在m ...

  9. 走近科学,探究阿里闲鱼团队通过数据提升Flutter体验的真相

    背景 闲鱼客户端的flutter页面已经服务上亿级用户,这个时候Flutter页面的用户体验尤其重要,完善Flutter性能稳定性监控体系,可以及早发现线上性能问题,也可以作为用户体验提升的衡量标准. ...

  10. 《C语言深度解剖》学习笔记之预处理

    第3章 预处理 1.下面两行代码都是错的.因为注释先于预处理指令被处理,当这两行被展开成“//……”和“/*……*/”时,注释已处理完毕,所以出现错误 #define BSC // #define B ...