zoukankan      html  css  js  c++  java
  • 深入浅出Vue.js(一) 变化侦测

    变化侦测真是很难理解啊,还是需要结合书去看去学习
     
    //dep.js
    
    let uid = 0
    
    export class Dep {
        constructor(){
            this.id = uid++
            this.subs = []
        }
        addSub(sub){
            this.subs.push(sub)
        }
        removeSub(sub){
            const index = this.subs.indexOf(sub)
            if(index > -1){
                return this.subs.splice(index,1)
            }
        }
        depend(){
            if(window.target){
                window.target.addDep(this)
            }
        }
        notify(){
            const subs = this.subs.slice()
            for(let i = 0,len = subs.length;i < len;i++){
                subs[i].update()
            }
        }
    }
    

      

    //observer.js
    
    mport Dep from "./dep";
    
    function observe(value){
        if(!isObject(value)){
            return
        }
        let ob
        if(hasOwn(value,'__ob__') && value.__ob__ instanceof Observer){
            ob = value.__ob__
        }else{
            ob = new Observer(value)
        }
        return ob
    }
    
    function def(obj,key,val,enumerable){
        Object.defineProperty(obj,key,{
            value:val,
            enumerable:!!enumerable,
            writable:true,
            configurable:true
        })
    }
    
    const arrayProto = Array.prototype
    const arrayMethods = Object.create(arrayProto)
    const baseMethods = ['push','pop','shift','unshift','splice','sort','reverse']
    baseMethods.forEach(method => {
        // 缓存原始方法
        const original = arrayProto[method]
        def(arrayMethods,method,function mutator(...args){
            const result = original.apply(this,args)
            const ob = this.__ob__
            let inserted
            switch (method) {
                case 'push':
                case 'unshift':
                    inserted = args
                    break;
                case 'splice':
                    inserted = args.splice(2)
                default:
                    break;
            }
            if(inserted){
                ob.observeArray(inserted)
            }
            ob.dep.notify()
            return result
        })
    })
    
    function defineReactive(data,key,val){
        let childOb = observe(val)
        let dep = new Dep()
        Object.defineProperty(data,key,{
            enumerable:true,
            configurable:true,
            get(){
                dep.depend()
                if(childOb){
                    childOb.dep.depend()
                }
                return val
            },
            set(newVal){
                if(val === newVal){
                    return
                }
                val = newVal
                dep.notify()
            }
        })
    }
    
    export class Observer {
        constructor(value){
            this.value = value
            this.dep = new Dep()
            def(value,'__ob__',this)
            if(Array.isArray(value)){
                this.observeArray(value)
            }else{
                this.walk(value)
            }
        }
        walk(obj){
            const keys = Object.keys(obj)
            for(let i = 0;i < keys.length;i++){
                defineReactive(obj,keys[i],obj[keys[i]])
            }
        }
        // 侦测Array中的每一项
        observeArray(items){
            for(let i = 0,len = items.length;i < len;i++){
                observe(items[i])
            }
        }
    }
    

      

    //watcher.js
    
    const reg = /[^w.$]/
    
    function parsePath(path){
        if(reg.test(path)){
            return
        }
        const segments = path.split('.')
        return function(obj){
            for(let i = 0;i < segments.length;i++){
                if(!obj){
                    return
                }
                obj = obj[segments[i]]
            }
            return obj
        }
    }
    
    const seenObjects = new Set()
    
    function traverse(value){
        _traverse(value,seenObjects)
        seenObjects.clear()
    }
    
    function _traverse(val,seen){
        let i,keys
        const isArray = Array.isArray(val)
        if((!isArray && !isObject(val)) || Object.isFrozen(val)){
            return
        }
        if(val.__ob__){
            const depId = val.__ob__.dep.id
            if(seen.has(depId)){
                return
            }
            seen.add(depId)
        }
        if(isArray){
            i = val.length
            while(i--) _traverse(val[i],seen)
        }else{
            keys = Object.keys(val)
            i = keys.length
            while(i--) _traverse(val[keys[i]],seen)
        }
    }
    
    export class Watcher {
        constructor(vm,expOrFn,cb,options){
            this.vm = vm
            if(options){
                this.deep = !!options.deep
            }else{
                this.deep = false
            }
            this.deps = []
            this.depIds = new Set()
            if(typeof expOrFn === 'function'){
                this.getter = expOrFn
            }else{
                this.getter = parsePath(expOrFn)
            }
            this.cb = cb
            this.value = this.get()
        }
        get(){
            window.target = this
            let value = this.getter.call(this.vm,this.vm)
            if(this.deep){
                traverse(value)
            }
            window.target = undefined
            return value
        }
        update(){
            const oldValue = this.value
            this.value = this.get()
            this.cb.call(this.vm,this.value,oldValue)
        }
        addDep(dep){
            const id = dep.id
            if(!this.depIds.has(id)){
                this.depIds.add(id)
                this.deps.push(dep)
                dep.addSub(this)
            }
        }
        teardown(){
            let len = this.deps.length
            while(len--){
                this.deps[i].removeSub(this)
            }
        }
    }
    

      


     
  • 相关阅读:
    docker 清理日志文件
    POJ2182 Lost Cows
    POJ3468
    楼兰图腾
    P2024 [NOI2001]食物链
    POJ1733 Parity game
    洛谷P1196 [NOI2002]银河英雄传说
    洛谷P1955 [NOI2015]程序自动分析
    CF 660 C. Uncle Bogdan and Country Happiness
    CF 660A&B
  • 原文地址:https://www.cnblogs.com/zhenjianyu/p/12965985.html
Copyright © 2011-2022 走看看