>[success] # Snabbdom -- h函數
1. `h` 用來來創建 `vnodes`,這個函數需要三個參數
* 第一個參數,一個字符串類型的 標簽或選擇器 參數類型 `string`
* 第二個參數,一個數據對象(可選)參數類型 `VNodeData`
* 第三個參數,一個子節點數組或字符串(可選)參數類型`VNodeChildren`
**現在想生成dom**
`<div id='container' class='cls' style='color:red'>我是例子<span>例子<span></div>`
* 通過`h` 函數生成寫法(這個例子中第二個參數類型就是VNodeData,第三個參數類型VNodeChildren)
~~~
let vnode = h('div', {
style: {
backgroundColor: 'red'
},
on: {
click: eventHandler
}
}, [
'我是文本'
h('h1', 'Hello Snabbdom'),
h('p', '這是p標簽')
])
~~~
2. 具體 `h` 函數定義 `snabbdom` 通過 用 **ts 重載**說明了幾種使用情況
~~~
export function h(sel: string): VNode; // (1)
export function h(sel: string, data: VNodeData): VNode; // (2)
export function h(sel: string, children: VNodeChildren): VNode; // (3)
export function h(sel: string, data: VNodeData, children: VNodeChildren): VNode; // (4)
export function h(sel: any, b?: any, c?: any): VNode {.....}
~~~
上面情依次表示
* **只創建了dom節點(1)**,節點中沒有任何內容
`<div id="app"></div>`
~~~
import { init, eventListenersModule, styleModule, h } from 'snabbdom'
// 2. 注冊模塊
let patch = init([styleModule, eventListenersModule])
// 3. 使用 h() 函數的第二個參數傳入模塊需要的數據(對象)
let vnode = h('div#app')
let app = document.querySelector('#app')
patch(app, vnode)
~~~
* **創建了dom節點,并創建dom中元素(2)**,節點中沒有任何內容
`<div id="app" class="name" style="background-color: red;"></div>
`
~~~
import {
init,
eventListenersModule,
classModule,
styleModule,
h,
} from 'snabbdom'
// 2. 注冊模塊
let patch = init([styleModule, eventListenersModule, classModule])
// 3. 使用 h() 函數的第二個參數傳入模塊需要的數據(對象)
let vnode = h('div#app', {
style: {
backgroundColor: 'red',
},
class: {
name: true,
age: false,
},
})
let app = document.querySelector('#app')
patch(app, vnode)
~~~
* **創建dom并且創建里面的內容(3)** `VNodeChildren` 類型作為`VNodeChildElement | VNodeChildElement[]`其中 `VNodeChildren`類型定義:
~~~
export type VNodeChildElement = VNode | string | number | undefined | null;
export type ArrayOrElement<T> = T | T[];
export type VNodeChildren = ArrayOrElement<VNodeChildElement>
~~~
`<div id="app"><span>子節點</span>12334</div>`
~~~
import { init, eventListenersModule, styleModule, h } from 'snabbdom'
// 2. 注冊模塊
let patch = init([styleModule, eventListenersModule])
// 3. 使用 h() 函數的第二個參數傳入模塊需要的數據(對象)
let vnode = h('div#app', [h('span', '子節點'), 1, 23, 34])
let app = document.querySelector('#app')
patch(app, vnode)
~~~
* **創建一個有屬性有內容的節點(4)** 演示省略
>[danger] ##### 源碼部分
通過 h 函數將傳入參數 轉換成了 `VNode(虛擬節點)`
~~~
export function h(sel: any, b ? : any, c ? : any): VNode {
var data: VNodeData = {},
children: any, text: any, i: number;
// 處理參數,實現重載的機制
if (c !== undefined) {
// 處理三個參數的情況
// sel、data、children/text
if (b !== null) {
data = b;
}
if (is.array(c)) {
children = c;
}
// 如果 c 是字符串或者數字
else if (is.primitive(c)) {
text = c;
}
// 如果 c 是 VNode
else if (c && c.sel) {
children = [c];
}
} else if (b !== undefined && b !== null) {
// 處理兩個參數的情況
// 如果 b 是數組
if (is.array(b)) {
children = b;
}
// 如果 b 是字符串或者數字
else if (is.primitive(b)) {
text = b;
}
// 如果 b 是 VNode
else if (b && b.sel) {
children = [b];
} else {
data = b;
}
}
if (children !== undefined) {
// 處理 children 中的原始值(string/number)
for (i = 0; i < children.length; ++i) {
// 如果 child 是 string/number,創建文本節點
// 因為你的文本節點是'我是文本'類似這種在數組中不是一個h函數的
// 表現形式因此需要被轉換成一個h函數的表現形式
if (is.primitive(children[i])) children[i] = vnode(undefined,
undefined, undefined, children[i], undefined);
}
}
if (
sel[0] === 's' && sel[1] === 'v' && sel[2] === 'g' &&
(sel.length === 3 || sel[3] === '.' || sel[3] === '#')
) {
// 如果是 svg,添加命名空間
addNS(data, children, sel);
}
// 返回 VNode
return vnode(sel, data, children, text, undefined);
};
// 導出模塊
export default h;
~~~
- 工程化 -- Node
- vscode -- 插件
- vscode -- 代碼片段
- 前端學會調試
- 谷歌瀏覽器調試技巧
- 權限驗證
- 包管理工具 -- npm
- 常見的 npm ci 指令
- npm -- npm install安裝包
- npm -- package.json
- npm -- 查看包版本信息
- npm - package-lock.json
- npm -- node_modules 層級
- npm -- 依賴包規則
- npm -- install 安裝流程
- npx
- npm -- 發布自己的包
- 包管理工具 -- pnpm
- 模擬數據 -- Mock
- 頁面渲染
- 渲染分析
- core.js && babel
- core.js -- 到底是什么
- 編譯器那些術語
- 詞法解析 -- tokenize
- 語法解析 -- ast
- 遍歷節點 -- traverser
- 轉換階段、生成階段略
- babel
- babel -- 初步上手之了解
- babel -- 初步上手之各種配置(preset-env)
- babel -- 初步上手之各種配置@babel/helpers
- babel -- 初步上手之各種配置@babel/runtime
- babel -- 初步上手之各種配置@babel/plugin-transform-runtime
- babel -- 初步上手之各種配置(babel-polyfills )(未來)
- babel -- 初步上手之各種配置 polyfill-service
- babel -- 初步上手之各種配置(@babel/polyfill )(過去式)
- babel -- 總結
- 各種工具
- 前端 -- 工程化
- 了解 -- Yeoman
- 使用 -- Yeoman
- 了解 -- Plop
- node cli -- 開發自己的腳手架工具
- 自動化構建工具
- Gulp
- 模塊化打包工具為什么出現
- 模塊化打包工具(新) -- webpack
- 簡單使用 -- webpack
- 了解配置 -- webpack.config.js
- webpack -- loader 淺解
- loader -- 配置css模塊解析
- loader -- 圖片和字體(4.x)
- loader -- 圖片和字體(5.x)
- loader -- 圖片優化loader
- loader -- 配置解析js/ts
- webpack -- plugins 淺解
- eslit
- plugins -- CleanWebpackPlugin(4.x)
- plugins -- CleanWebpackPlugin(5.x)
- plugin -- HtmlWebpackPlugin
- plugin -- DefinePlugin 注入全局成員
- webapck -- 模塊解析配置
- webpack -- 文件指紋了解
- webpack -- 開發環境運行構建
- webpack -- 項目環境劃分
- 模塊化打包工具 -- webpack
- webpack -- 打包文件是個啥
- webpack -- 基礎配置項用法
- webpack4.x系列學習
- webpack -- 常見loader加載器
- webpack -- 移動端px轉rem處理
- 開發一個自己loader
- webpack -- plugin插件
- webpack -- 文件指紋
- webpack -- 壓縮css和html構建
- webpack -- 清里構建包
- webpack -- 復制靜態文件
- webpack -- 自定義插件
- wepack -- 關于靜態資源內聯
- webpack -- source map 對照包
- webpack -- 環境劃分構建
- webpack -- 項目構建控制臺輸出
- webpack -- 項目分析
- webpack -- 編譯提速優護體積
- 提速 -- 編譯階段
- webpack -- 項目優化
- webpack -- DefinePlugin 注入全局成員
- webpack -- 代碼分割
- webpack -- 頁面資源提取
- webpack -- import按需引入
- webpack -- 搖樹
- webpack -- 多頁面打包
- webpack -- eslint
- webpack -- srr打包后續看
- webpack -- 構建一個自己的配置后續看
- webpack -- 打包組件和基礎庫
- webpack -- 源碼
- webpack -- 啟動都做了什么
- webpack -- cli做了什么
- webpack - 5
- 模塊化打包工具 -- Rollup
- 工程化搭建代碼規范
- 規范化標準--Eslint
- eslint -- 擴展配置
- eslint -- 指令
- eslint -- vscode
- eslint -- 原理
- Prettier -- 格式化代碼工具
- EditorConfig -- 編輯器編碼風格
- 檢查提交代碼是否符合檢查配置
- 整體流程總結
- 微前端
- single-spa
- 簡單上手 -- single-spa
- 快速理解systemjs
- single-sap 不使用systemjs
- monorepo -- 工程
- Vue -- 響應式了解
- Vue2.x -- 源碼分析
- 發布訂閱和觀察者模式
- 簡單 -- 了解響應式模型(一)
- 簡單 -- 了解響應式模型(二)
- 簡單 --了解虛擬DOM(一)
- 簡單 --了解虛擬DOM(二)
- 簡單 --了解diff算法
- 簡單 --了解nextick
- Snabbdom -- 理解虛擬dom和diff算法
- Snabbdom -- h函數
- Snabbdom - Vnode 函數
- Snabbdom -- init 函數
- Snabbdom -- patch 函數
- 手寫 -- 虛擬dom渲染
- Vue -- minVue
- vue3.x -- 源碼分析
- 分析 -- reactivity
- 好文
- grpc -- 瀏覽器使用gRPC
- grcp-web -- 案例
- 待續