<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        Vue 源碼分析之 Observer實現過程

        來源:懂視網 責編:小采 時間:2020-11-27 22:17:17
        文檔

        Vue 源碼分析之 Observer實現過程

        Vue 源碼分析之 Observer實現過程:導語: 本文是對 Vue 官方文檔深入響應式原理(https://cn.vuejs.org/v2/guide/reactivity.html)的理解,并通過源碼還原實現過程。 響應式原理可分為兩步,依賴收集的過程與觸發-重新渲染的過程。依賴收集的過程,有三個很重要的類,分別是 Watcher
        推薦度:
        導讀Vue 源碼分析之 Observer實現過程:導語: 本文是對 Vue 官方文檔深入響應式原理(https://cn.vuejs.org/v2/guide/reactivity.html)的理解,并通過源碼還原實現過程。 響應式原理可分為兩步,依賴收集的過程與觸發-重新渲染的過程。依賴收集的過程,有三個很重要的類,分別是 Watcher

        導語:

        本文是對 Vue 官方文檔深入響應式原理(https://cn.vuejs.org/v2/guide/reactivity.html)的理解,并通過源碼還原實現過程。

        響應式原理可分為兩步,依賴收集的過程與觸發-重新渲染的過程。依賴收集的過程,有三個很重要的類,分別是 Watcher、Dep、Observer。本文主要解讀 Observer 。

        這篇文章講解上篇文章沒有覆蓋到的 Observer 部分的內容,還是先看官網這張圖:

        Observer 最主要的作用就是實現了上圖中touch -Data(getter) - Collect as Dependency這段過程,也就是依賴收集的過程。

        還是以下面的代碼為例子進行梳理:

        (注:左右滑動即可查看完整代碼,下同)

        varvm = newVue({
        el: '#demo',
        data: {
        firstName: 'Hello',
        fullName: ''
        },
        watch: {
        firstName(val) {
        this.fullName = val + 'TalkingData';
        },
        }
        })

        在源碼中,通過還原Vue 進行實例化的過程,從開始一步一步到Observer 類的源碼依次為(省略了很多不在本篇文章討論的代碼):

        // src/core/instance/index.js
        functionVue(options) {
        if(process.env.NODE_ENV !== 'production'&&
        !(thisinstanceofVue)
        ) {
        warn('Vue is a constructor and should be called with the `new` keyword')
        }
        this._init(options)
        }
        // src/core/instance/init.js
        Vue.prototype._init = function(options?: Object) {
        constvm: Component = this
        // ...
        initState(vm)
        // ...
        }
        // src/core/instance/state.js
        exportfunctioninitState(vm: Component) {
        // ...
        constopts = vm.$options
        if(opts.data) {
        initData(vm)
        }
        // ...
        }
        functioninitData(vm: Component) {
        letdata = vm.$options.data
        data = vm._data = typeofdata === 'function'
        ? getData(data, vm)
        : data || {}
        // ...
        // observe data
        observe(data, true/* asRootData */)
        }

        在initData 方法中,開始了對data 項中的數據進行“觀察”,會將所有數據的變成observable 的。接下來看observe 方法的代碼:

        // src/core/observer/index.js
        functionobserve(value: any, asRootData: ?boolean): Observer| void{
        // 如果不是對象,直接返回
        if(!isObject(value) || value instanceofVNode) {
        return
        }
        letob: Observer | void
        if(hasOwn(value, '__ob__') && value.__ob__ instanceofObserver) {
        // 如果有實例則返回實例
        ob = value.__ob__
        } elseif(
        // 確保value是單純的對象,而不是函數或者是Regexp等情況
        observerState.shouldConvert &&
        !isServerRendering() &&
        (Array.isArray(value) || isPlainObject(value)) &&
        Object.isExtensible(value) &&
        !value._isVue
        ) {
        // 實例化一個 Observer
        ob = newObserver(value)
        }
        if(asRootData && ob) {
        ob.vmCount++
        }
        returnob
        }

        observe 方法的作用是給data 創建一個Observer 實例并返回,如果data 有ob屬性了,說明已經有Observer 實例了,則返回現有的實例。Vue 的響應式數據都會有一個ob的屬性,里面存放了該屬性的Observer 實例,防止重復綁定。再來看new Observer(value) 過程中發生了什么:

        exportclassObserver{
        value: any;
        dep: Dep;
        vmCount: number; // number of vms that has this object as root $data
        constructor(value: any) {
        this.value = value
        this.dep = newDep()
        this.vmCount = 0
        def(value, '__ob__', this)
        if(Array.isArray(value)) {
        // ...
        this.observeArray(value)
        } else{
        this.walk(value)
        }
        }
        walk (obj: Object) {
        constkeys = Object.keys(obj)
        for(leti = 0; i < keys.length; i++) {
        defineReactive(obj, keys[i], obj[keys[i]])
        }
        }
        observeArray (items: Array<any>) {
        for(leti = 0, l = items.length; i < l; i++) {
        observe(items[i])
        }
        }
        }

        通過源碼可以看到,實例化Observer 過程中主要是做了兩個判斷。如果是數組,則對數組里面的每一項再次調用oberser 方法進行觀察;如果是非數組的對象,遍歷對象的每一個屬性,對其調用defineReactive 方法。這里的defineReactive 方法就是核心!通過使用Object.defineProperty 方法對每一個需要被觀察的屬性添加get/set,完成依賴收集。依賴收集過后,每個屬性都會有一個Dep 來保存所有Watcher 對象。按照文章最開始的例子來講,就是對firstName和fullName分別添加了get/set,并且它們各自有一個Dep 實例來保存各自觀察它們的所有Watcher 對象。下面是defineReactive 的源碼:

        exportfunctiondefineReactive(
        obj: Object,
        key: string,
        val: any,
        customSetter?: ?Function,
        shallow?: boolean
        ) {
        constdep = newDep()
        // 獲取屬性的自身描述符
        constproperty = Object.getOwnPropertyDeor(obj, key)
        if(property && property.configurable === false) {
        return
        }
        // cater for pre-defined getter/setters
        // 檢查屬性之前是否設置了 getter/setter
        // 如果設置了,則在之后的 get/set 方法中執行設置了的 getter/setter
        constgetter = property && property.get
        constsetter = property && property.set
        // 通過對屬性再次調用 observe 方法來判斷是否有子對象
        // 如果有子對象,對子對象也進行依賴搜集
        letchildOb = !shallow && observe(val)
        Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: functionreactiveGetter() {
        // 如果屬性原本擁有getter方法則執行
        constvalue = getter ? getter.call(obj) : val
        if(Dep.target) {
        // 進行依賴收集
        dep.depend()
        if(childOb) {
        // 如果有子對象,對子對象也進行依賴搜集
        childOb.dep.depend()
        // 如果屬性是數組,則對每一個項都進行依賴收集
        // 如果某一項還是數組,則遞歸
        if(Array.isArray(value)) {
        dependArray(value)
        }
        }
        }
        returnvalue
        },
        set: functionreactiveSetter(newVal) {
        // 如果屬性原本擁有getter方法則執行
        // 通過getter方法獲取當前值,與新值進行比較
        // 如果新舊值一樣則不需要執行下面的操作
        constvalue = getter ? getter.call(obj) : val
        /* eslint-disable no-self-compare */
        if(newVal === value || (newVal !== newVal && value !== value)) {
        return
        }
        /* eslint-enable no-self-compare */
        if(process.env.NODE_ENV !== 'production'&& customSetter) {
        customSetter()
        }
        if(setter) {
        // 如果屬性原本擁有setter方法則執行
        setter.call(obj, newVal)
        } else{
        // 如果原本沒有setter則直接賦新值
        val = newVal
        }
        // 判斷新的值是否有子對象,有的話繼續觀察子對象
        childOb = !shallow && observe(newVal)
        // 通知所有的觀察者,更新狀態
        dep.notify()
        }
        })
        }

        按照源碼中的中文注釋,應該可以明白defineReactive 執行的過程中做了哪些工作。其實整個過程就是遞歸,為每個屬性添加getter/setter。對于getter/setter,同樣也需要對每一個屬性進行遞歸(判斷子對象)的完成觀察者模式。對于getter,用來完成依賴收集,即源碼中的dep.depend()。對于setter,一旦一個數據觸發其set方法,便會發布更新消息,通知這個數據的所有觀察者也要發生改變。即源碼中的dep.notify()。

        總結

        以上所述是小編給大家介紹的 Vue 源碼分析之 Observer實現過程,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網站的支持!

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Vue 源碼分析之 Observer實現過程

        Vue 源碼分析之 Observer實現過程:導語: 本文是對 Vue 官方文檔深入響應式原理(https://cn.vuejs.org/v2/guide/reactivity.html)的理解,并通過源碼還原實現過程。 響應式原理可分為兩步,依賴收集的過程與觸發-重新渲染的過程。依賴收集的過程,有三個很重要的類,分別是 Watcher
        推薦度:
        標簽: 過程 VUE 實現
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产在线98福利播放视频免费 | 日本亚洲国产一区二区三区| 国产成人精品日本亚洲网址| 亚欧在线精品免费观看一区| 亚洲综合精品一二三区在线| 中文字幕乱码免费看电影| 亚洲午夜久久久影院| 2022国内精品免费福利视频| 狠狠亚洲婷婷综合色香五月排名 | 免费播放春色aⅴ视频| 免费看一级一级人妻片| 亚洲综合精品网站在线观看| 国产美女视频免费观看的网站 | 国产精品亚洲片在线va| 成人网站免费观看| 亚洲国产精品18久久久久久| 国产乱子影视频上线免费观看| 羞羞视频免费观看| 亚洲中文字幕无码久久精品1| 一个人免费视频观看在线www | 亚洲无人区码一二三码区别图片| 24小时日本在线www免费的| 亚洲AV无码片一区二区三区| 亚洲美女在线国产| 无码国产精品一区二区免费模式 | 久久笫一福利免费导航| 亚洲精品无码高潮喷水A片软| 婷婷综合缴情亚洲狠狠尤物| 日韩免费观看一区| 亚洲中文字幕无码中文| 亚洲午夜福利精品久久| 日韩人妻无码精品久久免费一 | 免费观看久久精彩视频| 亚洲videos| 精品亚洲一区二区三区在线观看 | 免费三级毛片电影片| 黄网站色视频免费观看45分钟| 亚洲AV无码一区东京热久久 | 亚洲高清不卡视频| 国产jizzjizz免费视频| 久久A级毛片免费观看|