ToB企服应用市场:ToB评测及商务社交产业平台
标题:
vue3源码(六)渲染原理-runtime-core
[打印本页]
作者:
杀鸡焉用牛刀
时间:
2024-7-11 10:44
标题:
vue3源码(六)渲染原理-runtime-core
1.依赖关系
runtime-dom 依赖于runtime-core,runtime-core 依赖于reactivity和shared
runtime-core提供跨平台的渲染方法createRenderer,用户可以自己转达节点渲染的渲染方法renderOptions,本身不关心用户使用什么API
runtime-dom提供了为浏览器而生的渲染方法render,render方法调用runtime-core的createRenderer方法转达的renderOptions 是runtime-dom封装好的一系列关于渲染浏览器dom节点的操纵
const renderOptions = Object.assign({ patchProp }, nodeOps);
export const render = (vnode,container)=>{
return createRenderer(renderOptions).render(vnode,container)
}
复制代码
2.init
2.1 package init
runtime-core/package.json
{
"name": "@vue/runtime-core",
"version": "1.0.0",
"main": "index.js",
"module": "dist/runtime-core.esm-bundler.js",
"unpkg": "dist/runtime-core.global.js",
"buildOptions": {
"name": "RuntimeCore",
"formats": [
"esm-bundler",
"esm-browser",
"cjs",
"global"
]
},
"dependencies": {
"@vue/reactivity": "^3.4.30",
"@vue/shared": "*"
}
}
复制代码
2.2 调整runtime-dom/index依赖
import { nodeOps } from "./nodeOps";
import patchProp from "./patchProp";
import {createRenderer} from '@vue/runtime-core'
const renderOptions = Object.assign({ patchProp }, nodeOps);
export { renderOptions };
// 如果我们采用的是runtime-dom中的render方法,我们不需要传递renderOptions,因为会把runtime-dom 这一层的dom处理方法传递进去,主要为浏览器而生的
// 如果我们用的是runtime-core 中的createRenderer,需要用户自己传递renderOptions 并不关心采用什么api
// runtime-dom 是内置的dom api 会去调用createRenderer,传入渲染选项,返回的渲染器有一个render方法
// 采用dom api 进行渲染
export const render = (vnode,container)=>{
return createRenderer(renderOptions).render(vnode,container)
}
export * from "@vue/runtime-core"
复制代码
3.实现
3.1 init
createRenderer接受一个参数dom渲染相关配置,提供一个render方法,参数为虚拟节点和真实的dom元素
export function createRenderer(renderOptions) {
const {
insert: hostInsert,
remove: hostRemove,
patchProp: hostPatchProp,
createElement: hostCreateElement,
createText: hostCreateText,
setText: hostSetText,
setElementText: hostSetElementText,
parentNode: hostParentNode,
nextSibling: hostNextSibling,
} = renderOptions;
const render = (vnode, container) => {
// 将虚拟节点变成真实节点进行渲染
};
return {
render,
};
}
复制代码
3.2 render实现
const mountElement = (vnode, container) => {
console.log(vnode);
const { type, children, props } = vnode;
let el = hostCreateElement(type);
if (props) {
for (let key in props) {
hostPatchProp(el, key, null, props[key]);
}
}
hostSetElementText(el, children);
hostInsert(el, container);
};
const patch = (n1, n2, container) => {
if (n1 == n2) {
return;
}
if (n1 == null) {
mountElement(n2, container);
}
};
// core 中不关心如何渲染
const render = (vnode, container) => {
// 将虚拟节点变成真实节点进行渲染
patch(container._vnode || null, vnode, container);
container._vnode = vnode;
};
复制代码
vnode如图:
const ele1 = h(
"h1",
{ style: { color: "red" }},
"hello world"
);
const ele2 = h(
"h1",
{ style: { color: "green" } },
"hello world"
);
render(ele1, document.getElementById("app"));
setTimeout(()=>{
render(ele2, document.getElementById("app"));
},3000)
复制代码
此时可以实现底子渲染,由于我们知道节点children是文本,可以直接使用文本进行渲染,那如果dom内里又嵌套一个dom呢?
3.3 shapeFlag
为了能够判断子节点的类型,界说一个枚举
export const enum ShapeFlags { // vue3提供的形状标识
ELEMENT = 1,
FUNCTIONAL_COMPONENT = 1 << 1,
STATEFUL_COMPONENT = 1 << 2,
TEXT_CHILDREN = 1 << 3,
ARRAY_CHILDREN = 1 << 4,
SLOTS_CHILDREN = 1 << 5,
TELEPORT = 1 << 6,
SUSPENSE = 1 << 7,
COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8,
COMPONENT_KEPT_ALIVE = 1 << 9,
COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
}
复制代码
比如const ele1 = h("h1", { style: { color: "red" } }, "hello world");是节点和文本的组合,节点为1,文本为8,接纳
或运算,得出节点类型数据
9,可以看到上图中节点的shapeFlag为9,
接纳&运算得出节点具体类型
8&9=1000&1001=1000>0 则证明包含这个类型
const mountChildren = (children, container) => {
for(let i=0;i<children.length;i++) {
// 数组可能为字符串而不是节点
patch(null, children[i], container)
}
};
const { type, children, props, shapeFlag } = vnode;
if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
hostSetElementText(el, children);
} else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
mountChildren(children, el);
}
复制代码
此处判断了TEXT_CHILDREN是文本,ARRAY_CHILDREN是数组
const ele3 = h("h1", { style: { color: "red" } }, [
h("p", "hello"),
h("p", "world"),
]);
复制代码
可以精确渲染
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4