Vue——initRender【八】

来源:https://www.cnblogs.com/wangyang0210/archive/2023/03/23/17246033.html
-Advertisement-
Play Games

前言 前面我們簡單的瞭解了 vue 初始化時的一些大概的流程,這裡我們詳細的瞭解下具體的內容; 內容 這一塊主要圍繞init.ts中的initRender進行剖析,參數合併完成之後就開始了初始化生命周期。 initRender initRender位於src/core/instance/render ...


前言

前面我們簡單的瞭解了 vue 初始化時的一些大概的流程,這裡我們詳細的瞭解下具體的內容;

內容

這一塊主要圍繞init.ts中的initRender進行剖析,參數合併完成之後就開始了初始化生命周期。

initRender

initRender位於src/core/instance/render.ts

export function initRender(vm: Component) {
  vm._vnode = null // the root of the child tree
  vm._staticTrees = null // v-once cached trees
  const options = vm.$options
  const parentVnode = (vm.$vnode = options._parentVnode!) // the placeholder node in parent tree
  const renderContext = parentVnode && (parentVnode.context as Component)
  // 插槽
  // https://v2.cn.vuejs.org/v2/api/#vm-slots
  vm.$slots = resolveSlots(options._renderChildren, renderContext)
  // 作用域插槽
  // https://v2.cn.vuejs.org/v2/api/#vm-scopedSlots
  vm.$scopedSlots = parentVnode
    ? normalizeScopedSlots(
        vm.$parent!,
        parentVnode.data!.scopedSlots,
        vm.$slots
      )
    : emptyObject
  // bind the createElement fn to this instance
  // so that we get proper render context inside it.
  // args order: tag, data, children, normalizationType, alwaysNormalize
  // internal version is used by render functions compiled from templates
  // @ts-expect-error
  // 將createElement函數綁定到實例上,以保證正確的上下文渲染順序,
  // 內部版本使用的渲染函數來自模板編譯
  vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)
  // normalization is always applied for the public version, used in
  // user-written render functions.
  // 公共版本使用用戶編寫的渲染函數
  // @ts-expect-error
  vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true)

  // $attrs & $listeners are exposed for easier HOC creation.
  // they need to be reactive so that HOCs using them are always updated
  const parentData = parentVnode && parentVnode.data

  /* istanbul ignore else */
  if (__DEV__) {
    defineReactive(
      vm,
      '$attrs',
      (parentData && parentData.attrs) || emptyObject,
      () => {
        !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm)
      },
      true
    )
    defineReactive(
      vm,
      '$listeners',
      options._parentListeners || emptyObject,
      () => {
        !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm)
      },
      true
    )
  } else {
    // 通過defineReactive將$attrs和$listeners設置為響應式數據 | 這一塊後面再詳說
    // emptyObject 返回一個被凍結的對象空對象,不能被修改其原型也不能被修改

    // 包含了父作用域中不作為 prop 被識別 (且獲取) 的 attribute 綁定 (class 和 style 除外)。
    // 當一個組件沒有聲明任何 prop 時,這裡會包含所有父作用域的綁定(class 和 style 除外),
    // 並且可以通過 v-bind="$attrs" 傳入內部組件——在創建高級別的組件時非常有用。
    // https://v2.cn.vuejs.org/v2/api/?#vm-attrs

    defineReactive(
      vm,
      '$attrs',
      (parentData && parentData.attrs) || emptyObject,
      null,
      true
    )
    // 包含了父作用域中的 (不含 .native 修飾器的) v-on 事件監聽器。
    // 它可以通過 v-on="$listeners" 傳入內部組件——在創建更高層次的組件時非常有用。
    // https://v2.cn.vuejs.org/v2/api/?#vm-listeners
    defineReactive(
      vm,
      '$listeners',
      options._parentListeners || emptyObject,
      null,
      true
    )
  }
}

resolveSlots

resolveSlots 位於 src/core/instance/render-helpers/resolve-slots.ts

**
 * Runtime helper for resolving raw children VNodes into a slot object.
 *
 * 將children VNodes 轉化為 slot 對象
 */
