国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue偵測相關api

zhangfaliang / 2786人閱讀

vm.$watch

用法: vm.$watch( expOrFn, callback, [options] ),返回值為unwatch是一個函數用來取消觀察;下面主要理解options中的兩個參數deepimmediate以及unwatch

Vue.prototype.$watch = function (expOrFn, cb, options) {
    const vm = this
    options = options || {}
    const watcher = new Watcher(vm, expOrFn, cb, options)  
    if(options.immediate) {
        cb.call(vm, watcher,.value)
    }
    return function unwatchFn() {
        watcher.teardown()
    }
}
immediate

從上面代碼中可以看出當immediatetrue時,就會直接進行執行回調函數

unwatch 實現方式是:

將被訪問到的數據dep收集到watchs實例對象上,通過this.deps存起來

將被訪問到的數據dep.id收集到watchs實例對象上,通過this.depIds存起來

最后通過watchs實例對象的teardown進行刪除

class Watcher {
    constructor (vm, expOrFn, cb) {
        this.vm = vm
        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()
    }
    ....
    addDep (dep) {
        const id = dep.id             //參數dep是Dep實例對象
        if(!this.depIds.has(id)) {    //判斷是否存在避免重復添加
            this.depIds.add(id)       
            this.deps.push(dep)
            dep.addSub(this)         //this 是依賴
        }
    }
    teardown () {
        let i = this.deps.length
        while (i--) {
            this.deps[i].removeSub(this)
        }
    }
}
let uid = 0
class Dep {
    constructor () {
        this.id = uid++
        ...
    }
    ...
    depend () {
        if(window.target) {
            window.target.addDep(this)    //將this即當前dep對象加入到watcher對象上
        }
    }
    removeSub (sub) {
        const index = this.subs.indexOf(sub)
        if(index > -1) {
            return this.subs.splice(index, 1)
        }
    }
}
分析

當執行teardown() 時需要循環;因為例如expOrFn = function () { return this.name + this.age },這時會有兩個dep分別是nameage分別都加入了watcher依賴(this),都會加入到this.deps中,所以需要循環將含有依賴的dep都刪除其依賴

deep 需要明白的是

