mkdir toy-myreact
cd toy-myreact
npm init
npm install webpack webpack-cli --save-dev
npx webpack
module.exports = {
entry: {
main: './main.js',
},
};
指定一个入口文件,module.exports node的写法 配置里不做babel转化
打包成功后,输出一个dist目录,发现这个文件的内容并看不懂,想要看懂打包出来的文件怎么办呢??? 请看下一步
module.exports = {
entry: {
main: './main.js',
},
mode: "development",
optimization: {
minimize: false,
},
};
babel 把新版本的js文件翻译成老版本的js文件
npm install --save-dev babel-loader @babel/core @babel/preset-env
presets babel一系列的快捷方式
module.exports = {
entry: {
main: './main.js',
},
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
mode: "development",
optimization: {
minimize: false,
},
};
for (let i of [1, 2, 3]) {
console.log(i);
}
@babel/preset-env
是不包含jsx的执行能力的
在main.js
内 写jsx
并执行,报错
const a = <div />;
npm install @babel/plugin-transform-react-jsx --save-dev
@babel/plugin-transform-react-jsx
是专门用来处理jsx
的plugin
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-react-jsx'],
},
},
},
],
执行后 成功
直接翻译出带React
的函数名字, React.createElement
继续更改webpack配置
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: [['@babel/plugin-transform-react-jsx', {pragma: 'xixiToy.createElement'}]],
},
},
},
],
执行webpack, 发现React
函数名已经去掉了 变成了我们自己想要的名字
增加属性和子节点
const xixiToy = {
createElement,
};
/**
* @name: chelsea.jiang
* @test:
* @msg:
* @param {*} tagName 标签名
* @param {*} attributes 属性
* @param {array} children 子节点
* @return {*}
*/
function createElement(tagName, attributes, ...children) {
let e = document.createElement(tagName);
for (let attr in attributes) {
e.setAttribute(attr, attributes[attr]);
}
for (let child of children) {
e.appendChild(child);
}
return e;
}
window.a = (<div id="a" class="x">
<div></div>
</div>);
执行webpack编译之后,发现已不再报错
jsx 已具备初步的可用性
但是当文本节点的时候怎么办呢???
for (let child of children) {
if (typeof child === 'string') {
child = document.createTextNode(child);
}
e.appendChild(child);
}
window.a = (<div id="a" class="x">
<div>aaaa</div>
<div>bbb</div>
<MyComponent>cccc</MyComponent>
</div>);
MyComponent
编译后已不是带引号的标签
main.html
<body></body>
<script src="main.js"></script>
xixiToy.js
const xixiToy = {
createElement,
render,
};
class ElementWrapper {
constructor(type) {
this.root = document.createElement(type);
}
setAttribute(name, value) {
this.root.setAttribute(name, value);
}
appendChild(component) {
this.root.appendChild(component.root);
}
}
class TextWrapper {
constructor(content) {
this.root = document.createTextNode(content);
}
}
export class Component {
constructor() {
this._root = null;
this.props = Object.create(null);
this.children = [];
}
setAttribute(name, value) {
this.props[name] = value;
}
appendChild(component) {
this.children.push(component);
}
get root() {
if (!this._root) {
this._root = this.render().root;
}
return this._root;
}
}
function createElement(type, attributes, ...children) {
let e;
if (typeof type === 'string') {
e = new ElementWrapper(type);
} else {
e = new type;
}
for (let attr in attributes) {
e.setAttribute(attr, attributes[attr]);
}
for (let child of children) {
if (typeof child === 'string') {
child = new TextWrapper(child);
}
e.appendChild(child);
}
return e;
}
function render(component, parentElement) {
parentElement.appendChild(component.root);
}
export default xixiToy;
main.js
import xixiToy, { Component } from './xixiToy.js';
const { render } = xixiToy;
class MyComponent extends Component {
render() {
return (
<div>
<h1>111111</h1>
{this.children}
</div>
);
}
}
render(<div id="a" class="x">
<div>aaaa</div>
<div>bbb</div>
<MyComponent id='c'>cccc</MyComponent>
</div>, document.body);
是因为在createElement
child做处理的时候没有考虑到数组的情况
昨晚改造后,运行正常
function createElement(type, attributes, ...children) {
let e;
if (typeof type === 'string') {
e = new ElementWrapper(type);
} else {
e = new type;
}
for (let attr in attributes) {
e.setAttribute(attr, attributes[attr]);
}
const insertChildren = (children) => {
for (let child of children) {
if (typeof child === 'string') {
child = new TextWrapper(child);
}
if (typeof child === 'object' && child instanceof Array) {
insertChildren(child);
} else {
e.appendChild(child);
}
}
}
insertChildren(children);
return e;
}