- 搭建JSX环境, webpack.config.js
- webpack4.x
- yarn add babel-loader @babel/core @babel/preset-env —dev
module.exports = {
mode: 'development',
entry: {
main: './src/main.js'
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}
- 实现JSX要求的create
- yarn add @babel/plugin-transform-react-jsx —dev
添加配置plugins: ['@babel/plugin-transform-react-jsx']
后会自动解析<div></div>
标签为React.createElement("div", null)
修改配置 plugins: [['@babel/plugin-transform-react-jsx', {pragma: 'createElement'}]]
, 编译后变为createElement("div", null)
<div></div>
createElement("div", null, "")
<div>hello</div>
createElement("div", null, "hello");
<div id="app" class="head"></div>
createElement("div", {
id: "app",
"class": "head"
});
function createElement(tagName) {
return document.createElement(tagName)
}
- 第一个参数, tagName
- 第二个参数,attributes, null、{}
- 第三个参数, ‘text’文本, []子标签、文本
- 基本概念:attribute、children
```
hellocreateElement(“div”, { id: “app”, “class”: “head” }, “hello”)
function createElement(tagName, attributes, text) { let element = document.createElement(tagName) for (const key in attributes) { element.setAttribute(key, attributes[key]) } if (text) { let node = document.createTextNode(text) element.appendChild(node) } return element }
处理子标签
function createElement(tagName, attributes, …rest) { let element = document.createElement(tagName) if (typeof attributes === ‘object’ && attributes instanceof Object) { // setAttribute } for(let child of rest) { if (typeof child == ‘string’) { child = document.createTextNode(child) } element.appendChild(child) } return element }
4. 处理自定义组件
class Hello extends Component { render () { return
借助root属性。toy-react.js
function render(component, parentElement) { parentElement.appendChild(component.root) } class Component { // 处理自定义组件 constructor() { this.props = Object.create(null); this.children = []; this._root = null; } // setAttribute(name, value) appendChild(component) { this.children.push(component) } get root() { if (!this._root) this._root = this.render().root return this._root } } class ElementWrapper { // 包裹标签 constructor(type) { this.root = document.createElement(type) } // setAttribute(name, value) appendChild(component) { this.root.appendChild(component.root) } } class TextWrapper { constructor(content) { this.root = document.createTextNode(content) } } // 循环处理子标签 let insertChildren = (children) => { for(const child of children) { if (typeof child == ‘string’) { child = new TextWrapper(child) } if ((typeof child == ‘object’) && (child instanceof Array)) { insertChildren(child) } else { element.appendChild(child) } } } insertChildren(rest) ```