<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中的數據綁定原理的實現

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

        vue中的數據綁定原理的實現

        vue中的數據綁定原理的實現:本文主要介紹了vue中的數據綁定原理的實現,分享給大家,也給自己留個筆記,具體如下: vue中的響應式數據綁定是通過數據劫持和觀察者模式來實現的。當前學習源碼為vue2.0 源碼關鍵目錄 src |---core | |---instance | |---init.js
        推薦度:
        導讀vue中的數據綁定原理的實現:本文主要介紹了vue中的數據綁定原理的實現,分享給大家,也給自己留個筆記,具體如下: vue中的響應式數據綁定是通過數據劫持和觀察者模式來實現的。當前學習源碼為vue2.0 源碼關鍵目錄 src |---core | |---instance | |---init.js

        本文主要介紹了vue中的數據綁定原理的實現,分享給大家,也給自己留個筆記,具體如下:


        vue中的響應式數據綁定是通過數據劫持和觀察者模式來實現的。當前學習源碼為vue2.0

        源碼關鍵目錄

        src
        |---core
        | |---instance
        | |---init.js
        | |---state.js
        | |---observer
        | |---dep.js
        | |---watcher.js
        

        當我們實例化一個vue應用的時候,會伴隨著各種的初始化工作,相關的初始化工作代碼在init.js文件中

        // src/core/instance/init.js
        
        Vue.prototype._init = function (options?: Object) {
         ...
         initLifecycle(vm)
         initEvents(vm)
         callHook(vm, 'beforeCreate')
         initState(vm)
         callHook(vm, 'created')
         initRender(vm)
        }
        
        

        在這里可以看到對state的初始化工作initState()

        // src/core/instance/state.js
        
        export function initState (vm: Component) {
         vm._watchers = []
         initProps(vm)
         initData(vm)
         initComputed(vm)
         initMethods(vm)
         initWatch(vm)
        }
        
        

        可以看到這里有對各種sate的初始化工作,我們看initData()

        // src/core/instance/state.js
        
        function initData (vm: Component) {
         let data = vm.$options.data
         data = vm._data = typeof data === 'function'
         ? data.call(vm)
         : data || {}
         if (!isPlainObject(data)) {
         data = {}
         process.env.NODE_ENV !== 'production' && warn(
         'data functions should return an object.',
         vm
         )
         }
         // proxy data on instance
         const keys = Object.keys(data)
         const props = vm.$options.props
         let i = keys.length
         while (i--) {
         if (props && hasOwn(props, keys[i])) {
         process.env.NODE_ENV !== 'production' && warn(
         `The data property "${keys[i]}" is already declared as a prop. ` +
         `Use prop default value instead.`,
         vm
         )
         } else {
         proxy(vm, keys[i])
         }
         }
         // observe data
         observe(data)
         data.__ob__ && data.__ob__.vmCount++
        }
        
        

        這里做了一點判斷,判斷data方法是否返回的是一個對象,以及props中是否有與data中重名的屬性,最后會調用observe對data進行監聽,看一下observe

        // src/core/observer/index.js
        
        export function observe (value: any): Observer | void {
         if (!isObject(value)) {
         return
         }
         let ob: Observer | void
         if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
         ob = value.__ob__
         } else if (
         observerState.shouldConvert &&
         !config._isServer &&
         (Array.isArray(value) || isPlainObject(value)) &&
         Object.isExtensible(value) &&
         !value._isVue
         ) {
         ob = new Observer(value)
         }
         return ob
        }
        
        

        可已看到這里也是做了一點判斷,如果有__ob__屬性的話就用它,或者如果data是數組或對象或可擴展對象的話,就為它新建一個Observer,看一下Observer

        // src/core/observer/index.js
        
        export class Observer {
         value: any;
         dep: Dep;
         vmCount: number; // number of vms that has this object as root $data
        
         constructor (value: any) {
         this.value = value
         this.dep = new Dep()
         this.vmCount = 0
         def(value, '__ob__', this)
         if (Array.isArray(value)) {
         const augment = hasProto
         ? protoAugment
         : copyAugment
         augment(value, arrayMethods, arrayKeys)
         this.observeArray(value)
         } else {
         this.walk(value)
         }
         }
        
         /**
         * Walk through each property and convert them into
         * getter/setters. This method should only be called when
         * value type is Object.
         */
         walk (obj: Object) {
         const keys = Object.keys(obj)
         for (let i = 0; i < keys.length; i++) {
         defineReactive(obj, keys[i], obj[keys[i]])
         }
         }
        
         /**
         * Observe a list of Array items.
         */
         observeArray (items: Array<any>) {
         for (let i = 0, l = items.length; i < l; i++) {
         observe(items[i])
         }
         }
        }
        
        

        判斷data是不是數組,如果是數組就對數組元素再去調用observe方法做同樣的處理,如果不是,就調用walk去劫持該數據,對數據的劫持主要再defineReactive方法中,正如函數名,讓數據變得響應式。看一下defineReactive方法

        // src/core/observer/index.js
        
        export function defineReactive (
         obj: Object,
         key: string,
         val: any,
         customSetter?: Function
        ) {
         const dep = new Dep()
        // data中的每一個成員都有一個對應的Dep,在此閉包創建。
        
         const property = Object.getOwnPropertyDescriptor(obj, key)
         if (property && property.configurable === false) {
         return
         }
        
         // cater for pre-defined getter/setters
         const getter = property && property.get
         const setter = property && property.set
        
         let childOb = observe(val)
         Object.defineProperty(obj, key, {
         enumerable: true,
         configurable: true,
         get: function reactiveGetter () {
         const value = getter ? getter.call(obj) : val
         if (Dep.target) {
         dep.depend() // 依賴收集
         if (childOb) {
         childOb.dep.depend()
         }
         if (Array.isArray(value)) {
         for (let e, i = 0, l = value.length; i < l; i++) {
         e = value[i]
         e && e.__ob__ && e.__ob__.dep.depend()
         }
         }
         }
         return value
         },
         set: function reactiveSetter (newVal) {
         const value = getter ? getter.call(obj) : val
         if (newVal === value) {
         return
         }
         if (process.env.NODE_ENV !== 'production' && customSetter) {
         customSetter()
         }
         if (setter) {
         setter.call(obj, newVal)
         } else {
         val = newVal
         }
         childOb = observe(newVal)
         dep.notify() // 發布通知
         }
         })
        }
        
        

        遍歷狀態,修改狀態的getter和setter,當頁面上對應狀態被首次渲染的時候,會為頁面上每一個使用到data的地方新建一個watcher,并將當前watcher保存到全局變量Dep.target中,在對應data的getter中就會調用Dep.depend方法,將當前的watcher添加到當前的Dep中,一個Dep對應一個或多個watcher,著取決于,此狀態被使用的數量。當data被修改時,對應的setter就會被觸發,會調用對應的Dep中的notify方法,通知所有觀察者,進行更新。

        這里出現了兩個定的類:Dep和Watcher,其中Dep管理觀察者,Wathcer代表觀察者

        先看一下Dep

        // src/core/observer/dep.js
        
        export default class Dep {
         static target: ?Watcher;
         id: number;
         subs: Array<Watcher>;
        
         constructor () {
         this.id = uid++
         this.subs = []
         }
        
         addSub (sub: Watcher) {
         this.subs.push(sub)
         }
        
         removeSub (sub: Watcher) {
         remove(this.subs, sub)
         }
        
         depend () {
         if (Dep.target) {
        // 調用當前target,也就是正在處理的watcher的addDep方法,并把此Dep傳進去
         Dep.target.addDep(this)
         }
         }
        
         notify () {
         // stablize the subscriber list first
         const subs = this.subs.slice()
         for (let i = 0, l = subs.length; i < l; i++) {
         subs[i].update()
         }
         }
        }
        
        

        看一下watcher.js

        // src/core/observer/watcher.js
        
        export default class Watcher {
        ...
         addDep (dep: Dep) {
         const id = dep.id
         if (!this.newDepIds.has(id)) {
         this.newDepIds.add(id)
         this.newDeps.push(dep)
         if (!this.depIds.has(id)) {
         // 將當前watcher添加到當前的Dep中
         dep.addSub(this)
         }
         }
         }
        ...
        }
        
        

        總結

        vue的響應式數據綁定主要依賴Object.defineProperty和觀察者模式。

        1. 在我們新建一個vue實例的時候,做一系列的初始化工作,這部分的邏輯集中在src文件夾下的core文件夾下的instance和observer文件夾內
        2. 響應式數據綁定是在狀態的初始化階段完成的,在initState方法中的initData中進行data的數據綁定。
        3. 在initData中調用observe方法,為該data新建一個Observer類,然后最終調用為data中的每一個成員調用walk方法,在walk中通過defineReactive方法劫持當前數據
        4. 在defineReactive中通過Object.defineProperty去修改數據的getter和setter
        5. 在頁面渲染的時候,頁面上每一個用到data的地方都會生成一個watcher,并將它保存到全局變量Dep.target中,watcher改變每一個觀察者,Dep用來管理觀察者。
        6. 然后在data的getter中將調用Dep的depend方法,將Dep.target中的watcher添加到此data對應的Dep中,完成依賴收集
        7. 在data被修改的時候,對應data的setter方法就會被出動,會調用Dep.notify()方法發布通知,調用每個watcher的uptade方法進行更新。

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

        文檔

        vue中的數據綁定原理的實現

        vue中的數據綁定原理的實現:本文主要介紹了vue中的數據綁定原理的實現,分享給大家,也給自己留個筆記,具體如下: vue中的響應式數據綁定是通過數據劫持和觀察者模式來實現的。當前學習源碼為vue2.0 源碼關鍵目錄 src |---core | |---instance | |---init.js
        推薦度:
        標簽: 綁定 中的 數據
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲精品久久久www| 中文字幕一精品亚洲无线一区| 亚洲精品国产成人片| 亚洲日韩在线观看| 亚洲精品V欧洲精品V日韩精品| 亚洲成a人片在线不卡一二三区| www视频免费看| 日韩精品一区二区亚洲AV观看| 久久一区二区三区免费| 亚洲一级免费毛片| 久久亚洲国产精品五月天| 中文字幕在线日亚洲9| 在线免费观看你懂的| 亚洲va在线va天堂va888www| 中文字幕免费视频一| 亚洲人成精品久久久久| 青青免费在线视频| 很黄很色很刺激的视频免费| 亚洲精品免费在线| 97人妻无码一区二区精品免费| 亚洲日韩区在线电影| www亚洲精品久久久乳| 日本视频在线观看永久免费| 亚洲熟妇av一区二区三区| 在线观看片免费人成视频无码| 欧洲亚洲国产清在高| 国产精品白浆在线观看免费| 亚洲AV人无码综合在线观看| 最近免费视频中文字幕大全| 亚洲人成电影青青在线播放| 永久免费无码网站在线观看个| 波多野结衣在线免费视频| 2020久久精品亚洲热综合一本| 女人被弄到高潮的免费视频| 欧洲亚洲国产精华液| 亚洲国产主播精品极品网红| 在线观看片免费人成视频无码 | 免费成人在线观看| 亚洲成a人片在线观看中文动漫| 99re这里有免费视频精品 | 最刺激黄a大片免费网站|