>[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 -- 案例
- 待续