前言
我在寫這篇文章的時候, 原始碼也只是看了一部分, 而且有一些部分也不是非常的明白清除。各位看官還請酌情參考。發現錯誤還請指出。
什麼是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檔案。