你的简单不简单,你的困难真的难
公司项目进,时间周期不够,个人感觉脚手架真的是个入门直接开发的快速选择,
搭建环境
首先需要安装node环境 略
npm install -g creat-react-app//全局安装脚手架,任何地方都可以随时创建项目
create reactApp//创建一个reactApp目录 并将有所依赖以及配置文件放入
cd reactApp//进入目录
npm start//启动项目
复制代码
你已经成功启动了一个react项目。
React主要核心库
import React from 'react';
import ReactDom from 'react-dom';
ReactDom.render(
<h1>hello</h1>,
document.getElementById('root')
)
复制代码
最早的版本,react和react-dom这俩个是放在一起的,后来因为各种架构的优点,互补互惠。将react-dom给拆分出来,react相当于库的核心,其他的衍生的react库都如同女朋友一样偎在他身边。可以随时更换随时使用。
这些太low了,直接讲源码,
let objMale = <div>hello</divh1>; 等价于 React.createElement('div',null,['hello']);
js都是可以嵌套的,react当然也可以
let objFemale = <div>hello<span>juejin</span> 等价于 React.createElement('div',null,[React.createElement('span',null,['juejin'])]);
console.log(objMale);
复制代码
为什么呢,这里需要一个图来解释一下,
let obj = <div>hello</div>//这里最终是会return React.createElement('div',null,['hello']);
如果我在 组件类中 render(){
return (
<div>1</div>
<div>2</div>
)
}
并不是说这不合法,而是因为走到第一个div的时候就已经直接return 出结果,不会向下继续执行。--知识点哦
复制代码
现在开始,咱们先来了解一下最简单的render方法
刚才打印出来的objMale,你会发现在控制台中展示的是一个对象,这是react特有的对象,然后type对应h1,props对应内部文本节点
let objMale = {
type:'div',
props:{
children:['hello']
}
};
//大致是这样的一个结构,这已经成为我们可以看懂的js对象了吧。
然后开始分析代码,ReactDom.render(objMale,document.getElementById('root')),这一层render做了什么事情
客观分析,定义了一个JSX Dom元素,<div>hello</div>,render只是将他给插入到页面中
简单定义一个函数 _render 名字随便起
function _render(jsxDom,container){
//首先通过解构赋值 然后创建一个元素节点吧。
let {type,props} = jsxDom;
let newEle = document.createElement(type);//注意手法,这里就是将jsxDom,通过type为div 的转换成一个Dom元素
<!--
下一步操作 _nextRender (主要目的就是将props中的内容给添加到新创建的Dom元素中)
-->
//最终输出的就是讲创建的DOM元素插入到容器 -->
container.appendChild(newEle)
}
_render(objMale,document.getElementById('root'));
//大体来说无非就是这种操作,下一步也就是把渲染的元素加上相应的文本节点,
//可以打印一下 React.createElement('div',{id:1,className:'girl'},['hello']) 这个对象看一下props
function _nextRender(newEle,props){
//props不仅仅可能是一个对象
for ( let attr in props){
//介于react中的一些关键字不能和js中冲突,,jsx className <=> class class jsxom htmlFor <=> js for
//这里需要加一些判断
if(attr == 'children'){
//这里对应上面扩展的嵌套逻辑 我的children里面也可能是个对象吧。这时候就要用到递归(知识点哦)
props.forEach((item)=>{
//这里只有俩种可能,一种是字符串,一种是子元素(子元素依然会和父元素的jsxDom保持一致)
if(typeof item == 'string'){ //判断为字符串 直接添加
newEle.appendChild(item)
}else{ //否则就是元素 递归,,_render(当前子元素对象,上一级创建的容器)
_render(item,newEle);
}
})
}else if (attr == 'className'){
newEle.setAttribute('class',props[attr])
}else if(attr == 'className'){
newEle.setAttribute('for',props[attr])
}else{
newEle.setAttribute(attrr',props[attr])
}
}
}
let mulObj = {
type:'div',
props:{
className:'ai',
id:1,
children:['hello',{
type:'span',
props:{
className:'xi',
id:2,
children:['juejin']
}
}]
}
};
let jsxObj = <div className="ai" id="1">hello<span className="xi" id="2">juejin</span></div>
最终渲染在页面上就都是 <div class="ai" id="1">hello<span class="xi" id="2">juejin</span></div>
_render(mulObj,document.getElementById('root')); === ReactDom.render(jsxObj,document.getElementById('root'))
并不是完全相等,只是在渲染逻辑上差不多。
复制代码