国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【Vue 2.0】核心源碼解讀 -- 不定期更新

sunsmell / 2919人閱讀

摘要:觀察員由模板解析指令創(chuàng)建的觀察員負(fù)責(zé)模板中的更新視圖操作。觀察員種類目前了解情況來看主要分三類視圖指令的計(jì)算屬性的用戶自定義的

介紹

關(guān)于 Vue.js 的原理一直以來都是一個(gè)話題。經(jīng)過幾天的源碼學(xué)習(xí)和資料介紹,我將一些個(gè)人理解的經(jīng)驗(yàn)給寫下來,希望能夠與大家共勉。

附上GITHUB源碼地址, 如果有任何不解 可以在 文章下面提出或者寫下issue, 方便大家回答和學(xué)習(xí), 有興趣可以Star.
最后附上 LIVE DEMO

簡單圖解 Vue.js 內(nèi)置對象

構(gòu)造實(shí)例對象

應(yīng)用創(chuàng)建時(shí)需要使用的構(gòu)造函數(shù)對象, data 為我們的數(shù)據(jù)模型

const vm = new Vue({
  data: {
      foo: "hello world"
  }
});
數(shù)據(jù)雙向綁定 被觀察者 observe

被觀察對象,data屬性里的值的變化,get時(shí)檢查是否有新的觀察員需要加入觀察員集合, set時(shí)通知觀察員集合里的觀察員更新視圖,被觀察者有一個(gè)觀察員的集合對象。

觀察員集合對象 Dep

一個(gè)觀察員的收集器, depend()負(fù)責(zé)將當(dāng)前的 Dep.target 觀察員加入觀察員集合, data 中的每一項(xiàng)數(shù)據(jù)都會(huì)有對應(yīng)的閉包dep對象, 數(shù)據(jù)對象會(huì)有一個(gè)內(nèi)置的dep對象,用來通知嵌套的數(shù)據(jù)對象變化的情況。

觀察員 watcher

由模板解析指令創(chuàng)建的觀察員, 負(fù)責(zé)模板中的更新視圖操作。保留舊的數(shù)據(jù),以及設(shè)置鉤子函數(shù) update(), 等待被觀察者數(shù)據(jù)通知更新,對比新的value與舊數(shù)據(jù), 從而更新視圖。

數(shù)據(jù)代理 proxyData

我們的關(guān)注點(diǎn)在與創(chuàng)建后的vm, 其 options.data, 被掛載至vm._data, 同時(shí)被代理至 vm 上, 以至于 vm._data.foo 等價(jià)于 vm.foo, 代理函數(shù)代碼如下:

const noop = function () {}
const sharedPropertyDefinition = {
  enumerable: true,
  configurable: true,
  get: noop,
  set: noop
}

function proxy (target, sourceKey, key) {
  sharedPropertyDefinition.get = function proxyGetter () {
    return this[sourceKey][key]
  }
  sharedPropertyDefinition.set = function proxySetter (val) {
    this[sourceKey][key] = val
  }
  Object.defineProperty(target, key, sharedPropertyDefinition)
}

// initState 時(shí)執(zhí)行 initData
function initData () {
    
    const keys = Object.keys(data)
    let i = keys.length
    while (i--) {
      const key = keys[i]
      // key不以 $ 或 _開頭
      if (!isReserved(key)) {
        proxy(vm, `_data`, key)
      }
    }
    // do something
}
數(shù)據(jù)劫持 defineProperty
/**
 * Define a reactive property on an Object.
 */
