公司最近要做react的项目,所以,小白继续学习中……整理笔记如下……
React 和 Vue的对比
模块化:从代码的角度分析,把可复用的代码,抽离为单个的模块,便于项目的维护和开发。
组件化:从ui的角度分析,把可复用的ui抽离为单独的组件,便于项目的维护和开发。
vue的组件化
通过.vue文件,来创建对应的组件
- template 结构
- script 行为
- style 样式
react的组件化
没有像vue这样的组件模板文件。一切都是以js来表现。
虚拟DOM的概念
DOM -- Document Object Model
浏览器中的概念,用js对象来表示页面上的元素
虚拟DOM -- Virtual Document Object Model
框架中的概念,程序员用js对象来模拟页面上的DOM和DOM嵌套
目的:实现页面元素的高效更新
虚拟DOM为什么能高效更新?举个栗子……

需求:
点击日期和姓名旁的小三角,实现对应表格的数据排序
过程分析:
- 数据来源 -- 点击小三角,从数据库查询数据
- 数据存放 -- 查询到的数据,存放在浏览器的内存中,以对象数组的形式来表示
- 数据渲染 -- 循环拼接字符串 或 模板引擎
问题: 每次拿到数据后,内存中的对象数组是新的,页面总是要重新渲染。性能没有做到最优。
解决思路: 按需渲染。
如何实现按需渲染?
先了解网页的呈现过程:
- 浏览器请求服务器,获得HTML
- 浏览器在内存中,解析DOM结构,并在浏览器内存中,渲染出DOM树
- 浏览器把DOM树,呈现到页面上
因此,拿到内存中的新旧两棵DOM树,进行对比,就能得到需要按需更新的DOM元素
but,如何拿到新旧两棵DOM树呢?
浏览器中,没有直接提供获取DOM树的API,因此,只能程序员手动模拟DOM树
模拟对象:
<div id="ergou" title="fxd">
二狗有多哈
<p>非常哈</p>
</div>
模拟结果:
var div = {
tagName: 'div',
attrs: {
id: 'ergou',
title: 'fxd'
},
childrens: [
'二狗有多哈',
{
tagName: 'p',
childrens: [
'非常哈'
]
}
]
}
对比新旧模拟结果的js对象,即可实现页面元素的高效更新。这就是react中虚拟DOM的概念。
如何进行对比呢?
diff算法
diff -- different的缩写
- tree diff
新旧两棵DOM树,逐层对比的过程 - component diff
对比前后,如组件类型相同,暂时认定不需要更新
对比前后,组件类型不同,则移除旧组件,创建新组件,并追加到页面上 - element diff
如果是component diff中的情况1,则进行元素级别的对比
正式开始react的学习,准备工作,安装
webpack webpack-cli webpack-dev-server html-webpack-plugin
,搭建基本的项目结构,在package.json
中配置项目启动的具体参数,在webpack.config.js
中对项目插件进行配置
在项目中使用react
之前搭建的文件结构如下

- 先导入包,包的作用在入口文件中讲
import React from 'react'
import ReactDOM from 'react-dom'
- 在
index.html
文件中,挖坑,方便放入react创建的虚拟DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index</title>
<!-- <script src="./main.js"></script> -->
</head>
<body>
<h1>这是首页</h1>
<div id="app"></div> // 这里是坑
</body>
</html>
- 在入口文件
index.js
中写入
// 入口文件
import React from 'react' // 创建组件、虚拟DOM元素、生命周期
import ReactDOM from 'react-dom' // 把创建好的 组件 和 虚拟DOM 放到页面上展示
// 创建虚拟DOM元素
// 目标 <h1 title="啊,五环" id="myh1">你比四环多一环</h1>
// 参数1 - 字符串类型的参数,对应标签名
// 参数2 - 对象类型的参数,对应属性节点
// 参数3 - 子节点
// 参数4 - 关联的子元素
const myh1 = React.createElement(
'h1',
{
title: '啊,五环',
id: 'myh1'
},
'你比四环多一环'
)
const mydiv = React.createElement(
'div',
null,
'这是一个div',
myh1
)
// 渲染虚拟DOM元素
// 参数1 - 要渲染的虚拟DOM对象
// 参数2 - 指定容器,需要放容器的DOM对象
ReactDOM.render(mydiv, document.getElementById('app'))
JSX语法
// 导入包
import React from 'react'
import ReactDOM from 'react-dom'
// 创建虚拟DOM元素
// const mydiv = React.createElement('div', {id: 'mydiv', title: 'div aaa'}, '这是一个div元素')
// JSX的写法 - JS中,默认不能写类似于HTML的标记,所以要使用babel来转化这些JS中的标签
// JSX语法的本质,还是在运行的时候,被转化为了React.createElement形式来执行
const mydiv = <div id="mydiv" title="div aaa">这是一个div元素</div>
// 调用render函数渲染
ReactDOM.render(mydiv, document.getElementById('app'))
- 安装如下
babel插件
cnpm i babel-core babel-loader babel-plugin-transform-runtime -D
cnpm i babel-preset-env babel-preset-stage-0 -D
转换JSX语法的包
cnpm i babel-preset-react -D
- 根目录添加
.babelrc
文件,配置
{
"presets": ["env", "stage-0", "react"],
"plugins": ["transform-runtime"]
}
-
webpack.config.js
配置
module: { //要打包的第三方模块
rules: [
{ test: /\.js|jsx$/, use: 'babel-loader', exclude: /node_modules/ }
]
}
语法及注意
import React from 'react'
import ReactDOM from 'react-dom'
let a = 10
let str = 'hello'
let boo = false
let title = 'FXD'
const hh = <h1>好好吃饭 做个好人</h1>
const arr = [
<h2>111111</h2>,
<h2>22222222222</h2>
]
const arrStr = ['11', '22', '33', '44']
// 所有节点,必须有唯一根元素进行包裹
ReactDOM.render(<div>
{a}
<hr/>
{str}
<hr/>
{boo ? 'z' : 'j'}
<hr/>
<p title={title}>pppp</p>
<hr/>
{hh}
<hr/>
{arr}
<hr/>
{/* 知识点: */}
{/* 1. 注释只能用此方法 */}
{/* 2. key存在的意义,是为了保持状态 - 多选框勾选时,新推入值,勾选项不发生改变 */}
{/* 3. key必须写在最外层 */}
{/* 4. 此处可用foreach在jsx外处理,区别,foreach不返回值,map要返回值,并且map必须写return */}
{arrStr.map(item => <div key={item}><h3>{item}</h3></div>)}
<hr/>
{/* className -- class */}
<p className="myclass">!!!!!!!</p>
<hr/>
{/* htmlFor -- for */}
<label htmlFor="ooo">1111</label>
</div>, document.getElementById('app'))
网友评论