最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3模塊創(chuàng)建runtime-dom源碼解析

 更新時(shí)間:2023年01月12日 10:30:51   作者:騶虞  
這篇文章主要為大家介紹了vue3模塊創(chuàng)建runtime-dom源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

runtime-dom 是針對瀏覽器的運(yùn)行時(shí),包括 DOM 操作、props(例如class、事件、樣式以及其它attributes)的更新等內(nèi)容;本小節(jié)我們開啟 runtime-dom 的篇章。

創(chuàng)建模塊

packages/runtime-dom/ 目錄下創(chuàng)建目錄文件:

│  │  └─ src
│  │     ├─ index.ts
│  │     ├─ modules
│  │     │  ├─ attr.ts  // attributes 的更新方法
│  │     │  ├─ class.ts // class 的更新
│  │     │  ├─ event.ts // 事件綁定的更新
│  │     │  └─ style.ts // style屬性的更新
│  │     ├─ nodeOps.ts  // dom操作方法
│  │     └─ patchProp.ts    // 屬性更新操作

創(chuàng)建 runtime-dom/package.json 文件:

{
  "name": "@vue/runtime-dom",
  "version": "1.0.0",
  "main": "index.js",
  "module": "dist/runtime-dom.esm-bundler.js",
  "unpkg": "dist/runtime-dom.global.js",
  "buildOptions": {
    "name": "VueRuntimeDOM",
    "formats": [
      "esm-bundler",
      "cjs",
      "global"
    ]
  }
}

nodeOptions

先創(chuàng)建一些操作 DOM 的方法,例如元素和文本的增刪改查:

// runtime-dom/src/nodeOps.ts
export const nodeOps = {
  // 1. 創(chuàng)建元素
  createElement(tagName) {
    return document.createElement(tagName);
  },
  // 創(chuàng)建文本節(jié)點(diǎn)
  createText(text) {
    return document.createTextNode(text);
  },
  // 2. 插入元素
  insert(child, parent, anchor) {
    // 元素移動(dòng);
    // 當(dāng)?shù)诙€(gè)參數(shù)為null時(shí),插入到末尾;
    parent.insertBefore(child, anchor || null);
  },
  // 3. 移除元素
  remove(child) {
    const parent = child.parentNode;
    if (parent) {
      parent.removeChild(child);
    }
  },
  // 4. 查詢元素
  querySelector(selector) {
    return document.querySelector(selector);
  },
  parentNode(node) {
    return node.parentNode;
  },
  nextSibling(node) {
    return node.nextSibling;
  },
  // 5. 設(shè)置文本內(nèi)容
  setElementText(el, text) {
    el.textContent = text;
  },
  setText(node, text) {
    node.nodeValue = text;
  },
};

patchProps

patchProp

再來實(shí)現(xiàn)一些屬性的更新方法:

// runtime-dom/src/patchProp.ts
import { patchAttr } from "./modules/attr";
import { patchClass } from "./modules/class";
import { patchEvent } from "./modules/event";
import { patchStyle } from "./modules/style";
export const patchProp = (el, key, prevValue, nextValue) => {
  if (key === "class") {
    // 1. class 類名
    patchClass(el, nextValue);
  } else if (key === "style") {
    // 2. 樣式
    patchStyle(el, prevValue, nextValue);
  } else if (/^on[^a-z]/.test(key)) {
    // 3. onXxx 事件
    patchEvent(el, key, nextValue);
  } else {
    // 4. 其它 attributes 屬性
    patchAttr(el, key, nextValue);
  }
};

我們將 props 分成四種類型:class、styleonXxx 事件、以及其它 attributes 屬性;分別用四種方法來處理這四種 prop。

patchClass

更新 class 屬性:

  • value 為空時(shí),使用 el.removeAttribute("class") 去掉 class 屬性;
  • 否則設(shè)置元素的 className 屬性。
// runtime-dom/src/modules/class.ts
export const patchClass = (el, value) => {
  if (value == null) {
    el.removeAttribute("class");
  } else {
    el.className = value;
  }
};

patchStyle

