首頁 > 軟體

Vue 如何關掉響應式問題

2022-09-26 14:00:19

Vue如何關掉響應式

大家都知道Vue有雙向資料繫結 ,但是很少人知道怎樣把它這個功能關掉

比如想要讓某個值的改變不改變原有值

使用 Object.freeze(),這會阻止修改現有的 property,也意味著響應系統無法再追蹤變化。

例子

var obj = {
  foo: 'bar'
}

Object.freeze(obj)

new Vue({
  el: '#app',
  data: obj
})
<div id="app">
  <p>{{ foo }}</p>
  <!-- 這裡的 `foo` 不會更新! -->
  <button v-on:click="foo = 'baz'">Change it</button>
</div>

額外 Vue 也為大家提供了一個 只能修改資料一次的方法

v-once

通過使用 v-once 指令,你也能執行一次性地插值,當資料改變時,插值處的內容不會更新。但請留心這會影響到該節點上的其它資料繫結:

<span v-once>這個將不會改變: {{ msg }}</span>

Vue響應式的處理過程

響應式是從vue範例的init方法開始的。

在Init方法中先呼叫initState()初始化vue範例的狀態,在這個方法中呼叫了initData(),initData()是把我們的data屬性注入到vue範例上,並且呼叫observe()把data物件轉換成響應式物件。於是observe()就是我們響應式的入口。

observe()做了什麼事情:observe接收一個引數value,這個引數value就是我們響應式要處理的物件。

那麼在建立observe物件時做了什麼事:來看他的建構函式

陣列的響應式處理:其實就是設定陣列的那幾個特殊方法,比如push,pop,sort等等,這些方法會改變原陣列,所以當這些方法被呼叫的時候,我們要去傳送通知。傳送通知的時候是找到陣列物件對應的ob,也就是observe物件,在找到這個observe中的dep,呼叫dep的notify方法。更改完陣列的特殊方法之後,遍歷陣列的每一個成員,對每一個成員再去呼叫observe,如果這個成員是物件的話,也會把這個物件轉換成響應式物件。

物件的響應式處理:如果當前的value是物件的話,此時會呼叫walk()方法。Walk方法裡面會遍歷這個物件的所有屬性,對每一個屬性呼叫defineReactive()。

在defineReactive中,會為每一個屬性建立dep物件,讓dep去收集依賴。如果當前屬性的值是物件,則會呼叫observe,把這個物件也轉換成響應式物件。

在defineReactive裡最核心的事情就是定義getter和setter。

在getter中去收集依賴,收集依賴時要為每一個屬性收集依賴,如果這個屬性的值是物件,他也要為這個子物件收集依賴,在getter中最終返回這個屬性的值。

在setter中首先要把新的值儲存下來,如果新的值是物件,就呼叫observe,把我們新設定的值也轉換成響應式物件。在setter中,資料發生了變化,所以要傳送通知,其實就是呼叫dep.notify()。

收集依賴的過程:

在收集依賴時,首先要呼叫watcher物件的get方法,在get方法中呼叫pushTarget,在pushTarget中會把當前的watcher物件記錄到Dep.target屬性中。

在存取data中成員的時候去收集依賴,當我們存取這個屬性的值的時候,就會去觸發defineReactive中的getter,在getter中去收集依賴。他會把我們屬性對應的watcher物件新增到dep的subs陣列中,也就是為屬性收集依賴。如果這個屬性的值也是物件,此時要建立一個childOb物件,要為我們這個子物件收集依賴。目的是將來子物件發生變化時可以傳送通知。(其實陣列中內容發生變化時,就用到了這個childOb)。

Wacher:當資料發生變化時,會呼叫dep.notify()傳送通知,他會呼叫wacher的update方法,在wacher的update方法中,會去呼叫queueWatcher函數去判斷wacher是否被處理了,如果這個wacher物件沒有被處理,則會被新增到queue佇列中,並且呼叫flushSchedulerQueue去重新整理任務佇列。

在flushSchedulerQueue函數中會觸發beforeUpdate勾點函數,然後呼叫wacher.run()方法,在wacher.run方法中去呼叫wacher的get方法去呼叫getter方法,而getter中儲存的其實就是updateComponent(此處針對渲染wacher來說的)。在wacher.run執行完成後就已經將資料更新到了檢視上,我們就可以再頁面上看見變化了,剩下一些清理工作。

他會去清空我們上一次的依賴,重置wacher中的狀態,接下來去觸發actived勾點函數,最後觸發updated勾點函數。

這就是整個響應式的處理過程。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com