仿写一个我们自己的mini_react(第一章)
前言
我觉得大家也有过一种大胆的想法想写一个前端框架吧,这些本来应该是是我在梦里边的行为,但是看了一个大哥推荐的一篇文章后,我觉得我也可以,所以我们一起试着写一个吧
大哥的csdn地址:https://lpyexplore.blog.youkuaiyun.com/
文章的地址:https://pomb.us/build-your-own-react/
1.首先我们先了解一下react的渲染过程
其实jsx是通过一种打包方式打包成真正的js代码
const element = <h1 title="foo">Hello</h1>
const container = document.getElementById("root")
ReactDOM.render(element, container)
- 首先有一个组件,要有一个根节点root,通过render函数将组件渲染到根节点上
2.是通过什么方式将上文中的element组件转化为一个js文件呢?
举一个例子:
import React from 'react'
function App () {
return (
<div>
你吃饭了嘛
</div>
)
}
这个就是我们常常写的react的代码,现在有一个问题:我们没有用到react的方法为什么还要引用呢?
答:虽然表面上没有用但是在jsx打包时候会运行 React.createElement方法将html元素转化为一个对象
例子:
const element = <h1 title="foo">Hello</h1>
const element = React.createElement(
"h1",
{ title: "foo" },
"Hello"
)
现在我们知道了一个元素会变成这样的对象额。。。那就好办了我们来写一个实现他的简单方法
3.将对象那形式的元素变成真正的dom元素
<body>
<div id="root"></div>
<script>
// 第一步 获取根节点
let container = document.querySelector('#root')
// 第二步手动创建虚拟的元素对象
const element = {
type: "h1",
props: {
title: "foo",
children: "Hello"
}
}
// 第三步由虚拟的元素对象创建一个元素
const node = document.createElement(element.type)
node['title'] = element.props.title
const text = document.createTextNode('')
text['nodeValue'] = element.props.children
node.appendChild(text)
container.appendChild(node)
</script>
</body>
运行结果:
写到这其实我就挺激动了,一直不管学vue还是react都是应用层面,这些js的底层代码写着还真有意思
试着实现React.createElement方法
前言:我想想仿写一个方法,首先要知道他实现了什么功能
功能需求:我就想以传递函数参数的形式让createElement方法帮我创建一个虚拟元素对象
// 第一步 获取根节点
let container = document.querySelector('#root')
// 实现方法:React.createELement
// type: 元素的标签,props:元素的标签,...children:子元素
function createELement (type, props, ...children) {
return {
type,
props: {
...props,
children
}
}
}
这样我们就实现了通过函数传参数就可以形成虚拟的元素对象
但是现在又有一个问题:如果我的子元素他仅仅是一个文本我想更好的管理他应该怎么做?
答:对上述代码进行优化
// 第一步 获取根节点
let container = document.querySelector('#root')
// 实现方法:React.createELement
// 判断传进的children参数是否为一个元素
function createELement (type, props, ...children) {
return {
type,
props: {
...props,
children: children.map(child => {
return typeof child === 'object'
? child
: createELement(child)
})
}
}
}
// 给纯文本的子节点创建一个type: 'TEXT_ELEMENT'方便管理
function createTextElement (text) {
return {
type: 'TEXT_ELEMENT',
props: {
nodeText: text,
children: []
}
}
}
现在舒服的一批,同时呢又显得高级
提示!:
// 为了像react那样统一管理方法我们船舰一个对象来管理我们mini_react...帅就完了
const mini_react = {
createELement
}