vue 2.5.1 源码学习 之Vue.extend 和 data的合并策略


Posted in Javascript onJune 04, 2019

1. 子类父类

 2.Vue.extend()      //创建vue的子类

组件的语法器 Vue.extend(options)

Profile().$mount('#app') // 挂在app上,并替换app

新建 initExend

==》 Vue.extend

 3. strat.data

==> if(!vm){子组件中data的值是一个方法function ==> mergeDataorFn()} // 数据的合并

==> else {} //通过实例绑定的data 实际是一个函数 mergeDataorFn

==》 mergeDataorFn if(!vm) mergeDataFn ==> mergeData()

else ==》mergedInstanceDataFn ==>mergeData()

    mergeData(to,from) //终极合并

jquery.extend // 深copy和浅copy

// 大体思路 (二)
// 1. 子类父类 
/* 
   2.Vue.extend()  //创建vue的子类
   组件的语法器 Vue.extend(options)
   Profile().$mount('#app') // 挂在app上,并替换app
   新建 initExend  
     ==》 Vue.extend
*/
/* 3. strat.data  
  ==> if(!vm){子组件中data的值是一个方法function ==> mergeDataorFn()} // 数据的合并
  ==> else {} //通过实例绑定的data 实际是一个函数 mergeDataorFn 
  ==》 mergeDataorFn if(!vm) mergeDataFn ==> mergeData()  
     else ==》mergedInstanceDataFn ==>mergeData()
  mergeData(to,from) //终极合并
  jquery.extend // 深copy和浅copy
*/
(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 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.component){
      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 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: {},
    directives:{},
    _bash: Vue
  }
  function initExend(Vue){
    Vue.extend = function(extendOptions){
      extendOptions = extendOptions || {}  // -----忘记写
      var Super = this 
      var Child = function VueComponent() {
        this._init(options)
      }
      Child.prototype = Object.create(Super.prototype)
      Child.prototype.constructor = Child  // 改变constructor 的指向
      Child.options = mergeOptions(Super.options,extendOptions)
      // 子类继承父类的静态方法。
      Child.extend = Vue.extend
      return Child
    }
  }
  initExend(Vue)
  return Vue
})
<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:{
        huml: componentA
      }
    })
    // console.log(Vue)
    var Parent = Vue.extend({
      data: function() {}
    })
    var Child = Parent.extend({});
    console.log(vm.$options)
  </script>
</body>

总结

以上所述是小编给大家介绍的vue 2.5.1 源码学习 之Vue.extend 和 data的合并策略,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
Add Formatted Text to a Word Document
Jun 15 Javascript
setTimeout 不断吐食CPU的问题分析
Apr 01 Javascript
删除select中所有option选项jquery代码
Aug 12 Javascript
Google 地图获取API Key详细教程
Aug 06 Javascript
javascript中递归的两种写法
Jan 17 Javascript
js实现符合国情的日期插件详解
Jan 19 Javascript
基于vue实现多引擎搜索及关键字提示
Mar 16 Javascript
详解从Node.js的child_process模块来学习父子进程之间的通信
Mar 27 Javascript
JavaScript运动框架 链式运动到完美运动(五)
May 18 Javascript
vue组件Prop传递数据的实现示例
Aug 17 Javascript
JS中利用FileReader实现上传图片前本地预览功能
Mar 02 Javascript
vue中英文切换实例代码
Jan 21 Javascript
vue实现分环境打包步骤(给不同的环境配置相对应的打包命令)
Jun 04 #Javascript
JavaScript实现页面中录音功能的方法
Jun 04 #Javascript
vue elementUI 表单校验功能之数组多层嵌套
Jun 04 #Javascript
小程序根据手机机型设置自定义底部导航距离
Jun 04 #Javascript
js回文数的4种判断方法示例
Jun 04 #Javascript
Vue对象赋值视图不更新问题及解决方法
Jun 03 #Javascript
在 Vue 应用中使用 Netlify 表单功能的方法详解
Jun 03 #Javascript
You might like
编写自己的php扩展函数
2006/10/09 PHP
一次编写,随处运行
2006/10/09 PHP
php 取得瑞年与平年的天数的代码
2009/08/10 PHP
php微信高级接口群发 多客服
2016/06/23 PHP
浅析PHP中的 inet_pton 网络函数
2019/12/16 PHP
滚动经典最新话题[prototype框架]下编写
2006/10/03 Javascript
表单(FORM)的一些实用效果代码
2007/03/25 Javascript
jQuery 各种浏览器下获得日期区别
2008/12/22 Javascript
js实现的日期操作类DateTime函数代码
2010/03/16 Javascript
js预载入和JavaScript Image()对象使用介绍
2011/08/28 Javascript
jQuery插件实现屏蔽单个元素使用户无法点击
2013/04/12 Javascript
JavaScript实现QueryString获取GET参数的方法
2013/07/02 Javascript
Jquery实现的一种常用高亮效果示例代码
2014/01/28 Javascript
JavaScript按位运算符的应用简析
2014/02/04 Javascript
js中通过父级进行查找定位元素
2014/06/15 Javascript
javascript中slice(),splice(),split(),substring(),substr()使用方法
2015/03/13 Javascript
jquery实现图片预加载
2015/12/25 Javascript
JS对象和字符串之间互换操作实例分析
2019/02/02 Javascript
vue中动态select的使用方法示例
2019/10/28 Javascript
vue element ui validate 主动触发错误提示操作
2020/09/21 Javascript
python3+PyQt5实现使用剪贴板做复制与粘帖示例
2017/01/24 Python
python编程实现希尔排序
2017/04/13 Python
python torch.utils.data.DataLoader使用方法
2020/04/02 Python
在django中查询获取数据,get, filter,all(),values()操作
2020/08/09 Python
关于box-sizing的全面理解
2016/07/28 HTML / CSS
俄罗斯街头服装品牌:Black Star Wear
2017/03/01 全球购物
优秀党务工作者事迹材料
2014/05/07 职场文书
党的群众路线教育实践活动宣传标语口号
2014/06/06 职场文书
党员群众路线学习心得体会
2014/11/04 职场文书
2014教师年度工作总结
2014/11/10 职场文书
2014年汽车销售工作总结
2014/12/01 职场文书
2014小学二年级班主任工作总结
2014/12/05 职场文书
原料仓管员岗位职责
2015/04/01 职场文书
宇宙与人观后感
2015/06/05 职场文书
java Nio使用NioSocket客户端与服务端交互实现方式
2021/06/15 Java/Android
使用Python开发冰球小游戏
2022/04/30 Python