zoukankan      html  css  js  c++  java
  • 【js】Vue 2.5.1 源码学习 (八)响应式入口observe

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