preact源码分析(一)

4次阅读

共计 2211 个字符,预计需要花费 6 分钟才能阅读完成。

前言
我在写这篇文章的时候, 源码也只是看了一部分, 而且有一些部分也不是非常的明白清除。各位看官还请酌情参考。发现错误还请指出。
什么是 preact?
官方给出的定义如下 Fast 3kB React alternative with the same modern API. Components & Virtual DOM.。preact 是 react 的精简实现。废话少说, 接下来我们直接看 preact 的源码。
src/create-element.js
create-element.js 里一共定义了 5 个方法, 我们在这里先讨论其中的 3 个。其余的方法会在后序的文章中涉及。
createElement && createVNode
createElement 和 createVNode 一同实现了创建 VNode 节点的功能。createElement 一共有三个参数, type, props, children。
type 参数为创建 VNode 的类型。根据源码中 type 参数的 d.ts 的定义文件可知, type 可以为 String 类型和 Function 类型或者 Null。String 类型对应着普通的 DOM 节点, Function 类型则对应的 Preact 组件。
props 参数为 VNode 的属性, 同时对应着组件的 Props。
children 参数 VNode 的子节点, 在这里没有规定 children 参数的个数, VNode 可以拥有一组子节点。
export function createElement(type, props, children) {
// 对 props 做出容错处理, 设置 props 的默认值
if (props==null) props = {};

// 对多余的参数创建一个 children 的数组, 数组中存放着 VNode 的子节点
if (arguments.length>3) {
children = [children];
for (let i=3; i<arguments.length; i++) {
children.push(arguments[i]);
}
}

// 将 children 挂载到 props 上
if (children!=null) {
props.children = children;
}

// 如果 Function 类型的 type 存在 defaultProps 属性 (默认的 props 可以参数 React 中用法)
// 将其每一个属性挂载到 props 上
if (type!=null && type.defaultProps!=null) {
for (let i in type.defaultProps) {
if (props[i]===undefined) props[i] = type.defaultProps[i];
}
}

// 从 props 中单独取出 ref 和 key 属性
let ref = props.ref;
if (ref) delete props.ref;
let key = props.key;
if (key) delete props.key;

// 将处理后的参数交由 createVNode 函数处理
return createVNode(type, props, null, key, ref);
}

createVNode 函数更为简单, 它会创建 VNode 对象并返回它。
其中 text 参数对应中文本节点中, 文本内容。
export function createVNode(type, props, text, key, ref) {
const vnode = {
type,
props,
text,
key,
ref,
_children: null,
_dom: null,
_lastDomChild: null,
_component: null
};

if (options.vnode) options.vnode(vnode);

return vnode;
}
coerceToVNode
通过函数的名称可得知, coerceToVNode 函数会将一些非 VNode 的节点转化为 VNode 节点

export function coerceToVNode(possibleVNode) {
// boolean 类型和 null 返回 null
if (possibleVNode == null || typeof possibleVNode === ‘boolean’) {
return null;
}
// string 类型和 number 类型返回 text 的 Vnode 节点
if (typeof possibleVNode === ‘string’ || typeof possibleVNode === ‘number’) {
return createVNode(null, null, possibleVNode, null, null);
}

// 对于数组将会使用 Fragment 做一层包装
if (Array.isArray(possibleVNode)) {
return createElement(Fragment, null, possibleVNode);
}

// 如果本身属于 Vnode 节点将会返回一个 clone 的 Vnode 节点
if (possibleVNode._dom!=null) {
return createVNode(possibleVNode.type, possibleVNode.props, possibleVNode.text, possibleVNode.key, null);
}

return possibleVNode;
}
结语
截止目前据我们所知的 VNode 节点如下。在下一篇文章中我们将学习 component.js 文件。

正文完
 0