更新 style 屬性:

  • style 沒有新值時(shí),去掉 style 屬性;style 有新值時(shí)才進(jìn)行更新;
  • 將新的樣式添加到 style 上,如果老的 style 中有重復(fù)的,則直接將老的樣式覆蓋
  • 對于老的 style 中有、新的 style 中沒有的樣式,需要將其移除
// runtime-dom/src/modules/style.ts
export const patchStyle = (el, prev, next) => {
  if (next) {
    const style = el.style;
    // 1. 將新的樣式添加到style上,如果有重復(fù)的直接覆蓋
    for (let key in next) {
      style[key] = next[key];
    }
    for (let key in prev) {
      // 2. 老的有,新的沒有,要移除掉
      if (next[key] == null) {
        style[key] = null;
      }
    }
  } else {
    el.removeAttribute("style");
  }
};

patchEvent

更新事件(事件是以 onXxx 的形式綁定的):

  • 通過一個(gè)調(diào)用器 invoker 來存儲(chǔ)事件的回調(diào)函數(shù)(存儲(chǔ)到invoker.value上),以及執(zhí)行回調(diào)(執(zhí)行invoker.value()
  • 需要將老事件緩存起來,緩存到 el._vei 屬性上(緩存的是 invoker
  • 情況一:如果存在新的事件回調(diào)函數(shù),且在 el._vei 中存在該事件的緩存,則是更新事件;直接更新 invoker.value 即可
  • 情況二:如果存在新的事件回調(diào)函數(shù),但緩存中不存在,則是綁定新的事件;先創(chuàng)建 invoker,并將invoker 緩存到 el._vei 中,然后通過 el.addEventListener() 綁定事件
  • 情況三:如果不存在新的事件回調(diào)函數(shù),則是移除事件,直接使用 el.removeEventListener() 將該事件移除。
// runtime-dom/src/modules/event.ts
function createInvoker(initialValue) {
  const invoker = (e) => invoker.value(e);
  // 將事件的回調(diào)綁定到 invoker.value 上,后續(xù)更新事件回調(diào)的時(shí)候,只需更新 invoker.value 即可
  invoker.value = initialValue;
  return invoker;
}
export const patchEvent = (el, key, nextValue) => {
  const invokers = el._vei || (el._vei = {}); // _vei 是 vue event invoker 的縮寫
  const name = key.slice(2).toLowerCase(); // 獲取事件名
  const existingInvoker = invokers[name]; // 取緩存
  // 1. 如果是更新事件的回調(diào)
  if (nextValue && existingInvoker) {
    // 事件是存儲(chǔ)到 invoker.value 上的,更新該屬性即可
    existingInvoker.value = nextValue;
  } else {
    // 2. 如果是綁定新的事件
    if (nextValue) {
      // 2.1 創(chuàng)建 invoker(事件的回調(diào)函數(shù)),并緩存起來(本質(zhì)是緩存到el._vei上)
      const invoker = (invokers[name] = createInvoker(nextValue));
      // 2.2 綁定事件
      el.addEventListener(name, invoker);
    } else {
      // 3. 如果是移除事件
      // 3.1 解綁事件
      el.removeEventListener(name, existingInvoker);
      // 3.2 清除緩存
      invokers[name] = null;
    }
  }
};

patchAttr

更新其它 attributes

  • 使用 el.removeAttribute() 移除屬性;
  • 使用 el.setAttribute() 新增和更新屬性
// runtime-dom/src/modules/attr.ts
export const patchAttr = (el, key, value) => {
  if (value == null) {
    el.removeAttribute(key);
  } else {
    el.setAttribute(key, value);
  }
};

總結(jié)

本小節(jié)我們大致介紹了 runtime-dom 模塊,實(shí)現(xiàn)了一些 DOM 操作和 props 更新方法; 下一小節(jié),我們將介紹 runtime-core 模塊相關(guān)的內(nèi)容。

以上就是vue3模塊創(chuàng)建runtime-dom源碼解析的詳細(xì)內(nèi)容,更多關(guān)于vue3 runtime-dom模塊創(chuàng)建的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue學(xué)習(xí)之a(chǎn)xios的使用方法實(shí)例分析

    Vue學(xué)習(xí)之a(chǎn)xios的使用方法實(shí)例分析

    這篇文章主要介紹了Vue學(xué)習(xí)之a(chǎn)xios的使用方法,結(jié)合實(shí)例形式分析了vue.js axios庫的功能及網(wǎng)絡(luò)請求相關(guān)操作技巧,需要的朋友可以參考下
    2020-01-01
  • vue使用監(jiān)聽實(shí)現(xiàn)全選反選功能

    vue使用監(jiān)聽實(shí)現(xiàn)全選反選功能

    最近做的項(xiàng)目用到了全選全不選功能,于是我就自己動(dòng)手寫了一個(gè),基于vue使用監(jiān)聽實(shí)現(xiàn)全選反選功能,具體實(shí)例代碼大家參考下本文
    2018-07-07
  • 使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問題排查及解決

    使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問題排查及解決

    使用vue3+vite開發(fā)的時(shí)候,導(dǎo)入svg圖片時(shí),同一個(gè)文件夾下的文件,其中一個(gè)路徑正常解析,另一個(gè)不行,更改文件名之后,該圖片文件就可以正常解析了,本文給大家介紹了使用vue3+vite導(dǎo)入圖片路徑錯(cuò)亂問題排查及解決,需要的朋友可以參考下
    2024-03-03
  • vue3 diff 算法示例

    vue3 diff 算法示例

    這篇文章主要為大家介紹了vue3 diff 的算法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • vue3.x項(xiàng)目降級到vue2.7的解決方案

    vue3.x項(xiàng)目降級到vue2.7的解決方案

    Vue2.7是Vue2.x的最終次要版本,下面這篇文章主要給大家介紹了關(guān)于vue3.x項(xiàng)目降級到vue2.7的解決方案,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • 基于Vue實(shí)例對象的數(shù)據(jù)選項(xiàng)

    基于Vue實(shí)例對象的數(shù)據(jù)選項(xiàng)

    下面小編就為大家?guī)硪黄赩ue實(shí)例對象的數(shù)據(jù)選項(xiàng)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • el-table?樹形數(shù)據(jù)?tree-props?多層級使用避坑

    el-table?樹形數(shù)據(jù)?tree-props?多層級使用避坑

    本文主要介紹了el-table?樹形數(shù)據(jù)?tree-props?多層級使用避坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Vue滾動(dòng)頁面到指定位置的實(shí)現(xiàn)及避坑

    Vue滾動(dòng)頁面到指定位置的實(shí)現(xiàn)及避坑

    這篇文章主要介紹了Vue滾動(dòng)頁面到指定位置的實(shí)現(xiàn)及避坑,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Vue封裝localStorage設(shè)置過期時(shí)間的示例詳解

    Vue封裝localStorage設(shè)置過期時(shí)間的示例詳解

    這篇文章主要介紹了Vue封裝localStorage設(shè)置過期時(shí)間的相關(guān)資料,在這個(gè)示例中,我們在MyComponent.vue組件的setup函數(shù)中導(dǎo)入了setItemWithExpiry和getItemWithExpiry函數(shù),并在函數(shù)內(nèi)部使用它們來設(shè)置和獲取帶有過期時(shí)間的localStorage數(shù)據(jù),需要的朋友可以參考下
    2024-06-06
  • Vue中@click.stop與@click.prevent、@click.native使用

    Vue中@click.stop與@click.prevent、@click.native使用

    這篇文章主要介紹了Vue中@click.stop與@click.prevent、@click.native使用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08

最新評論

鹤壁市| 旺苍县| 泾阳县| 大同市| 陕西省| 邵东县| 顺义区| 乐亭县| 呼玛县| 临海市| 福泉市| 大化| 安吉县| 景泰县| 丹寨县| 嫩江县| 肥乡县| 寿光市| 嘉善县| 河西区| 天津市| 胶州市| 扶余县| 嘉荫县| 广河县| 通州区| 承德市| 盈江县| 广汉市| 三亚市| 金秀| 桃源县| 当雄县| 洮南市| 临高县| 兴业县| 新郑市| 和平区| 泰州市| 南部县| 竹北市|