国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

詳解Vue源碼學習之雙向綁定

2024-05-06 15:40:51
字體:
來源:轉載
供稿:網友

原理

當你把一個普通的 JavaScript 對象傳給 Vue 實例的 data 選項,Vue 將遍歷此對象所有的屬性,并使用 Object.defineProperty 把這些屬性全部轉為 getter/setter。Object.defineProperty 是 ES5 中一個無法 shim 的特性,這也就是為什么 Vue 不支持 IE8 以及更低版本瀏覽器。

上面那段話是Vue官方文檔中截取的,可以看到是使用Object.defineProperty實現對數據改變的監聽。Vue主要使用了觀察者模式來實現數據與視圖的雙向綁定。

function initData(vm) { //將data上數據復制到_data并遍歷所有屬性添加代理 vm._data = vm.$options.data; const keys = Object.keys(vm._data);  let i = keys.length; while(i--) {   const key = keys[i];  proxy(vm, `_data`, key); } observe(data, true /* asRootData */) //對data進行監聽}

在第一篇數據初始化中,執行new Vue()操作后會執行initData()去初始化用戶傳入的data,最后一步操作就是為data添加響應式。

實現

在Vue內部存在三個對象:Observer、Dep、Watcher,這也是實現響應式的核心。

Observer

Observer對象將data中所有的屬性轉為getter/setter形式,以下是簡化版代碼,詳細代碼請看這里。

export function observe (value) { //遞歸子屬性時的判斷 if (!isObject(value) || value instanceof VNode) {  return } ... ob = new Observer(value)}export class Observer { constructor (value) {  ... //此處省略對數組的處理  this.walk(value) } walk (obj: Object) {  const keys = Object.keys(obj)  for (let i = 0; i < keys.length; i++) {   defineReactive(obj, keys[i]) //為每個屬性創建setter/getter  } } ...}//設置set/getexport function defineReactive ( obj: Object, key: string, val: any) { //利用閉包存儲每個屬性關聯的watcher隊列,當setter觸發時依然能訪問到 const dep = new Dep() ... //如果屬性為對象也創建相應observer let childOb = observe(val) Object.defineProperty(obj, key, {  enumerable: true,  configurable: true,  get: function reactiveGetter () {   if (Dep.target) {    dep.depend() //將當前dep傳到對應watcher中再執行watcher.addDep將watcher添加到當前dep.subs中    if (childOb) { //如果屬性是對象則繼續收集依賴     childOb.dep.depend()     ...    }   }   return value  },  set: function reactiveSetter (newVal) {   ...   childOb = observe(newVal) //如果設置的新值是對象,則為其創建observe   dep.notify() //通知隊列中的watcher進行更新  } })}

創建Observer對象時,為data的每個屬性都執行了一遍defineReactive方法,如果當前屬性為對象,則通過遞歸進行深度遍歷。該方法中創建了一個Dep實例,每一個屬性都有一個與之對應的dep,存儲所有的依賴。然后為屬性設置setter/getter,在getter時收集依賴,setter時派發更新。這里收集依賴不直接使用addSub是為了能讓Watcher創建時自動將自己添加到dep.subs中,這樣只有當數據被訪問時才會進行依賴收集,可以避免一些不必要的依賴收集。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 松江区| 大城县| 望谟县| 烟台市| 廉江市| 河曲县| 民乐县| 蓬安县| 红原县| 乳山市| 潢川县| 台东市| 邹平县| 枣庄市| 崇信县| 云南省| 雅江县| 南郑县| 广平县| 唐山市| 灵丘县| 鹤岗市| 赤城县| 海城市| 旬邑县| 泾阳县| 千阳县| 荔波县| 长宁区| 错那县| 盐城市| 镇康县| 延安市| 吉木萨尔县| 泰兴市| 黄梅县| 巴林右旗| 峡江县| 文成县| 乌拉特后旗| 清徐县|