export function resolveSlots(
  children: Array<VNode> | null | undefined,
  context: Component | null
): { [key: string]: Array<VNode> } {
  // 如果不存在子節點直接返回空對象
  if (!children || !children.length) {
    return {}
  }
  // 定義一個slots空對象,存放slot
  const slots: Record<string, any> = {}

  // 對子節點進行遍歷
  for (let i = 0, l = children.length; i < l; i++) {
    const child = children[i]
    const data = child.data
    // remove slot attribute if the node is resolved as a Vue slot node
    // 如果節點是slot節點的話就移除slot的屬性
    if (data && data.attrs && data.attrs.slot) {
      // 刪除該節點attrs的slot
      delete data.attrs.slot
    }
    // named slots should only be respected if the vnode was rendered in the
    // same context.
    // 判斷是否為具名插槽
    // https://v2.cn.vuejs.org/v2/guide/components-slots.html#%E5%85%B7%E5%90%8D%E6%8F%92%E6%A7%BD
    if (
      (child.context === context || child.fnContext === context) &&
      data &&
      data.slot != null
    ) {
      // 獲取插槽的名字
      const name = data.slot
      // 插槽名字不存在則賦值為空數組
      const slot = slots[name] || (slots[name] = [])
      // 如果是template元素將child.children添加到數組中
      if (child.tag === 'template') {
        slot.push.apply(slot, child.children || [])
      } else {
        slot.push(child)
      }
    } else {
      // 返回匿名的slot,名字是default
      ;(slots.default || (slots.default = [])).push(child)
    }
  }
  // ignore slots that contains only whitespace
  // 忽略空白內容的插槽
  for (const name in slots) {
    // 利用every檢測指定的slots數組下的所有結果是否能夠通過isWhitespace的測試
    // 全部通過才會返回true
    if (slots[name].every(isWhitespace)) {
      delete slots[name]
    }
  }
  return slots
}

function isWhitespace(node: VNode): boolean {
  return (node.isComment && !node.asyncFactory) || node.text === ' '
}

學無止境,謙卑而行.
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 數字革命悄然爆發,與互聯網互相成就的“人氣王”MySQL開源資料庫,如今也正面臨突破發展瓶頸的關鍵時刻,作為記憶體中的實時數據平臺,虹科提供的Redis企業版資料庫能與MySQL輕鬆實現協同合作,帶領MYSQL跑贏數字時代! ...
  • 身處數字經濟時代,隨著大數據應用越來越廣泛,越來越多的企業和組織開始關註大數據基礎平臺的建設和運營。在認識到其的重要性之後,如何具體著手搭建或採購大數據基礎平臺成為下一步需要解決的問題。 在大數據基礎平臺中,大數據組件是非常重要的一部分,包括數據存儲、數據處理、數據分析、數據可視化等。在選擇大數據組 ...
  • 學會使用 Redis 的一個重要內容就是 Redis 的數據類型,對於開發人員而言,學會 Redis 基礎數據類型的使用即可應用到程式開發當中。 ...
  • 場景:在SQL Server資料庫的SQL優化中,我們有時候會需要找出某個視圖的依賴對象,簡單的視圖倒是很容易一眼就找出依賴對象,一旦遇到一些複雜的視圖,如果我們手動整理的話,就相當麻煩了,因為你要一個對象一個對象的捋一遍。相當的耗時耗力,其實這種機械、重覆、繁雜的事情就應該讓機器(SQL)去處理。 ...
  • 一、單表查詢 庫表student.report,有3個欄位, 姓名、 學科、 成績, 記錄如下, 根據要求完成SQL語句 | Name | Subject | Result | | | | | | 李白 | Math | 95 | | 杜甫 | English | 83 | | 李商隱 | Math ...
  • 二維碼識別技術已廣泛應用在移動支付、實用工具、電商購物、社交通訊等場景。然而,在實際生活中,二維碼容易遇到距離遠、暗光、強光、污損、模糊和大角度傾斜等複雜場景,導致識別困難,掃碼體驗差。華為HMS Core 統一掃碼服務(Scan Kit)為開發者們的APP帶來一站式掃碼解決方案,並且擁有高識別率和 ...
  • 有時候會想,如果chatGPT是人,它會是一個怎樣的人呢?下麵是我的推測過程。 首先,她應該是女人 會推測而不會計算 你問它: 3457 * 43216 = ,它回答 149261912 (這是錯的。正確結果是 149397712)。 之所以結果的 2 是對的,僅僅因為它讀了太多的文字資料以後,隱約 ...
  • SparseArray家族 SparseArray基於鍵值對存儲數據,key為int,value為object,簡單使用如下: //聲明 SparseArray<String> sparseArray= new SparseArray<>(); //增加元素,append方式 sparseArray ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...