【js】vue 2.5.1 源码学习 (四) 钩子函数 资源选项 watch 的合并策略
- // 大体思路 (三)
- // 1.钩子函数 自定义策略
- /** LIFECYCLE_HOOK= []
- * created = [function(){} , function(){}] 组装方法。
- * ==> starts.[hook]= mergeHook
- * mergeHook(parent,child) // 合并parentVal 和childVal
- */
- /* 2.资源选项 自定义策略
- * ==> ASSET_TYPES = []
- * ==> starts.[type] = mergeAssets
- * ==> Object.create(parentVal || null)
- ==> if(childVal) assetObjectType // 检测conponents 值是否是object
- ==> extend(res,childVal) // 合并
- *
- */
- // 3.选择watch 合并策略 监听vue实例数据的变化
- /* ==> strats.watch */
- (function(global,factory){
- // 兼容 cmd
- typeof exports === 'object' && module !== 'undefined' ? module.exports = factory():
- // Amd
- typeof define === 'function' && define.amd ? define(factory) : global.Vue = factory();
- })(this,function(){
- var uip = 0;
- function warn(string){
- console.error('Vue Wran:' + string)
- }
- function resolveConstructorOptions(Con){
- var options = Con.options;
- // 判断是否为vm的实例 或者是子类
- return options
- }
- var hasOwnPropeerty = Object.prototype.hasOwnProperty
- function hasOwn(obj , key){
- return hasOwnPropeerty.call(obj,key)
- }
- function makeMap(str, expectsLoweraseC){
- if(expectsLoweraseC){
- str = str.toLowerCase()
- }
- var map = Object.create(null)
- var list = str.split(',')
- for(var i = 0 ; i < list.length; i++){
- map[list[i]] = true
- }
- return function(key){
- return map[key]
- }
- }
- var isbuiltInTag = makeMap('slot,component',true)
- 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 ASSET_TYPES = [
- 'component',
- 'directive',
- 'filter'
- ];
- var LIFECYCLE_HOOKS = [
- 'beforeCreate',
- 'created',
- 'beforeMount',
- 'mounted',
- 'beforeUpdate',
- 'updated',
- 'beforeDestroy',
- 'destroyed',
- 'activated',
- 'deactivated',
- 'errorCaptured'
- ];
- var isReservedTag = function(key){
- return isHTMLTag(key) || isSVG(key)
- }
- function validataComponentName(key){
- //检测component 的自定义名称是否合格
- // 只能是字母开头或下划线,必须是字母开头
- if(!(/^[a-zA-Z][\w-]*$/g.test(key))){
- warn('组件的名称必须是字母或中横线,必须由字母开头')
- }
- // 1. 不能为内置对象,2.不能是html ,和avg的内部标签
- if( isbuiltInTag(key) || isReservedTag(key)){
- warn('不能为html标签或者avg的内部标签')
- }
- }
- function checkComonpents(child){
- for(var key in child.components){
- validataComponentName(key)
- }
- }
- // 配置对象
- var config = {
- // 自定义的策略
- optionMergeStrategies:{}
- }
- var strats = config.optionMergeStrategies
- strats.el = function(parent,child , key , vm){
- if(!vm){
- warn('选项'+key+'只能在vue实例用使用')
- }
- return defaultStrat(parent,child , key , vm)
- }
- function mergeData(to,form){
- // 终极合并
- if(!form){
- return to
- }
- // 具体合并。
- }
- function mergeDataorFn(parentVal,childVal,vm){
- // 合并 parentVal childVal 都是函数
- if(!vm){
- if(!childVal){
- return parentVal
- }
- if(!parentVal){
- return childVal
- }
- return function mergeDataFn(parentVal,childVal,vm){//只是一个函数 什么样的情况下调用 加入响应式系统
- // 合并子组件对应的data 和 父组件对应的data
- return mergeData(
- typeof parentVal === 'function' ? parentVal.call(this,this) : parentVal, // -----忘记写
- typeof childVal === 'function' ? childVal.call(this,this): childVal) // -----忘记写
- }
- }else{ // vue实例
- return function mergeInstanceDataFn(parentVal,childVal,vm){//只是一个函数 什么样的情况下调用 加入响应式系统
- var InstanceData = typeof childVal === 'function' ? childVal.call(vm,vm): childVal; // -----忘记写
- var defaultData = typeof parentVal === 'function' ? parent.call(vm,vm): parentVal; // -----忘记写
- if(InstanceData){
- return mergeData(parentVal,childVal)
- }else{ // -----忘记写
- defaultData
- }
- }
- }
- }
- strats.data = function(parent,child , key , vm){
- if(!vm){
- // console.log(typeof child === 'function')
- if(child && !(typeof child === 'function')){
- warn('data必须返回是一个function')
- }
- return mergeDataorFn(parent,child)
- }
- return mergeDataorFn(parent,child,vm)
- }
- // 生命周期策略的合并,值等于一个function 如果是有两个,放到一个数组里面。
- function mergeHook(parentVal,childVal,key,vm){
- // console.log(key)
- // console.log(parentVal.concat(childVal) )
- return childVal ? parentVal ? parentVal.concat(childVal):
- Array.isArray(childVal) ? childVal : [childVal] : parentVal
- }
- LIFECYCLE_HOOKS.forEach(function(key){
- strats[key] = mergeHook
- });
- // 检测是否为object
- function isPlainObject(obj){
- return Object.prototype.toString.call(obj) === '[object Object]'
- }
- function assetObjectType(obj){
- if(!isPlainObject(obj)){
- marn('选项的值'+obj+'无效:必须是一个对象的')
- }
- }
- // 对parent实现链式调用。
- function extend(to,form){
- for(key in form){
- to[key] = form[key]
- }
- return to
- }
- // 实现Assets 的策略合并 conmponents filter diretive
- function mergeAssets(parentVal,childVal,key,vm){
- var parent = Object.create(parentVal || null) // 保证子类的每个值的指向都是一个新的object。否则回出现相互引用的现象。
- if(childVal){
- assetObjectType(childVal)
- return extend(parent,childVal)
- }
- return parent
- }
- ASSET_TYPES.forEach(function(key){
- strats[key+'s'] = mergeAssets
- })
- // 实现watch的策略和并,将相同的属性放到一个数组里面。
- strats.watch = function(parentVal,childVal , key , vm){
- if(!childVal){
- return Object.create(parentVal)
- }
- var res = {}
- res = extend(res,parentVal)
- for(var key in childVal){
- var parent = res[key]
- var child = childVal[key]
- res[key] = parent ? Array.isArray(parent) ? parent.concat(child) : [parent].concat(child) :
- Array.isArray(child) ? child : [child] ;
- }
- return res
- }
- function defaultStrat(parent,child , key , vm){
- return child === undefined ? parent :child ;
- }
- function mergeOptions(parent,child,vm){
- var options = {}
- // 检测是component 是否是合法的
- checkComonpents(child)
- // console.log(parent, child)
- for(key in parent){
- magerField(key)
- }
- for(key in child){
- if(!hasOwn(parent ,key)){ // parent 中循环过地方不进行循环
- magerField(key) // ----忘记写
- }
- }
- // 默认合并策略
- function magerField(key){
- // 自定义策略 默认策略
- // console.log(key)
- var result = strats[key] || defaultStrat // ---忘记写
- options[key] = result(parent[key],child[key] , key , vm)
- }
- // console.log(options)
- return options
- }
- function initMinxin(options){
- Vue.prototype._init = function(options){
- var vm = this
- // 记录生成的vue实例对象
- vm._uip = uip++ // //-------忘记写
- vm.$options =mergeOptions(resolveConstructorOptions(vm.constructor),options,vm)
- }
- }
- function Vue(options){
- // 安全机制
- if(!(this instanceof Vue)){ //-------忘记写
- warn('Vue是一个构造函数,必须是由new关键字调用')
- }
- this._init(options)
- }
- initMinxin() // 初始化选项1: 规范 2: 合并策略。
- Vue.options = {
- components: {
- transtions: {},
- keepAlive:{},
- solt:{},
- transtionsGroup:{}
- },
- directives:{},
- _bash: Vue
- }
- function initExend(Vue){
- Vue.extend = function(extendOptions){
- extendOptions = extendOptions || {} // -----忘记写
- var Super = this
- var Child = function VueComponent(options) {
- this._init(options)
- }
- Child.prototype = Object.create(Super.prototype)
- Child.prototype.constructor = Child // 改变constructor 的指向
- Child.options = mergeOptions(Super.options,extendOptions)
- // 子类继承父类的静态方法。
- Child.extend = Vue.extend
- // console.log(new Child({}))
- return Child
- }
- }
- initExend(Vue)
- return Vue
- })
dome.html 代码如下
- <body>
- <div id="app">
- <huml></huml>
- </div>
- <script src="vue.js"></script>
- <!-- <script src="vue2.5.1.js"></script> -->
- <script type="text/javascript">
- var componentA = {
- el: "#app"
- }
- var vm = new Vue({
- el:"#app",
- data: {
- message: "hello Vue",
- key: "wodow"
- },
- components:{
- humle: componentA
- }
- })
- // console.log(Vue)
- var Parent = Vue.extend({
- data: function() {},
- components:{
- huml: componentA
- },
- created : function(){
- },
- watch: {
- test: function(){}
- }
- })
- var Child = Parent.extend({
- components:{
- humlt: componentA
- },
- created: function(){
- },
- watch: {
- aa: function(){},
- test: function(){}
- }
- });
- // console.log(vm.$options)
- console.log (Parent.options)
- console.log(Child.options)
- </script>
- </body>
以上仅为个人学习笔记,如有疑问,请评论回复
【js】vue 2.5.1 源码学习 (四) 钩子函数 资源选项 watch 的合并策略的更多相关文章
- 【js】 vue 2.5.1 源码学习(五) props directives规范化 props 合并策略
大体思路 (四) 上节回顾: A: 对于生命周期函数将父子组件的函数放到一个数组里面,特定时间点调用,保证父子组件函数都调用到. B: 对于directive,filters,components 等 ...
- 如何实现全屏遮罩(附Vue.extend和el-message源码学习)
[Vue]如何实现全屏遮罩(附Vue.extend和el-message源码学习) 在做个人项目的时候需要做一个类似于电子相册浏览的控件,实现过程中首先要实现全局遮罩,结合自己的思路并阅读了(饿了么) ...
- 【js】vue 2.5.1 源码学习 (三) Vue.extend 和 data的合并策略
大体思路 (三) 1. 子类父类 2.Vue.extend() //创建vue的子类 组件的语法器 Vue.extend(options) Profile().$mount('#app' ...
- 【js】vue 2.5.1 源码学习(二) 策略合并
一. 整体思路 1 首先是代码的大体构造,先判断引入代码的环境,即对应amd 和cmd的处理 2 vue_init 需要借助 initMinxin ==>>> ...
- 【js】 vue 2.5.1 源码学习(十二)模板编译
大体思路(十) 本节内容: 1. baseoptions 参数分析 2. options 参数分析 3. parse 编译器 4. parseHTNL 函数解析 // parse 解析 parser- ...
- 【js】vue 2.5.1 源码学习 (十一) 模板编译compileToFunctions渲染函数
大体思路(九) 本节内容: 1. compileToFunctions定位 1. compileToFunctions定位 ==> createCompiler = createCompiler ...
- 【js】vue 2.5.1 源码学习 (十) $mount 挂载函数的实现
大体思路(九) 本节内容: 1. $mount 挂载函数的实现. // 将Vue.prototype.$mount 缓存下来 ==>mountComponet(this,el) { // 组建挂 ...
- 【js】vue 2.5.1 源码学习 (九) 响应数组对象的变
大体思路(八) 本节内容: 1.Observe 如何响应数组的变化 代理原型 数组变异方法 shell cacheArrProto methods 新添加的数组需要加到显示系统里面,拦截 push等的 ...
- 【js】Vue 2.5.1 源码学习 (八)响应式入口observe
大体思路(七) 本节内容: deps 依赖收集的数组对象 => Dep 构造函数 /** ==> observe() * var ob * ==> if --isObject * = ...
随机推荐
- CodePlus2017 12月月赛 div2火锅盛宴
当时看到这道题感觉真是难过,我数据结构太弱啦. 我们来看看需要求什么: 1.当前熟了的食物的最小id 2.当前熟了的食物中有没有编号为id的食物 3.当前没熟的食物中有没有编号为id的食物 4.当前没 ...
- 移动项目到centos中运行报错:failed to open stream: Permission denied
这是文件夹没有读写权限的错误: (注意:TP5.0权限给runtime文件夹就行了,官方文档在安装tp5的方法中有介绍到权限问题) 在需要赋予权限的文件夹的前一级输入: chmod -R 文件夹名字
- springboot security 安全
spring security几个概念 “认证”(Authentication) 是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统) . “授权 ...
- Facebook POP动效库使用教程
编者注:用Origami作iOS动效的同学如果愁怎么实现,可以把这个给开发看看作为参考哦 如果说Origami这款动效原型工具是Facebook Paper的幕后功臣,那么POP便是Origami的地 ...
- 简单的requestAnimationFrame动画
html部分 <div id="test" style="width:1px;height:17px;background:#0f0;">0%< ...
- TensorFlow3学习笔记1
1.简单实例:向量相加 下面我们通过两个向量相加的简单例子来看一下Tensorflow的基本用法. [1. 1. 1. 1.] + [2. 2. 2. 2.] = [3. 3. 3. 3.] impo ...
- cmd 命令重启远程服务器
今天,连接服务器突然无法连接远程桌面,更无法重新启动机器,先进行了ping 操作: 机器运行正常... 后通过远程软件发现,可以用命令...这是一个新发现 …^ .^ 1.输入cmd 运行正常. ...
- 快速删除项目中的输出日志console.log
项目开发时,控制台往往有许多忘记删除或注释掉的输出日志.但是上线后总不能一个一个删吧,最近总结出几个解决思路 重写console.log方法,使其失去 输出能力 这个最直接有效,用vue框架的话放在m ...
- 走近科学,探究阿里闲鱼团队通过数据提升Flutter体验的真相
背景 闲鱼客户端的flutter页面已经服务上亿级用户,这个时候Flutter页面的用户体验尤其重要,完善Flutter性能稳定性监控体系,可以及早发现线上性能问题,也可以作为用户体验提升的衡量标准. ...
- 《C语言深度解剖》学习笔记之预处理
第3章 预处理 1.下面两行代码都是错的.因为注释先于预处理指令被处理,当这两行被展开成“//……”和“/*……*/”时,注释已处理完毕,所以出现错误 #define BSC // #define B ...