【Vue原理】Render
寫文章不容易,點個讚唄兄弟
專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳情,讓我們一起學習吧
研究基於 Vue版本 【2.5.17】
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧
【Vue原理】Render - 原始碼版 之 靜態 Render
上一篇我們講了 render 函式,而 Vue 為了更新時速度快一些,加入了一個 staticRender
沒錯,就是 靜態 render,看過前面文章的人,應該知道什麼是 靜態 render
靜態 render 就是用於渲染哪些不會變化的節點
大家可以先看看,Vue 是怎麼判斷某個節點是否是靜態節點
好,下面開始我們的正文,想了想,我們還是以幾個問題開始吧
1、靜態 render 是什麼樣子的
2、靜態 render 是怎麼生成和 儲存
3、靜態 render 怎麼執行
什麼是 靜態Render
靜態 render 其實跟 render 是一樣的,都是執行得到 Vnode
只是靜態 render,沒有繫結動態資料而已,也就是說不會變化
比如說,一個簡單 render 是這樣的
綁定了動態資料,需要從例項去獲取
_c('div',[_v(_s(aa))])
而靜態 render 是這樣的
沒有動態資料,這個靜態render 的執行結果是永遠不會變的
_c('div',[_c('span',[_v("1")])])
生成儲存靜態Render
靜態 render 是在 generate 階段生成的,生成的方式和 render 是一樣的
比如在一個模板中,有很多個靜態 根節點,像這樣
首先,Vue 會在遍歷模板的時候,發現 span 和 strong 本身以及其子節點都是靜態的
那麼就會給 span 和 strong 節點本身設定一個屬性 staticRoot,表示他們是靜態根節點
然後這兩個靜態根節點就會生成自己專屬的 靜態 render
如何標記靜態根節點的具體可以看 Compile 之 optimize 標記靜態節點
怎麼把靜態根節點生成 render 的可以看 Compile 之 generate 節點拼接 中 genStatic 的部分
如果你有一直看我的Vue 筆記的話,你應該這裡是會有點印象的
之後
靜態 render 生成之後是需要儲存的,那麼儲存在哪裡呢?
儲存在一個數組中,名叫 staticRenderFns,就是直接push 進去
當然了,此時的 push 進去的 靜態 render 還是字串,並沒有變成函式
以上面的模板為例,這裡的 staticRenderFns 就是這樣,包含了兩個字串
staticRenderFns = [
"_c('span',[_c('b',[_v("1")])])",
"_c('strong',[_c('b',[_v("1")])])"
]
但是在後面會逐個遍歷變成可執行的函式
staticRenderFns = staticRenderFns.map(code => {
return new Function(code)
});
那麼 這個 staticRenderFns 又是什麼啊?
每個 Vue 例項都有一個獨立的 staticRenderFns,用來儲存例項本身的靜態 render
staticRenderFns 的位置是
vm.$options.staticRenderFns
執行靜態Render
靜態 render 需要配合 render 使用,怎麼說
看個例子
這個模板的 render 函式是
_c('div',[
_m(0),
_v(_s(a),
_m(1)
])
_m(0) , _m(1) 就是執行的就是 靜態 render 函式,然後返回 Vnode
於是 render 也可以完成 vnode 樹的構建了
那麼 _m 是什麼呢?
在 Vue 初始化時,給Vue的原型便註冊了這個函式,也就是說每個例項都繼承到 _m
function installRenderHelpers(target) {
target._m = renderStatic;
}
installRenderHelpers(Vue.prototype);
再來看 renderStatic
function renderStatic(index) {
var cached = this._staticTrees || (this._staticTrees = []);
var tree = cached[index];
// 如果快取存在,就直接返回
if (tree) return tree
// 這裡是執行 render 的地方
tree = cached[index] =
this.$options.staticRenderFns[index].call(
this, null, this
);
// 只是標記靜態 和 節點id 而已
markStatic(tree, "__static__" + index, false);
return tree
}
這個函式做的事情可以分為幾件
1、執行靜態render
2、快取靜態render 結果
3、標記 靜態 render 執行得到的 Vnode
我們來一個個說
1 執行靜態render
上面我們說過了,靜態render 儲存在 陣列 staticRenderFns
所以這個函式接收一個索引值,表示要執行陣列內哪個靜態render
取出靜態render 後,執行並繫結 Vue 例項為上下文物件
然後得到 Vnode
2 快取靜態render 結果
這一步就是要把上一步得到的 Vnode 快取起來
那麼快取在哪裡呢?
_staticTrees
這是一個數組,每個例項都會有一個獨立的 _staticTrees,用來存在自身的靜態 render 執行得到的 Vnode
看一下上個模板中例項儲存的 _staticTrees
3 標記 靜態 render 執行得到的 Vnode
我們已經執行靜態render得到了 Vnode,這一步目的是標記
標記什麼呢
1、新增標誌位 isStatic
2、新增 Vnode 唯一id
renderStatic 中我們看到標記的時候,呼叫了 markStatic 方法,現在就來看看
function markStatic(
tree, key
) {
if (Array.isArray(tree)) {
for (var i = 0; i < tree.length; i++) {
if ( tree[i] && typeof tree[i] !== 'string') {
var node = tree[i]
node.isStatic = true;
node.key = key + "_" + i;
}
}
}
else {
tree.isStatic = true;
tree.key = key
}
}
為什麼新增標誌位 isStatic?
前面我們新增的所有靜態標誌位都是針對 模板生成的 ast
這裡我們是給 Vnode 新增 isStatic,這才能完成Vue的目的
Vue 目的就是效能優化,在頁面改變時,能儘量少的更新節點
於是在頁面變化時,當 Vue 檢測到該 Vnode.isStatic = true,便不會比較這部分內容
從而減少比對時間
Vnode 唯一id
每個靜態根Vnode 都會存在的一個屬性
我也沒想到 靜態Vnode 的 key 有什麼作用,畢竟不需要比較,也許是易於區分??
最後
靜態 render 我們就講完了,是不是很簡單,在沒看原始碼之前,我以為很難
現在看完,發現也簡單的,不過我也是看了幾個月的。。。。
鑑於本人能力有限,難免會有疏漏錯誤的地方,請大家多多包涵,如果有任何描述不當的地方,歡迎後臺聯絡本人,有重謝
相關推薦
【Vue原理】Render
寫文章不容易,點個讚唄兄弟 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳
【Vue原理】Watch
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Watch - 原始碼版 今天繼續探索 Watch 原始碼,廢話不多說了 帶著我的幾個疑問開始 1、什麼時候初始化 2、怎麼確定監聽哪些值 3、深度監聽怎麼回事 4、怎麼觸發我的函式 這些問題的答案會摻
【Vue原理】Props
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Props - 原始碼版 今天記錄 Props 原始碼流程,哎,這東西,就算是研究過了,也真是會隨著時間慢慢忘記的。 幸好我做了詳細的文章,忘記了什麼的,回憶起來必然是很快的。 好的,回到正題,Props 請你
【Vue原理】Mixins
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Mixins - 原始碼版 今天探索的是 mixins 的原始碼,mixins 根據不同的選項型別會做不同的處理 篇幅會有些長,你知道的,有很多種選項型別的嘛,但不是很難。只是涉及原始碼難免會有些煩, 不過這篇文
【Vue原理】依賴更新
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】依賴更新 - 原始碼版 如果對依賴收集完全沒有概念的同學,可以先看我這篇白話版 響應式原理 - 白話版 我們已經講過了 依賴收集 【Vue原理】依賴收集 - 原始碼版之基本資料型別 【Vue
【Vue原理】VNode
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】VNode - 原始碼版 今天就來探索 VNode 的原始碼,VNode 是 Vue2 渲染機制中很重要的一部分,是深入Vue 必須瞭解的部分 我們以4個問題來開始我們的探索 1、vnode 是什麼及其作用
【Vue原理】Event
如果你覺得排版難看,請點選 下面連結 或者 拉到 下面關注公眾號也可以吧 【Vue原理】Event - 原始碼版 之 自定義事件 Vue 的自定義事件很簡單,就是使用 觀察者模式 進行事件的監聽和分發 Vue 封裝的這個觀察者模式,可以說是很完善了,這個可以獨立抽取出來的在其他專案中使用的程式碼,
【Vue原理】NextTick
寫文章不容易,點個讚唄兄弟 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,白話版助於理解工作原理,原始碼版助於瞭解內部詳
【Vue原理】Diff
寫文章不容易,點個讚唄兄弟 <br> <br> 專注 Vue 原始碼分享,文章分為白話版和 原始碼版,
【vue.js】入門
emp 寫到 logs 組件 images href one mooc 渲染 慕課網視頻學習筆記:http://www.imooc.com/learn/694 1.將html、js、css寫到一個後綴名.vue的文件中,區分這三種類型是通過<template>、
【底層原理】四位計算機的原理及其實現
一點 led燈 waiting lean div rm2 src and nvt 你是否想過,計算機為什麽會加減乘除?或者更直接一點,計算機的原理到底是什麽? Waitingforfriday有一篇詳細的教程,講解了如何自己動手,制作一臺四位計算機。從中可以看到,二進制、數
【計算機原理】程序執行過程
進程 cnblogs div 空間 時間片 chat 內存管理 tro alt 本章主要介紹程序執行過程中操作系統、CPU都幹了什麽 運行前 程序在運行前,只是在硬盤上待著,此時就是一堆二進制代碼而已,沒有任何作用。 程序只有進入了內存才能運行,但是要進入內存,則需要服從操
【計算機原理】CPU部分.md
工作 信號 通過 臃腫 流水線 處理 2.6 操作 ade 本文由CPU阿甘改編而得,主要講的是系統啟動和程序執行時CPU做的工作。 CPU的構成 中央處理器(CPU,Central Processing Unit)由運算器、控制器、Cache等。 控制器:主要是對指令進
Django 【第二篇】render、redirect和方向生產URL
規則 app nbsp 場景 http 設計 配置 建立 get 一、知識點回顧 1、MTV模型 model:模型,和數據庫相關的 template:模板,存放html文件,模板語法(目的是將變量如何巧妙的嵌入到HTML頁面中)。 views:視圖函數 另加u
【組成原理】第一章 計算機系統概述
表示 運算 傳遞 intro 指令 掌握 周期 style 主存 重點掌握:MAR和MDR的含義,主存容量大小、CPU執行時間的計算,性能指標CPI、MIPS、主頻等等。 1. 存儲單元:CPU訪問存儲器的基本單位,每個單元有一個地址。通常是字節大小的整數倍。 2. CPU
【編譯原理】c++實現自下而上語法分析器
不可 acm times style size PC -i 表達式 鏈接 寫在前面:本博客為本人原創,嚴禁任何形式的轉載!本博客只允許放在博客園(.cnblogs.com),如果您在其他網站看到這篇博文,請通過下面這個唯一的合法鏈接轉到原文! 本博客全網唯一合法URL:ht
【計數原理】【UVA11538】 Chess Queen
put typename return col nbsp 題意 putchar cst putc 傳送門 Description 給你一個n*m的棋盤,在棋盤上放置一黑一白兩個皇後,求兩個皇後能夠互相攻擊的方案個數 Input 多組數據,每組數據包括:
MongoDB 復制集 第 二 部 之【選舉原理】
command primary red and 優先權 mongo mongodb 主機 set 目錄: 1·復制與選舉的原理與驗證2·oplog 日誌調整3·配置復制集的優先級4·部署認證的復制5·總結 復制與選舉的原理: 上一篇文章搭建了多臺實例,部署成復制集,
Memcached 主主復制 + Keepalived 高可用架構【附上原理】
ima pki nag ali event 主服務器 figure tel outer 目錄: 1·Memcached 主主復制概念2·Memcached 高可用的實現3·案例部署4·總結 Memcached 主主復制概念 (1)主主復制概念: Memcached
【Windows原理】非同步IO-_APC(非同步過程呼叫)
// 同步IO的缺點是, 在讀寫檔案時, 如果檔案太大, 或者讀寫的時間太長, 就會在讀寫函式中 // 阻塞住. // 非同步IO解決了這個問題, 非同步IO讀寫檔案時, 檔案再大也不會阻塞住 // 但是非同步IO要完成這樣的特性是有一點付出的 // 非同步讀寫檔案後, 需要通過一些方式