function defineReactive(obj, key, val) {

  // 觀察員集合
  const dep = new Dep();
  
  // data 內(nèi)屬性描述 
  const property = Object.getOwnPropertyDescriptor(obj, key);

  // 屬性不可再次修改
  if (property && property.configurable === false) {
    return;
  }

  // 屬性預(yù)定義 getter/setters
  const getter = property && property.get;
  const setter = property && property.set;

  // 如果val為對象, 獲取val的 被觀察數(shù)據(jù)對象 __ob__
  let childOb = observe(val);
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      // 被觀察數(shù)據(jù)被使用時(shí), 獲取被觀察員最新的數(shù)據(jù)
      const value = getter ? getter.call(obj) : val
      
      // 觀察員在new時(shí)或使用 get()時(shí), 注入給被觀察員對象集合
      if (Dep.target) {
        // 將當(dāng)前的 watcher 傳遞給 觀察員
        dep.depend();
        if (childOb) {
          // 將當(dāng)前的 watcher 傳遞給子對象的 觀察員
          childOb.dep.depend();
        }
      }
      return val;
    },
    set: function reactiveSetter(newVal) {
      const value = getter ? getter.call(obj) : val;
      if (newVal === value || (newVal !== newVal && value !== value)) {
        return;
      }
      if (setter) {
        setter.call(obj, newVal);
      } else {
        val = newVal;
      }
      // 新value設(shè)置被觀察者對象 __ob__
      childOb = observe(newVal);
      
      // 通知數(shù)據(jù)對象依賴的觀察員, 更新 update()
      dep.notify();
    }
  });
}
計(jì)算屬性介紹 初始化執(zhí)行過程

計(jì)算屬性的定義和使用

var vm = new Vue({
    data: {
        firstname: "li",
        lastname: "yanlong"
    },
    computed: {
        fullname () {
            return this.firstname + this.lastname;
        }
    }
});
console.log(vm.fullname);
核心代碼解讀
const computedWatcherOptions = {lazy: true};
function initComputed (vm, computedOptions) {
    // 創(chuàng)建計(jì)算屬性對應(yīng)的觀察員對象
    // 獲取計(jì)算屬性時(shí)收集 內(nèi)置數(shù)據(jù)對象的 dep
    const watchers = vm._computedWatchers = Object.create(null)
    
    for (const key in computed) {
        const userDef = computed[key]
        const getter = typeof userDef === "function" ? userDef : userDef.get
        // create internal watcher for the computed property.
        watchers[key] = new Watcher(
          vm,
          getter || noop,
          noop,
          computedWatcherOptions
        );
        if (!(key in vm)) {
          defineComputed(vm, key, userDef)
        } 
    }
}

function defineComputed (target, key, userDef) {
    // 如果不為服務(wù)端渲染,則使用緩存value
    const shouldCache = !isServerRendering()
    
    // sharedPropertyDefinition 共享屬性配置
    if (typeof userDef === "function") {
      sharedPropertyDefinition.get = shouldCache
        ? createComputedGetter(key)
        : userDef
      sharedPropertyDefinition.set = noop
    } else {
      sharedPropertyDefinition.get = userDef.get
        ? shouldCache && userDef.cache !== false
          ? createComputedGetter(key)
          : userDef.get
        : noop
      sharedPropertyDefinition.set = userDef.set
        ? userDef.set
        : noop
    }
    // 給 vm對象定義計(jì)算屬性 
    Object.defineProperty(target, key, sharedPropertyDefinition)
}

// 創(chuàng)建
function createComputedGetter (key) {
  return function computedGetter () {
    const watcher = this._computedWatchers && this._computedWatchers[key]
    if (watcher) {
      // 計(jì)算屬性的 watcher 有數(shù)據(jù)更新過, 重新計(jì)算
      if (watcher.dirty) {
        watcher.evaluate()
      }
      
      // 視圖指令 使用了計(jì)算屬性
      // 將計(jì)算屬性的watcher依賴傳遞給視圖指令的 watcher
      if (Dep.target) {
        // 源碼地址
        // https://github.com/vuejs/vue/blob/master/src/core/observer/watcher.js#L210
        watcher.depend()
      }
      return watcher.value
    }
  }
}
計(jì)算屬性知識(shí)點(diǎn)介紹

1. 計(jì)算屬性的 watcher 對象
計(jì)算屬性函數(shù)在讀取它本身的value時(shí), 使用一個(gè)watcher觀察員進(jìn)行代理. 通過對原始數(shù)據(jù)的劫持, 將watcher 觀察員添加到原始數(shù)據(jù)的dep依賴集合中.

