vue響應(yīng)式數(shù)據(jù)的簡易實(shí)現(xiàn)過程

本文主要介紹vue響應(yīng)式數(shù)據(jù)的簡易實(shí)現(xiàn)過程

由于我的語言組織表達(dá)能力不足贝椿,所以就只能在代碼片段末尾,附上了我的個(gè)人思路。

// 發(fā)布者類
class Dep {
  constructor() {
    // 訂閱者
    this.subscribers = new Set()
  }
   // 收集訂閱者
  depend() {
    if (activeEffect) {
      this.subscribers.add(activeEffect)
    }
  }
  // 通知訂閱者更新數(shù)據(jù)
  notify() {
    this.subscribers.forEach(fun => {
      fun()
    })
  }
}

// 用來收集訂閱者 
let activeEffect = null
function watchEffect(effect) {
  activeEffect = effect
  effect()
  activeEffect = null
}

/**
 * WeakMap: 用來包裹傳入的對象(垃圾回收機(jī)制)
 * 傳入的對象:是一個(gè)map對象(用來建立對應(yīng)的映射)
 * map對象:每一項(xiàng)都是一個(gè)Dep(發(fā)布者)
 * 
 * 也就是說:getDep函數(shù)的作用就是給每一項(xiàng)數(shù)據(jù)都建立一個(gè)對應(yīng)的發(fā)布者
 */
const targetMap = new WeakMap()
// 用來建立對應(yīng)的發(fā)布者
function getDep(target, key) {
  // 根據(jù)傳入的對象,獲取對應(yīng)的map對象
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    depsMap = new Map()
    // 給對應(yīng)的map對象賦值
    targetMap.set(target, depsMap)
  }
  // 獲取key屬性對應(yīng)的dep對象(獲取key對應(yīng)的發(fā)布者)
  let dep = depsMap.get(key)
  if (!dep) {
    dep = new Dep()
    depsMap.set(key, dep)
  }
  return dep
}
// vue2
function reactive(raw) {
  Object.keys(raw).forEach(key => {
    let value = raw[key]
    const dep = getDep(raw, key)
    Object.defineProperty(raw, key, {
      get() {
        // 收集依賴
        dep.depend()
        return value
      },
      set(newValue) {
        value = newValue
        // 通知訂閱者們更新數(shù)據(jù)
        dep.notify()
      }
    })
  })
  return raw
}

// vue3
// function reactive(raw) {
//   return new Proxy(raw, {
//     get(target, key) {
//       const dep = getDep(raw, key)
//       dep.depend()
//       return target[key]
//     },
//     set(target, key, newValue) {
//       const dep = getDep(raw, key)
//       target[key] = newValue
//       dep.notify()
//     }
//   })
// }


// 測試代碼
const info = reactive({ name: 'summer', age: 18 })
const info2 = reactive({ height: 1.88, weight: 188 })

watchEffect(function () {
  console.log('effect1', info.name, info.age)
})
watchEffect(function () {
  console.log('effect2', info2.height, info2.weight)
})

info.name = 'black'
// info2.height = 1.66

/**
 * 思路:
 * 1. 定義變量并賦值時(shí)酥诽,對變量進(jìn)行截取(reactive),利用Object.defineProperty重寫它的get和set方法
 *      get方法中dep.depend用于收集數(shù)據(jù)的依賴(訂閱者)
 *      set方法中dep.notify用于通知訂閱者更新數(shù)據(jù)
 * 2. reactive方法中有g(shù)etDep()方法的執(zhí)行遏弱,getDep方法的目的是:給每個(gè)數(shù)據(jù)項(xiàng)建立一個(gè)對應(yīng)的發(fā)布者
 *      當(dāng)執(zhí)行這個(gè)函數(shù)的時(shí)候會傳入兩個(gè)參數(shù):target目標(biāo)對象盆均,key目標(biāo)對象中的屬性塞弊,
 *      第一次執(zhí)行這個(gè)函數(shù)時(shí)漱逸,target還是普通對象,這時(shí)候?qū)arget轉(zhuǎn)化為map對象游沿,并且target和map-target作為targetMap的一個(gè)鍵值對饰抒,
 *      這時(shí)候再將第一次執(zhí)行的屬性(target對象里的屬性)的屬性值都設(shè)置為dep對象(發(fā)布者)
 * 3. 類Dep,用于創(chuàng)建發(fā)布者(dep)和收集這個(gè)發(fā)布者對應(yīng)的訂閱者(subscribers)的诀黍,當(dāng)一個(gè)數(shù)據(jù)被重新賦值時(shí)袋坑,就通過notify通知訂閱者執(zhí)行,更新數(shù)據(jù)
 *      Dep中的depend用于收集這個(gè)發(fā)布者(數(shù)據(jù)項(xiàng))對應(yīng)的所有訂閱者
 */

如果看完了這篇文章眯勾,對vue整個(gè)響應(yīng)式流程感興趣的話婆誓,可以看我的另一篇文章http://www.reibang.com/p/280c45ddbc8f

如有錯(cuò)誤也颤,歡迎指正洋幻!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市翅娶,隨后出現(xiàn)的幾起案子文留,更是在濱河造成了極大的恐慌,老刑警劉巖竭沫,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件燥翅,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜕提,警方通過查閱死者的電腦和手機(jī)森书,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谎势,“玉大人拄氯,你說我怎么就攤上這事∷常” “怎么了译柏?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長姐霍。 經(jīng)常有香客問我鄙麦,道長,這世上最難降的妖魔是什么镊折? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任胯府,我火速辦了婚禮,結(jié)果婚禮上恨胚,老公的妹妹穿的比我還像新娘骂因。我一直安慰自己,他們只是感情好赃泡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布寒波。 她就那樣靜靜地躺著,像睡著了一般升熊。 火紅的嫁衣襯著肌膚如雪俄烁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天级野,我揣著相機(jī)與錄音页屠,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛辰企,可吹牛的內(nèi)容都是我干的风纠。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼牢贸,長吁一口氣:“原來是場噩夢啊……” “哼议忽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起十减,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤栈幸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后帮辟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體速址,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年由驹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了芍锚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蔓榄,死狀恐怖并炮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情甥郑,我是刑警寧澤逃魄,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站澜搅,受9級特大地震影響伍俘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勉躺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一但指、第九天 我趴在偏房一處隱蔽的房頂上張望鸳谜。 院中可真熱鬧勺鸦,春花似錦讽坏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至糖赔,卻和暖如春萍丐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背放典。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奋构。 一個(gè)月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓壳影,卻偏偏與公主長得像,于是被迫代替她去往敵國和親弥臼。 傳聞我的和親對象是個(gè)殘疾皇子宴咧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容