做爰高潮a片〈毛片〉,尤物av天堂一区二区在线观看,一本久久A久久精品VR综合,添女人荫蒂全部过程av

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題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關(guān)鍵字專題關(guān)鍵字專題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
當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

Vue 源碼分析之 Observer實(shí)現(xiàn)過程

來源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 22:17:17
文檔

Vue 源碼分析之 Observer實(shí)現(xiàn)過程

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

導(dǎo)語:

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

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

這篇文章講解上篇文章沒有覆蓋到的 Observer 部分的內(nèi)容,還是先看官網(wǎng)這張圖:

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

還是以下面的代碼為例子進(jìn)行梳理:

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

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

在源碼中,通過還原Vue 進(jìn)行實(shí)例化的過程,從開始一步一步到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 項(xiàng)中的數(shù)據(jù)進(jìn)行“觀察”,會將所有數(shù)據(jù)的變成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) {
// 如果有實(shí)例則返回實(shí)例
ob = value.__ob__
} elseif(
// 確保value是單純的對象,而不是函數(shù)或者是Regexp等情況
observerState.shouldConvert &&
!isServerRendering() &&
(Array.isArray(value) || isPlainObject(value)) &&
Object.isExtensible(value) &&
!value._isVue
) {
// 實(shí)例化一個(gè) Observer
ob = newObserver(value)
}
if(asRootData && ob) {
ob.vmCount++
}
returnob
}

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

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])
}
}
}

通過源碼可以看到,實(shí)例化Observer 過程中主要是做了兩個(gè)判斷。如果是數(shù)組,則對數(shù)組里面的每一項(xiàng)再次調(diào)用oberser 方法進(jìn)行觀察;如果是非數(shù)組的對象,遍歷對象的每一個(gè)屬性,對其調(diào)用defineReactive 方法。這里的defineReactive 方法就是核心!通過使用Object.defineProperty 方法對每一個(gè)需要被觀察的屬性添加get/set,完成依賴收集。依賴收集過后,每個(gè)屬性都會有一個(gè)Dep 來保存所有Watcher 對象。按照文章最開始的例子來講,就是對firstName和fullName分別添加了get/set,并且它們各自有一個(gè)Dep 實(shí)例來保存各自觀察它們的所有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
// 檢查屬性之前是否設(shè)置了 getter/setter
// 如果設(shè)置了,則在之后的 get/set 方法中執(zhí)行設(shè)置了的 getter/setter
constgetter = property && property.get
constsetter = property && property.set
// 通過對屬性再次調(diào)用 observe 方法來判斷是否有子對象
// 如果有子對象,對子對象也進(jìn)行依賴搜集
letchildOb = !shallow && observe(val)
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: functionreactiveGetter() {
// 如果屬性原本擁有g(shù)etter方法則執(zhí)行
constvalue = getter ? getter.call(obj) : val
if(Dep.target) {
// 進(jìn)行依賴收集
dep.depend()
if(childOb) {
// 如果有子對象,對子對象也進(jìn)行依賴搜集
childOb.dep.depend()
// 如果屬性是數(shù)組,則對每一個(gè)項(xiàng)都進(jìn)行依賴收集
// 如果某一項(xiàng)還是數(shù)組,則遞歸
if(Array.isArray(value)) {
dependArray(value)
}
}
}
returnvalue
},
set: functionreactiveSetter(newVal) {
// 如果屬性原本擁有g(shù)etter方法則執(zhí)行
// 通過getter方法獲取當(dāng)前值,與新值進(jìn)行比較
// 如果新舊值一樣則不需要執(zhí)行下面的操作
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方法則執(zhí)行
setter.call(obj, newVal)
} else{
// 如果原本沒有setter則直接賦新值
val = newVal
}
// 判斷新的值是否有子對象,有的話繼續(xù)觀察子對象
childOb = !shallow && observe(newVal)
// 通知所有的觀察者,更新狀態(tài)
dep.notify()
}
})
}

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

總結(jié)

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

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

Vue 源碼分析之 Observer實(shí)現(xiàn)過程

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

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 和田市| 灌阳县| 凌云县| 孙吴县| 淅川县| 喜德县| 金昌市| 塔河县| 通州市| 乌拉特前旗| 土默特左旗| 财经| 汪清县| 普兰店市| 怀宁县| 奉化市| 满洲里市| 三河市| 维西| 天柱县| 松滋市| 鸡东县| 塘沽区| 达孜县| 翁源县| 丽水市| 磴口县| 个旧市| 黄石市| 大港区| 万源市| 乐清市| 江川县| 沭阳县| 刚察县| 洪湖市| 栾城县| 嵊泗县| 宁蒗| 濮阳市| 忻州市|