2. deps的數(shù)據(jù)對象發(fā)生更新
舉例,如果firstname 或者 lastname 任意一個(gè)更新,那么就會(huì)設(shè)置計(jì)算屬性的watcher.dirty = true, 而當(dāng)其它指令或者函數(shù)使用,計(jì)算屬性會(huì)重新計(jì)算值,如果是視圖指令,還會(huì)重新該指令的watcher的數(shù)據(jù)對象依賴。

Watcher 觀察員種類

目前了解情況來看, 主要分三類

視圖指令的 watcher

計(jì)算屬性的 watcher

用戶自定義的 watcher

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88829.html

相關(guān)文章

  • vuex 2.0 源碼解讀

    摘要:至此它便作為一個(gè)唯一數(shù)據(jù)源而存在。改變中的狀態(tài)的唯一途徑就是顯式地提交。這樣使得可以方便地跟蹤每一個(gè)狀態(tài)的變化,從而能夠?qū)崿F(xiàn)一些工具幫助更好地了解應(yīng)用背后的基本思想,借鑒了和參考源碼解讀一架構(gòu)入門教程狀態(tài)管理 準(zhǔn)備工作 1.下載安裝運(yùn)行 這里以2.0.0-rc.6為例官網(wǎng)github下載鏈接(對應(yīng)版本):https://github.com/vuejs/vuex...點(diǎn)擊下載到本地 ...

    yvonne 評(píng)論0 收藏0
  • Vue 2.0源碼學(xué)習(xí)

    摘要:今年的月日,的版本正式發(fā)布了,其中核心代碼都進(jìn)行了重寫,于是就專門花時(shí)間,對的源碼進(jìn)行了學(xué)習(xí)。本篇文章就是源碼學(xué)習(xí)的總結(jié)。實(shí)現(xiàn)了并且將靜態(tài)子樹進(jìn)行了提取,減少界面重繪時(shí)的對比。的最新源碼可以去獲得。 Vue2.0介紹 從去年9月份了解到Vue后,就被他簡潔的API所吸引。1.0版本正式發(fā)布后,就在業(yè)務(wù)中開始使用,將原先jQuery的功能逐步的進(jìn)行遷移。 今年的10月1日,Vue的2...

    Joyven 評(píng)論0 收藏0
  • 來一打前端博客壓壓驚

    前言 本文所有內(nèi)容全部發(fā)布再個(gè)人博客主頁 https://github.com/muwoo/blogs歡迎訂閱。不過最近因?yàn)槭虑楸容^多,有一段時(shí)間沒有更新了,后面打算繼續(xù)不斷學(xué)習(xí)更新,歡迎小伙伴一起溝通交流~ 最近更新 前端單測的那些事 基于virtual dom 的canvas渲染 js Event loop 機(jī)制簡介 axios 核心源碼實(shí)現(xiàn)原理 JS 數(shù)據(jù)類型、賦值、深拷貝和淺拷貝 j...

    wangbinke 評(píng)論0 收藏0
  • 來一打前端博客壓壓驚

    前言 本文所有內(nèi)容全部發(fā)布再個(gè)人博客主頁 https://github.com/muwoo/blogs歡迎訂閱。不過最近因?yàn)槭虑楸容^多,有一段時(shí)間沒有更新了,后面打算繼續(xù)不斷學(xué)習(xí)更新,歡迎小伙伴一起溝通交流~ 最近更新 前端單測的那些事 基于virtual dom 的canvas渲染 js Event loop 機(jī)制簡介 axios 核心源碼實(shí)現(xiàn)原理 JS 數(shù)據(jù)類型、賦值、深拷貝和淺拷貝 j...

    villainhr 評(píng)論0 收藏0
  • 來一打前端博客壓壓驚

    前言 本文所有內(nèi)容全部發(fā)布再個(gè)人博客主頁 https://github.com/muwoo/blogs歡迎訂閱。不過最近因?yàn)槭虑楸容^多,有一段時(shí)間沒有更新了,后面打算繼續(xù)不斷學(xué)習(xí)更新,歡迎小伙伴一起溝通交流~ 最近更新 前端單測的那些事 基于virtual dom 的canvas渲染 js Event loop 機(jī)制簡介 axios 核心源碼實(shí)現(xiàn)原理 JS 數(shù)據(jù)類型、賦值、深拷貝和淺拷貝 j...

    xiaoqibTn 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<