deep干啥用的,例如data = {arr: [1, 2, {b: 6]},當我們只是監聽data.arr時,在[1, 2, {b: 66}]這個數值內部發生變化時,也需要觸發,即b = 888

怎么做呢?
class Watcher {
    constructor (vm, expOrFn, cb, options) {
        this.vm = vm
        this.deps = []
        this.depIds = new Set()
        if(typeof expOrFn === "function") {
            this.getter = expOrFn
        }else {
            this.getter = parsePath(expOrFn)
        }
        if(options) {                    //取值
            this.deep = !!options.deep
        }else {
            this.deep = false
        }
        this.cb = cb
        this.value = this.get()
    }
    get () {
        window.target = this
        let value = this.getter.call(vm, vm)
        if(this.deep) {
            traverse(value)
        }
        window.target = undefined
        return value
    }
    ...
}
const seenObjects = new Set()
function traverse (val) {
    _traverse(val, seenObjects)
    seenObjects.clear()
}
function _traverse(val, seen) {
    let i, keys
    const isA = Array.isArray(val)
    if((!isA && isObject(val)) || Object.isFrozen(val)) {  //判斷val是否是對象或者數組以及是否被凍結
        return
    }
    if(val._ob_) {
        const depId = val._ob_.dep.id     //可以看前面一篇我們對Observer類添加了this.dep = new Dep(),所以能訪問其dep.id
        if(seen.has(depId)) {
            return
        }
        seen.add(depId)
    }
    if(isA) {
        i = val.length
        while (i--) _traverse(val[i], seen)
    } else {
        keys = Object.keys(val)
        i = keys.length
        while (i--) _traverse(val[i], seen)
    }
}
分析

window.target = this,寄存依賴

let value = this.getter.call(vm, vm) 訪問當前val,并執行get

dep.depend(),如果發現val為數組,則將依賴加入到observerdep中,也就實現了對當前數組的攔截

traverse(value) 也就是執行_traverse(val, seenObjects);核心就是對被Observerval通過val[i]通過這種操作,間接觸發get,將依賴添加到當前數值的dep中,這樣也就實現了,當內部數據發生變化,也會循環subs執行依賴的update,從而觸發回調;當是數組時,只需進行遍歷,看內部是否有Object對象即可,因為在第二步的時候,會對val進行判斷是否是數組,變改變七個方法的value,在遍歷;所以這邊只要是內部數組都會進行攔截操作,添加依賴,即對象{}這種沒沒添加依賴。

seenObjects.clear()當內部所以類型數據都添加好其依賴后,就清空。

window.target = undefined消除依賴

vm.$set

用法: vm.$set(target, key, value)

作用

對于數組,進行set則是添加新元素,并需要觸發依賴更新

對于對象,如果key值存在,則是修改value;不存在,則是添加新元素,需新元素要進行響應式處理,以及觸發更新

對于對象本身不是響應式,則直接添加key-value,無需處理

Vue.prototype.$set = function (target, key, val) {
   if(Array.isArray(target) && isValidArrayIndex(key)) {    //是數組并且key有效
        target.length = Math.max(target.length, key)   //處理key > target.length
        target.splice(key, 1, val)   //添加新元素,并輸出依賴更新同時新元素也會進行`Obsever`處理
        return val
   }
   if(key in targert && !(key in Object.prototype) {  //能遍歷并且是自身key
        target[key] = val   //觸發set,執行依賴更新
        return val
   }
   const ob = target._ob_
   if(target.isVue || (ob && ob.vm.Count) {  //不是vue實例也不是vue實例的根對象(即不是this.$data跟對象)
       //觸發警告
       return
   }
   if(!ob) {    //只添加
       target[key] = val
       return val
   }
   defineReactive(ob.value, key, val)  //進行響應式處理
   ob.dep.notify()  //觸發依賴更新
   returnv val
}
vm.$delete

用法: vm.$delete( target, key)

作用

對于數組,進行delete則是刪除新元素,并需要觸發依賴更新

對于對象,如果key值不存在,直接return,存在,刪除元素,

對于對象本身不是響應式,則只刪除key-value,無需其他處理

Vue.prototype.$delete = function (target, key) {
    if(Array.isArray(target) && isValidArrayIndex(key)) {
        target.splice(key, 1)
        return
    }
    const ob = target._ob_
    if(target.isVue || (ob && ob.vm.Count) {  //不是vue實例也不是vue實例的根對象(即不是this.$data跟對象)
        //觸發警告
        return
   }
   if(!hasOwn(target, key)) {
       return
   }
    delete target[key]
    if(!ob) {
        return
    }
    ob.dep.notify()
}

掘金地址

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/109735.html

相關文章

  • vue的變化偵測

    摘要:由來最近在看深入淺出,第一篇變化偵測,想把自己的理解總結一下。的變化偵測總結一下我看了后的理解將數據變成可響應式的,即將數據變成可監聽的。由來 最近在看深入淺出vuejs,第一篇變化偵測,想把自己的理解總結一下。 Object的變化偵測 總結一下我看了后的理解 將數據變成可響應式的,即將數據變成可監聽的。通過Observer類來實現 依賴是什么?就是這個數據在哪里用到了,相當于this當...

    zhoutk 評論0 收藏0
  • vue的變化偵測

    摘要:由來最近在看深入淺出,第一篇變化偵測,想把自己的理解總結一下。的變化偵測總結一下我看了后的理解將數據變成可響應式的,即將數據變成可監聽的。 由來 最近在看深入淺出vuejs,第一篇變化偵測,想把自己的理解總結一下。 Object的變化偵測 總結一下我看了后的理解 將數據變成可響應式的,即將數據變成可監聽的。通過Observer類來實現 依賴是什么?就是這個數據在哪里用到了,相當于th...

    Freeman 評論0 收藏0
  • 深入淺出Vue響應式原理

    摘要:總結最后我們依照下圖參考深入淺出,再來回顧下整個過程在后,會調用函數進行初始化,也就是過程,在這個過程通過轉換成了的形式,來對數據追蹤變化,當被設置的對象被讀取的時候會執行函數,而在當被賦值的時候會執行函數。 前言 Vue 最獨特的特性之一,是其非侵入性的響應式系統。數據模型僅僅是普通的 JavaScript 對象。而當你修改它們時,視圖會進行更新。這使得狀態管理非常簡單直接,不過理解...

    yiliang 評論0 收藏0
  • Zepto 源碼分析 2 - Polyfill 設計

    摘要:此模塊包含的設計思路即為預以匹配降級方案。沒有默認編譯該模塊,以及利用該模塊判斷后提供平臺相關邏輯的主要原因在于其設計原則的代碼完成核心的功能。此處,也引出了代碼實現的另一個基本原則面向功能標準,先功能覆蓋再優雅降級。 在進入 Zepto Core 模塊代碼之前,本節簡略列舉 Zepto 及其他開源庫中一些 Polyfill 的設計思路與實現技巧。 涉及模塊:IE/IOS 3/Dete...

    chuyao 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<