前言
我在写这篇文章的时候, 源码也只是看了一部分, 而且有一些部分也不是非常的明白清除。各位看官还请酌情参考。发现错误还请指出。
什么是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文件。
发表回复