1、React是什么?
一个将数据渲染为HTML视图的开源JavaScript库,操作DOM呈现页面。
2、特点
旧版本:16.x,新版本:18.x
依赖包认识:
使用本地开发环境创建一个项目:
npx create-react-app my-app
删除掉新项目中 src/
文件夹下的所有文件。删除掉新项目中 src/
文件夹下的所有文件。
引入3个依赖包,引入顺序:react.development.js、react-dom.development.js、babel.min.js(没有老师的这个文件,可以直接引入官方网站)
1、创建虚拟DOM
2、渲染虚拟DOM到页面
Document
效果:
下载开发者工具:
注意:
1、用jsx创建虚拟DOM
2、用js创建虚拟DOM
创建多个虚拟DOM,jsx更方便
3、虚拟DOM就是一个Object类型的对象,即一般对象
4、与真实DOM的区别:consolog输出的真实DOM就是标签及内容,用断点查看会看到真实DOM身上的属性很多,而虚拟DOM身上的属性只有几个 =》原因:虚拟DOM是react内部在用,无需真实DOM
5、虚拟DOM最终会被react转化为真实DOM显示在页面上
jsx = js +XML,是react创造的
语法规则:
1、定义虚拟DOM时,不需要写引号,因为不是字符串
2、标签中混入js表达式(≠ js代码=js代码)时用{ }包裹,且变量内容大小写都有时要转换成小写
3、样式的类名不要写class,要写classname
4、内联样式,用{{ }}包裹,因为样式style里是key-value组成的形式,但是jsx里不能这么写,需要写成对象形式。多个样式时,用逗号隔开,且样式属性名只能用驼峰写法
5、虚拟DOM只能有1个根标签
6、标签要闭合
7、标签首字母为小写,标签转为html同名标签,无同名标签就报错。标签首字母为大写,标签渲染同名组件,找不到该组件就报错
案例:
关于遍历数据,只能遍历数组,不能遍历对象。
纯数组数据jsx无法渲染出来,但是数据如果是jsx形式就可以被直接渲染到页面,但很显然后端是不会提供这种形式的数据的
遍历时不能少了key,会报错
安装开发工具:
执行render后发生了什么?
(1)react解析组件标签,找到组件
(2)发现组件是函数定义的,调用该函数,返回的虚拟DOM转换为真实DOM,渲染到页面
执行render后发生了什么?
(1)react解析组件标签,找到组件
(2)发现组件是类定义的,new该类的实例,并通过实例调用原型的render方法
(3)将render返回的虚拟DOM转换为真实DOM,渲染到页面
1、初始化state + 事件绑定 + 修改方法的this指向:
注意两个this后指的是什么:
2、setState:修改数据
changeWeather() {
// changeWeather放在Weather的原型对象上,供实例使用
// changeWeather作为onClick的回调,不是通过实例调用的而是直接调用
// 类中的方法默认开启了局部的严格模式,所以changeWeather的this是undefined
// console.log(this);
// this.state.isHot = !this.state.isHot; // 数据是不能直接改的,直接改没法渲染
const isHot = this.state.isHot;
// setState修改数据,更新是新旧数据的合并,只修改改变的,不变的数据没有丢失依旧不变
this.setState({ isHot: !this.state.isHot });
}
组件的构造器调用1次,render就调用n+1次,n次是状态更新的次数,方法用几次就调用几次
3、简写
(1)state可以不写在构造器里,单独写出来,与render同级
(2)自定义方法写成赋值语句+箭头函数,满足修改this指向
changeWeather = () => {
// changeWeather放在Weather的原型对象上,供实例使用
// changeWeather作为onClick的回调,不是通过实例调用的而是直接调用
// 类中的方法默认开启了局部的严格模式,所以changeWeather的this是undefined
// console.log(this);
// this.state.isHot = !this.state.isHot; // 数据是不能直接改的,直接改没法渲染
const isHot = this.state.isHot;
// setState修改数据,更新是新旧数据的合并,只修改改变的,不变的数据没有丢失依旧不变
this.setState({ isHot: !this.state.isHot });
}
在组件标签上以key-value形式写的变量,实例里用this.props.变量名呈现
解构简写:
用...展开运算符,这里是浅拷贝的意思,不是将对象展开,...是无法展开对象的
15版本之前,react有一个属性propTypes可以限制,之后版本就用到prop-types包
限制函数写成=》PropTypes.func
将propTypes、defaultProps写成静态方法,放在类里
class Person extends React.Component {
// 限制标签属性值类型
static propTypes = {
name: PropTypes.string.isRequired, // 限制name为字符串,且必须有
};
// 给标签属性值设置默认值
static defaultProps = {
age: 18,
};
render() {
console.log(this); // Person实例
const { name, age, sex } = this.props;
return (
- name: {name}
- sex: {sex}
- age: {age}
- speak: {speak}
);
}
}
在构造器里可以不写props,但是用this无法找到当前类的props
constructor(props) {
super(props);
console.log(this.props);
}
constructor() {
super();
console.log(this.props); // undefined
}
调用后可以返回一个容器,该容器可以存储被ref标识的节点,该容器专节点专用(也就是会被新的覆盖)
发生事件的元素和操作事件的元素是同一个,可以省略ref
元素现用现取,用ref,如form里的input
元素不是现用现取,不用ref
注意!生命周期钩子函数的书写顺序与react调用顺序无关,react会在该调用的时候调用
卸载组件ReactDOM.unmountComponentAtNode (记忆:卸载组件在节点)
componentDidMount:组件挂载完毕
render:初始化渲染、状态更新之后
第一条路:正常更新
shouldComponentUpdate:控制组件是否更新,默认值true,如果程序员不亲自写则保持默认值,如果亲自写成false则永远无法更新状态
第二条路:强制更新
应用场景:不想对状态中的数据更新,但想更新页面
第三条路: 父子组件的生命周期顺序
构建父子组件:
如果新版本用了旧版本的钩子函数,在控制台3个带will的钩子函数,会被警告,且带上UNSAFE_钩子函数名称 :
18.x已废弃
如果返回值是一个状态对象,返回状态对象就会影响状态更新componentWillUpdate,返回的状态对象含有初始状态的数据,页面渲染就按返回的状态对象来。强制更新、卸载是不受影响的。
如果向组件传入数据,组件用props接收,getDerivedStateFromProps(props),return props的效果与上面所述一致。
应用场景:state的值取决于props
比较的最小粒度是节点
脚手架基于webpack
安装脚手架:
npm i create-react-app -g
cmd打开并输入以下命令:
create-react-app 项目名称
App.js
import './App.css';
// 创建组件App
import React from 'react';
class App extends React.Component {
render(){
return (
hello
)
}
}
export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// 检查App代码不合理的地方
);
reportWebVitals();
1、配置代理:
package.json:
“proxy”:“http://localhost:5000” 5000是服务器的端口号
2、配置多个代理
工具库:PubSubJS
安装:
npm i pubsub-js
使用:
在componentDidMount里写
浏览器window上内置,promise封装
有3个:web,native,any
安装命令:
npm i react-router-dom
1)src / index.js引入路由:
import { BrowserRouter } from 'react-router-dom';
2)将a标签改为路由标签,将a里的herf属性改为to属性
Link:无高亮
NavLink:有高亮
在App.js引入:
import { NavLink } from "react-router-dom";
3)在呈现组件的位置注册路由
问题:为何废弃旧版本的switch,改为新版本的routes
书写要点:
①要用
②组件名称写在element属性
③组件写成标签形式
④一个路由匹配之后,就算path一样,也不会再匹配其他路由
⑤重定向:Navigator 只要渲染,就会引起视图的变化,默认路由跳转模式是push,replace需要打开replace={true}
⑥自定义类名:写成函数形式,可以通过类名改变导航高亮的样式
⑦useRoutes:将多个路由写成一个路由表
一般业务开发,路由配置单独写在routes/index.js:
在App.js使用:
⑧嵌套路由
⑨路由占位符
相当于Vue-router里的view-router
10)hooks
<1>useRoutes
<2>useNavigator
编程式路由导航,返回一个函数
<3>useParams
接收当前匹配路由的params参数,直接解构就可以直接使用
<4>useSearchParams
读取和修改当前位置的url中的查询字符串
返回一个数组:[当前的search参数,更新的search参数] 《==》 [search, setSearch]
search:search参数对象,获取某个参数 =》search.get(参数名)
setSearch:更新search参数的方法
<5>useLocation
获取当前location信息
<6>useMatch
返回当前匹配信息
<7>useInRouterContext
返回是布尔值,只要是App的子组件,不管是不是路由组件,该hook的输出都是true,说明处于上下文环境中
某个组件脱离路由器的管理,就会返回false
<8>useNavigationType
通过哪种路由方式来到当前组件
返回值:pop(通过刷新页面而来),push,replace
<9>useOutlet
呈现当前组件中渲染的嵌套路由组件
<10>useResolvedPath(URL)
给定URL,解析其中的path、search、hash
编程式路由导航
1、安装
npm i antd --save
2、引入
// 按需引入组件
import {Button} from "antd";
// 引入antd的样式
import "antd/dist/reset.css";
引入ant.css出现错误可以尝试引入ant.min.css
3、按需引入
配置具体的修改规则,config-overrides.js
4、自定义主题
安装less:npm i less less-loader
react组件要进行行为时,创建一个动作对象action,action存储数据类型type和具体数据data,告诉action actors,action actors派发dispatch给store,store是一个调度者指挥者,并不对数据进行改动,store将当前数据状态和action对象发给reducers,reducers本身可以初始化状态state,此时previousState=understand,reducers把action数据对象进行加工更改后返回新的数据状态给store,store再把新的数据返回给react组件,组件通过getState获取
(1)createStore():创建store 已弃用
新版本 =》import { legacy_createStore as createStore } from 'redux';
(2)store.getState():获取状态
(3)store.dispatch():派发action数据对象
(4)store.subscribe(()=>{}):检测redux数据变化,数据变化就调用render
(1)同步:object一般对象类型的action
(2)异步:函数类型的action,return也是函数
react插件库
优化:
react状态更新是异步的
lazy本身是一个函数,在内部还要调用一个函数
3、hook
(1)statehook ==》 React.useState()
返回值,数组,[状态,更新状态的方法]
(2)effecthook
(3)refhook
4、fragment
5、 context
6、PureComponent
7、render props
8、ErrorBoundary 错误边界
9、 组件通信方式