zoukankan      html  css  js  c++  java
  • 【js】vue 2.5.1 源码学习 (九) 响应数组对象的变

    大体思路(八)
    本节内容:
    1.Observe 如何响应数组的变化
    代理原型 数组变异方法
    shell cacheArrProto methods
    新添加的数组需要加到显示系统里面,拦截 push等的方法
    swith(method){
      case:"push"/"unshift" : 存储东西}
      observer.prototype.observeArray = function(items){
      observe(item[i])
    }
    observe
      ==> var augment = hasProto ? protoAugment : copyAugment ;
      ==> augment(value, shell)

    protoAugment(target,shell) ==> 非ie
    target._proto = shell
    copyAugment(target,src,arrayKeys) ==> ie
      ==> def(target,key,src[key])
    vue.js代码如下
      1 //  大体思路(八)
      2 //  本节内容:
      3 //  1.Observe 如何响应数组的变化
      4 //      代理原型  数组变异方法  
      5 //      shell cacheArrProto methods 
      6 //      新添加的数组需要加到显示系统里面,拦截 push等的方法
      7 //      swith(method){
      8 //         case:"push"/"unshift"  : 存储东西}
      9 //      observer.prototype.observeArray = function(items){  
     10 //            observe(item[i])
     11 //     }
     12 // observe 
     13 //  ==>  var augment =   hasProto  ? protoAugment : copyAugment ;
     14 //  ==>  augment(value, shell)
     15 
     16 //  protoAugment(target,shell) ==> 非ie  
     17 //  target._proto = shell
     18 //  copyAugment(target,src,arrayKeys)  ==> ie 
     19 //     ==>  def(target,key,src[key])
     20 
     21 
     22 
     23 
     24 
     25 (function (global, factory) {
     26     // 兼容 cmd  
     27     typeof exports === 'object' && module !== 'undefined' ? module.exports = factory() :
     28     // Amd
     29     typeof define === 'function' && define.amd ? define(factory) : global.Vue = factory();
     30 })(this, function () {
     31     var uip = 0;
     32 
     33     function warn(string) {
     34         console.error('Vue Wran:' + string)
     35     }
     36 
     37     function warnNonpresent(target, key) {
     38         warn('属性方法' + key + '未在实例对象上定义,渲染功能正在尝试访问这个不存在的属性!')
     39     }
     40 
     41     function resolveConstructorOptions(Con) {
     42         var options = Con.options;
     43         // 判断是否为vm的实例 或者是子类
     44         return options
     45     }
     46     var hasOwnPropeerty = Object.prototype.hasOwnProperty
     47    
     48     function hasOwn(obj, key) {
     49         return hasOwnPropeerty.call(obj, key)
     50     }
     51 
     52     function makeMap(str, expectsLoweraseC) {
     53         if (expectsLoweraseC) {
     54             str = str.toLowerCase()
     55         }
     56         var map = Object.create(null)
     57         var list = str.split(',')
     58         for (var i = 0; i < list.length; i++) {
     59             map[list[i]] = true
     60         }
     61         return function (key) {
     62             return map[key]
     63 
     64         }
     65     }
     66     var isbuiltInTag = makeMap('slot,component', true)
     67     var isHTMLTag = makeMap(
     68         'html,body,base,head,link,meta,style,title,' +
     69         'address,article,aside,footer,header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,' +
     70         'div,dd,dl,dt,figcaption,figure,picture,hr,img,li,main,ol,p,pre,ul,' +
     71         'a,b,abbr,bdi,bdo,br,cite,code,data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,' +
     72         's,samp,small,span,strong,sub,sup,time,u,var,wbr,area,audio,map,track,video,' +
     73         'embed,object,param,source,canvas,script,noscript,del,ins,' +
     74         'caption,col,colgroup,table,thead,tbody,td,th,tr,' +
     75         'button,datalist,fieldset,form,input,label,legend,meter,optgroup,option,' +
     76         'output,progress,select,textarea,' +
     77         'details,dialog,menu,menuitem,summary,' +
     78         'content,element,shadow,template,blockquote,iframe,tfoot'
     79     );
     80     var isSVG = makeMap(
     81         'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
     82         'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
     83         'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view',
     84         true
     85     );
     86    
     87     var ASSET_TYPES = [
     88         'component',
     89         'directive',
     90         'filter'
     91     ];
     92 
     93     var LIFECYCLE_HOOKS = [
     94         'beforeCreate',
     95         'created',
     96         'beforeMount',
     97         'mounted',
     98         'beforeUpdate',
     99         'updated',
    100         'beforeDestroy',
    101         'destroyed',
    102         'activated',
    103         'deactivated',
    104         'errorCaptured'
    105     ];
    106     var methods = [
    107         'push',
    108         'pop',
    109         'shift',
    110         'unshift',
    111         'splice',
    112         'sort',
    113         'reverse'
    114     ];
    115     var cacheArrProto = Array.prototype
    116     var shell = Object.create(Array.prototype)
    117     methods.forEach(function(method){
    118         var cacheMethod = cacheArrProto[method]
    119         def(shell,method,function(){
    120             var args = []
    121             var len = arguments.length
    122             while(len--) args[len] = arguments[len]
    123             var result = cacheMethod.apply(this,args)  // 调用原来的方法
    124             var ob = this.__ob__;
    125             var inserted ;
    126             switch(method){
    127                 case 'push' : 
    128                 case 'unshift': 
    129                 inserted = args
    130                 case 'splice': 
    131                 inserted = args.slice(2);
    132             }
    133             if(inserted){
    134                 ob.observeArray(inserted)  // 奖新加入的数组加入到显示系统里面。
    135             }
    136             ob.dep.notify();
    137             return result;  //返回数组原来的答案,
    138         })
    139     })
    140     var arrayKeys = Object.getOwnPropertyNames(shell)
    141     var hasProto = '__proto__' in {}
    142     var noop = function () {}
    143     var isReservedTag = function (key) {
    144         return isHTMLTag(key) || isSVG(key)
    145     }
    146     // 检测data的属性名称是否为 _ 或者$ 开始的,这些的话是vue的其他属性的值。
    147     function isReserved(key) {
    148         var c = key.charCodeAt(0)
    149         return c === 0x24 || c === 0x5F
    150     }
    151     // 检查是否为对象
    152     function isObject(val) {
    153         return val !== null && typeof val === 'object'
    154     }
    155 
    156     function validataComponentName(key) {
    157         //检测component 的自定义名称是否合格 
    158         // 只能是字母开头或下划线,必须是字母开头
    159         if (!(/^[a-zA-Z][w-]*$/g.test(key))) {
    160             warn('组件的名称必须是字母或中横线,必须由字母开头')
    161         }
    162         // 1. 不能为内置对象,2.不能是html ,和avg的内部标签
    163         if (isbuiltInTag(key) || isReservedTag(key)) {
    164             warn('不能为html标签或者avg的内部标签')
    165         }
    166     }
    167 
    168     function checkComonpents(child) {
    169         for (var key in child.components) {
    170             validataComponentName(key)
    171         }
    172     }
    173     // 配置对象
    174     var config = {
    175         // 自定义的策略
    176         optionMergeStrategies: {}
    177     }
    178     var strats = config.optionMergeStrategies
    179     strats.el = function (parent, child, key, vm) {
    180 
    181         if (!vm) {
    182             warn('选项' + key + '只能在vue实例用使用')
    183         }
    184         return defaultStrat(parent, child, key, vm)
    185     }
    186 
    187     function mergeData(to, form) {
    188         // 终极合并
    189         if (!form) {
    190             return to
    191         }
    192         // 具体合并。  
    193     }
    194 
    195     function mergeDataorFn(parentVal, childVal, vm) {
    196         // 合并 parentVal childVal  都是函数
    197         if (!vm) {
    198             if (!childVal) {
    199                 return parentVal
    200             }
    201             if (!parentVal) {
    202                 return childVal
    203             }
    204             return function mergeDataFn(parentVal, childVal, vm) { //只是一个函数   什么样的情况下调用 加入响应式系统 
    205                 // 合并子组件对应的data 和   父组件对应的data
    206                 return mergeData(
    207                     typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal, // -----忘记写
    208                     typeof childVal === 'function' ? childVal.call(this, this) : childVal) // -----忘记写
    209             }
    210         } else { // vue实例
    211             return function mergeInstanceDataFn() { //只是一个函数   什么样的情况下调用 加入响应式系统 
    212                 var InstanceData = typeof childVal === 'function' ? childVal.call(vm, vm) : childVal; // -----忘记写
    213                 var defaultData = typeof parentVal === 'function' ? parentVal.call(vm, vm) : parentVal; // -----忘记写
    214                 if (InstanceData) {
    215                     return mergeData(InstanceData, defaultData)
    216                 } else { // -----忘记写
    217                     return defaultData
    218                 }
    219 
    220             }
    221         }
    222     }
    223     strats.data = function (parent, child, key, vm) {
    224         if (!vm) {
    225             // console.log(typeof child === 'function')
    226             if (child && !(typeof child === 'function')) {
    227                 warn('data必须返回是一个function')
    228             }
    229             return mergeDataorFn(parent, child)
    230         }
    231         return mergeDataorFn(parent, child, vm)
    232     }
    233     // 生命周期策略的合并,值等于一个function 如果是有两个,放到一个数组里面。
    234     function mergeHook(parentVal, childVal, key, vm) {
    235         // console.log(key)
    236         // console.log(parentVal.concat(childVal) )
    237         return childVal ? parentVal ? parentVal.concat(childVal) :
    238             Array.isArray(childVal) ? childVal : [childVal] : parentVal
    239     }
    240     LIFECYCLE_HOOKS.forEach(function (key) {
    241         strats[key] = mergeHook
    242     });
    243     // 检测是否为object
    244     function isPlainObject(obj) {
    245         return Object.prototype.toString.call(obj) === '[object Object]'
    246     }
    247 
    248     function assetObjectType(obj) {
    249         if (!isPlainObject(obj)) {
    250             warn('选项的值' + obj + '无效:必须是一个对象的')
    251         }
    252     }
    253     // 对parent实现链式调用。
    254     function extend(to, form) {
    255         for (key in form) {
    256 
    257             to[key] = form[key]
    258         }
    259         return to
    260     }
    261     // 实现Assets 的策略合并  conmponents  filter  diretive   
    262     function mergeAssets(parentVal, childVal, key, vm) {
    263         var parent = Object.create(parentVal || null) // 保证子类的每个值的指向都是一个新的object。否则回出现相互引用的现象。
    264         if (childVal) {
    265             assetObjectType(childVal)
    266             return extend(parent, childVal)
    267         }
    268         return parent
    269     }
    270     ASSET_TYPES.forEach(function (key) {
    271         strats[key + 's'] = mergeAssets
    272     })
    273     // 实现watch的策略和并,将相同的属性放到一个数组里面。
    274     strats.watch = function (parentVal, childVal, key, vm) {
    275         if (!childVal) {
    276             return Object.create(parentVal)
    277         }
    278         var res = {}
    279         res = extend(res, parentVal)
    280         for (var key in childVal) {
    281             var parent = res[key]
    282             var child = childVal[key]
    283             res[key] = parent ? Array.isArray(parent) ? parent.concat(child) : [parent].concat(child) :
    284                 Array.isArray(child) ? child : [child];
    285         }
    286         return res
    287     }
    288     // 实现props指令的合并策略
    289     strats.props = function (parentVal, childVal, key, vm) {
    290         if (!childVal) {
    291             return parentVal
    292         }
    293         var res = Object.create(null)
    294         extend(res, parentVal)
    295         if (childVal) {
    296             extend(res, childVal)
    297         }
    298         return res
    299     }
    300 
    301     function defaultStrat(parent, child, key, vm) {
    302         return child === undefined ? parent : child;
    303     }
    304     var cmalizeRE = /-(w)/g
    305 
    306     function camelize(val) {
    307         return val.replace(cmalizeRE, function (c, m) {
    308             return m ? m.toUpperCase() : ""
    309         })
    310     }
    311 
    312     function normalizeProps(options) {
    313         var props = options.props
    314         if (!props) {
    315             return
    316         }
    317         var i, val, name
    318         var res = {}
    319         if (Array.isArray(props)) {
    320             i = props.length
    321             while (i--) {
    322                 val = props[i]
    323                 if (toString.call(val) === '[object String]') {
    324                     name = camelize(val)
    325                     res[name] = {
    326                         type: null
    327                     }
    328                 } else {
    329                     warn('使用数组愈发时props成员' + val + '必须时一个数组')
    330                 }
    331 
    332 
    333             }
    334         } else if (isPlainObject(props)) {
    335             for (var key in props) {
    336                 val = props[key]
    337                 name = camelize(key)
    338                 res[name] = isPlainObject(val) ? val : {
    339                     type: val
    340                 }
    341             }
    342         } else {
    343             warn('选项props的值必须是一个对象或者是数组')
    344         }
    345         options.props = res
    346     }
    347 
    348     function mormalizeDirectives(options) {
    349         var dir = options.directives
    350         var res = {}
    351         if (!dir) {
    352             return
    353         }
    354         if (dir) {
    355             for (var key in dir) {
    356                 var val = dir[key]
    357                 var name = camelize(key)
    358                 if (isPlainObject(val)) {
    359                     res[name] = val
    360                 }
    361                 if (toString.call(val) === '[object Function]') {
    362                     res[name] = {
    363                         bind: val,
    364                         upata: val
    365                     }
    366                 }
    367             }
    368         }
    369         options.directives = res
    370 
    371     }
    372 
    373     function mergeOptions(parent, child, vm) {
    374         var options = {}
    375         // 检测是component 是否是合法的  
    376         checkComonpents(child)
    377         // 规范props 
    378         normalizeProps(child)
    379         // 规范 dirctives 
    380         mormalizeDirectives(child)
    381 
    382         // console.log(parent, child)
    383         for (key in parent) {
    384             magerField(key)
    385         }
    386         for (key in child) {
    387             if (!hasOwn(parent, key)) { // parent 中循环过地方不进行循环
    388                 magerField(key) // ----忘记写
    389             }
    390 
    391         }
    392         // 默认合并策略
    393         function magerField(key) {
    394             // 自定义策略  默认策略 
    395             // console.log(key)
    396             var result = strats[key] || defaultStrat // ---忘记写
    397             options[key] = result(parent[key], child[key], key, vm)
    398         }
    399         // console.log(options)
    400         return options
    401     }
    402 
    403     var allowedGlobals = makeMap(
    404         'Infinity,undefined,NaN,isFinite,isNaN,' +
    405         'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
    406         'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
    407         'require' // for Webpack/Browserify
    408     );
    409 
    410     function isNative(Ctor) {
    411         return typeof Ctor !== undefined && /native code/.test(toString.call(Ctor))
    412     }
    413     var hasproxy = typeof Proxy !== undefined && isNative(Proxy)
    414     var hasHeadler = {
    415         has: function (target, key) {
    416             var val = key in target
    417             // key 是否是全局对象 或者内置方法 _
    418             var isAllowed = allowedGlobals(key) || (typeof key === 'string' && key.charAt(0) === '_')
    419             if (!val && !isAllowed) {
    420                 warnNonpresent(target, key)
    421             }
    422             return val || !isAllowed
    423         }
    424     }
    425     var getHeadler = {
    426         get: function (target, key) {
    427             if (typeof key === 'string' && !(key in target)) {
    428                 warnNonpresent(target, key)
    429             }
    430             return target[key]
    431         }
    432     }
    433 
    434     // 数据代理
    435     function initProxy(vm) {
    436         var options = vm.$options
    437         // 判断是否是es6 是否存在Proxy
    438         if (hasproxy) {
    439             // 渲染函数拦截那些操作。 1. has 查询 2. get 或者
    440             var headler = options.render && options.render._withStripeed ?
    441                 getHeadler :
    442                 hasHeadler;
    443             vm._renderPorxy = new proxy(vm, headler)
    444         } else {
    445             // 如果不支es6  Proxy
    446             vm._renderPorxy = vm
    447         }
    448     }
    449 
    450 
    451     // 初始化当前实例的$children 和$parent 的指向
    452     function initLifeCycle(vm) {
    453         var options = vm.$options
    454         // 当前组件 父实例 
    455         var parent = options.parent // 组件的实例对象
    456         // 是否抽象组件 
    457         if (parent && !parent.abstrat) {
    458             while (parent.$options.abstrat && parent.$parent) {
    459                 parent = parent.$options.parent
    460             }
    461             parent.$children.push(vm)
    462         }
    463         vm.$parent = parent
    464         vm.$root = parent ? parent.$root : vm;
    465 
    466         vm.$children = [];
    467         vm.$refs = {};
    468 
    469         vm._watcher = null;
    470         vm._inactive = null;
    471         vm._directInactive = false;
    472         vm._isMounted = false; // 是否挂载 
    473         vm._isDestroyed = false; // 是否销毁
    474         vm._isBeingDestroyed = false; // 是否正在销毁
    475 
    476     }
    477 
    478     function callHook(vm, hook) {
    479         var options = vm.$options
    480         var obj = options[hook]
    481         if (obj) {
    482             for (var i = 0; i < obj.length; i++) {
    483                 obj[i].call(vm)
    484             }
    485         }
    486 
    487     }
    488 
    489     function getData(data, vm) {
    490         return data.call(vm, vm)
    491     }
    492 
    493     //共享的访问器对象
    494     var sharedProperty = {
    495         enumerable: true,
    496         configurable: true,
    497         get: noop,
    498         set: noop
    499     };
    500 
    501     function proxy(vm, data, key) {
    502 
    503         sharedProperty.get = function () {
    504                 // console.log("我监听到你访问了我")
    505                 return this[data][key]
    506             },
    507             sharedProperty.set = function (newVal) {
    508                 console.log("我设置了data的值" + key + "==" + newVal)
    509                 this[data][key] = newVal
    510 
    511             }
    512         Object.defineProperty(vm, key, sharedProperty)
    513     }
    514 
    515     function initData(vm) {
    516         var opts = vm.$options
    517         var data = vm.$options.data
    518         // 通过之前strats 里面合成好的数据,data是一个function ,为了独立数据调用的空间。拿到data的值。
    519         data = vm._data = typeof data === 'function' ? getData(data, vm) : data || {}
    520         if (!isPlainObject(data)) {
    521             data = {}
    522             warn('data选项应该是object对象')
    523         }
    524         // data methods props 里面属性名称不能相同
    525         var props = opts.props
    526         var methods = opts.methods
    527         for (let key in data) {
    528             if (props && hasOwn(props, key)) {
    529                 warn("props " + key + "选项已经定义为data的属性.")
    530             } else if (methods && hasOwn(methods, key)) {
    531                 warn("methods: " + key + "选项已经定义为data的属性.")
    532             } else if (!isReserved(key)) {
    533                 proxy(vm, "_data", key)
    534             }
    535 
    536         }
    537         observe(data, true)
    538     }
    539     var shouldObserve = true
    540     var toggleObserving = function (value) {
    541         shouldObserve = value
    542     }
    543 
    544     function Dep() {
    545         this.subs = []
    546     }
    547     Dep.prototype.addSub = function (sub) {
    548         this.subs.push(sub)
    549     }
    550     Dep.prototype.depend = function () {
    551         console.log("收集依赖"); //Watch 观察者
    552     }
    553     Dep.prototype.notify = function () {
    554         var subs = this.subs.slice()
    555         for (var i = 0; i < subs.length; i++) {
    556             subs[i].updata() // 数据更新的操作   Watch
    557         }
    558     }
    559     Dep.target = null
    560 
    561     function def(obj, key, val) { // data._ob_  实例对象 指向 Observer
    562         Object.defineProperty(obj, key, {
    563             value: val,
    564             enumerable: false, //不可枚举
    565             configrable: true
    566         })
    567     }
    568 
    569     function Observe(value) {
    570         this.value = value;
    571         this.vmCount = 0;
    572         this.dep = new Dep() //回调列表 依赖在什么情况调用 
    573         def(value, '_ob_', this)
    574         if(Array.isArray(value)){
    575             var augment = hasProto ?  protoAugment : copyAugment ;
    576             augment(value,shell,arrayKeys)
    577         }else{
    578             this.walk(value)
    579         }
    580        
    581     }
    582     function protoAugment(target,src){
    583         target.__proto__ = src
    584     }
    585     function copyAugment(target,src,keys){
    586         for(var i =0, j=keys.length; i<j; i++){
    587             var key = keys[i];
    588             def(target, key, src[key]);
    589         }
    590         console.log(target)
    591     }
    592     // 加入响应式系统   添加   setter  getter
    593     function defindReactive(obj, key, val, shallow) {
    594         var dep = new Dep() // 收集依赖  回调列表
    595         var property = Object.getOwnPropertyDescriptor(obj, key)
    596         var getter = property && property.get
    597         var setter = property && property.set
    598         // getter 和 setter 都不存在。或者都存在则为 true ===》 (!getter || setter)
    599         // console.log((!getter || setter),arguments)
    600         if ((!getter || setter) && arguments.length === 2) {
    601             val = obj[key] // 深度观测  
    602         }
    603         var childOb = !shallow && observe(val)
    604         Object.defineProperty(obj, key, {
    605             get: function () {
    606                 var value = getter ? getter.call(obj) : val
    607                 if (Dep.target) {
    608                     dep.depend()  // 收集依赖
    609                     if (childOb) {
    610                         childOb.dep.depend()  // 收集依赖
    611                     }
    612                 }
    613                 return value
    614             },
    615             set: function (newVal) {
    616                 var value = setter ? setter.call(obj) : val
    617                 // is NaN !== NaN
    618                 if (newVal === value || (value !== value && newVal !== newVal)) {
    619                     return
    620                 }
    621                 if (setter) {
    622                     setter.call(obj, newVal)
    623                 } else {
    624                     val = newVal
    625                 }
    626                 console.log('我监听到data变化' + newVal)
    627                 // 如果改变的新值为 object 或者Array 就在进行深度检测,递归。
    628                 childOb = !shallow && observe(val)
    629                 dep.notify() //通知依赖更新
    630 
    631             }
    632         })
    633     }
    634     Observe.prototype.walk = function (value) {
    635         var keys = Object.keys(value)
    636         for (var i = 0; i < keys.length; i++) {
    637             defindReactive(value, keys[i])
    638         }
    639     }
    640     Observe.prototype.observeArray = function(items){
    641         items.forEach(function(item){
    642             observe(item)
    643         })
    644     }
    645     // 响应式系统
    646     function observe(value, asRootData) {
    647         var ob
    648         if (!isObject(value)) {
    649             return;
    650         }
    651         if(hasOwn(value,'_ob_') && value._ob_ instanceof Observe){
    652             ob= value._ob_
    653 
    654         }else if (shouldObserve && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value) && !value._isVue) {
    655             ob = new Observe(value)
    656         }
    657         if (ob && asRootData) {
    658             ob.vmCount++
    659         }
    660 
    661         return ob
    662     }
    663 
    664     function initState(vm) {
    665         var opts = vm.$options
    666         // 初始化props
    667         if (opts.props) {
    668             initProps(vm, opts.props)
    669         }
    670         // 初始化methods
    671         if (opts.methods) {
    672             initMethods(vm, opts.methods)
    673         }
    674         // 初始化computed
    675         if (opts.computed) {
    676             initComputed(vm, opts.computed)
    677         }
    678         // 初始化data 如果存在就initData
    679         if (opts.data) {
    680             initData(vm)
    681         } else {
    682             // 放在响应式系统里面
    683             observe(vm._data = {}, true)
    684         }
    685     }
    686 
    687     function initMinxin(options) {
    688         Vue.prototype._init = function (options) {
    689             var vm = this
    690             // 记录生成的vue实例对象 
    691             vm._uip = uip++ //   //-------忘记写
    692             // 是否可扩展
    693             vm.is_Vue = true;
    694             //合并选项
    695             vm.$options = mergeOptions(resolveConstructorOptions(vm.constructor), options, vm)
    696             // // 初始化数值代理
    697             initProxy(vm)
    698             // 初始化当前实例的$children 和$parent 的指向
    699             initLifeCycle(vm)
    700             // 调用beforeCreate 的钩子函数
    701             callHook(vm, 'beforeCreate')
    702             // 初始化数据
    703             initState(vm)
    704         }
    705     }
    706 
    707     function Vue(options) {
    708         // 安全机制
    709         if (!(this instanceof Vue)) { //-------忘记写
    710             warn('Vue是一个构造函数,必须是由new关键字调用')
    711         }
    712         this._init(options)
    713     }
    714     initMinxin() //  初始化选项1: 规范 2: 合并策略。
    715     Vue.options = {
    716         components: {
    717             transtions: {},
    718             keepAlive: {},
    719             solt: {},
    720             transtionsGroup: {}
    721         },
    722         directives: {},
    723         _bash: Vue
    724     }
    725 
    726     function initExend(Vue) {
    727         Vue.extend = function (extendOptions) {
    728             extendOptions = extendOptions || {} // -----忘记写
    729             var Super = this
    730             var Child = function VueComponent(options) {
    731                 this._init(options)
    732             }
    733             Child.prototype = Object.create(Super.prototype)
    734             Child.prototype.constructor = Child // 改变constructor 的指向
    735             Child.options = mergeOptions(Super.options, extendOptions)
    736             // 子类继承父类的静态方法。
    737             Child.extend = Vue.extend
    738             // console.log(new Child({}))
    739             return Child
    740         }
    741     }
    742     initExend(Vue)
    743     return Vue
    744 })
    View Code

    html代码

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     7     <title>第八课</title>
     8 </head>
     9 <body>
    10     <div id="app">
    11         <huml></huml>
    12      
    13     </div>
    14     <script src="vue.js"></script>
    15     <!-- <script src="vue2.5.1.js"></script> -->
    16     <script type="text/javascript">
    17         var componentA = {
    18             el: "#app"
    19         }
    20         var vm = new Vue({
    21             el:"#app",
    22             data: { 
    23                 message: "hello Vue",
    24                 key: "wodow",
    25                 test: 1,
    26                 list: {
    27                     b:1
    28                 },
    29                 aa:{
    30                     b: [1,2,3]
    31                 }
    32             },
    33             beforeCreate: function(){
    34                 console.log('我钩子函数beforeCreate')
    35             },
    36             components:{
    37                 humle: componentA
    38             } 
    39         })
    40         vm.test = 2;
    41         // console.log(vm.aa)
    42     </script>
    43 </body>
    44 </html>
    View Code
  • 相关阅读:
    jsp 生成验证码代码
    成为Java顶尖程序员 ,看这11本书就够了
    自动清除浏览器缓存-Cache Killer
    移动端-ios-上拉加载卡顿
    移动端-ios-点击阴影去除
    转--Android开发实践:使用Service还是Thread
    Android入门:Handler简介与实例
    Spring事务的隔离级别
    ThreadLocal的内存泄漏问题
    Spring 使用注解方式进行事务
  • 原文地址:https://www.cnblogs.com/yeujuan/p/11169055.html
Copyright © 2011-2022 走看看