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 相关文章推荐
CSS+JS构建的图片查看器
Jul 22 Javascript
上传图片js判断图片尺寸和格式兼容IE
Sep 01 Javascript
WordPress中鼠标悬停显示和隐藏评论及引用按钮的实现
Jan 12 Javascript
jQuery基于ID调用指定iframe页面内的方法
Jul 06 Javascript
基于jQuery实现歌词滚动版音乐播放器的代码
Sep 17 Javascript
JS图片压缩(pc端和移动端都适用)
Jan 12 Javascript
JS对象深度克隆实例分析
Mar 16 Javascript
bootstrap日期控件问题(双日期、清空等问题解决)
Apr 19 Javascript
学习使用Bootstrap页面排版样式
May 11 Javascript
Vue 2.5 Level E 发布了: 新功能特性一览
Oct 24 Javascript
详解vue项目中如何引入全局sass/less变量、function、mixin
Jun 02 Javascript
Vue实现按钮旋转和移动位置的实例代码
Aug 09 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
LotusPhp笔记之:Cookie组件的使用详解
2013/05/06 PHP
php读取csv实现csv文件下载功能
2013/12/18 PHP
微信公众平台开发(五) 天气预报功能开发
2016/12/03 PHP
php使用json_decode后数字对象转换成了科学计数法的解决方法
2017/02/20 PHP
JQUBar 基于JQUERY的柱状图插件
2010/11/23 Javascript
Javascript中产生固定结果的函数优化技巧
2013/01/16 Javascript
javascript打印大全(打印页面设置/打印预览代码)
2013/03/29 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
利用javascript实现禁用网页上所有文本框,下拉菜单,多行文本域
2013/12/14 Javascript
Jquery下EasyUI组件中的DataGrid结果集清空方法
2014/01/06 Javascript
js实现图片点击左右轮播
2015/07/08 Javascript
js获取json中key所对应的value值的简单方法
2020/06/17 Javascript
jQuery查找dom的几种方法效率详解
2017/05/17 jQuery
Vue.js鼠标悬浮更换图片功能
2017/05/17 Javascript
JS实现图片转换成base64的各种应用场景实例分析
2018/06/22 Javascript
vue2使用keep-alive缓存多层列表页的方法
2018/09/21 Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
2019/07/20 Javascript
Vue利用localStorage本地缓存使页面刷新验证码不清零功能的实现
2020/09/04 Javascript
[00:12]2018DOTA2亚洲邀请赛 Sccc亮相SOLO赛,今年他又会有什么样的战绩?
2018/04/06 DOTA
python爬虫的数据库连接问题【推荐】
2018/06/25 Python
python多线程同步之文件读写控制
2021/02/25 Python
Python pygame绘制文字制作滚动文字过程解析
2019/12/12 Python
python isinstance函数用法详解
2020/02/13 Python
Numpy 多维数据数组的实现
2020/06/18 Python
python开发入门——set的使用
2020/09/03 Python
日本一家专门经营各种箱包的大型网站:Traveler Store
2016/08/03 全球购物
英国在线房屋中介网站:Yopa
2018/01/09 全球购物
Ajax的优点和缺点
2014/11/21 面试题
中学生打架检讨书
2014/02/10 职场文书
幼儿园社区活动总结
2014/07/07 职场文书
会计岗位职责范本
2015/04/02 职场文书
召开会议通知范文
2015/04/15 职场文书
毕业设计致谢词
2015/05/14 职场文书
《卧薪尝胆》读后感3篇
2019/12/26 职场文书
详细聊聊关于Mysql联合查询的那些事儿
2021/10/24 MySQL
Python使用PyYAML库读写yaml文件的方法
2022/04/06 Python