antD demo
import React from 'react';
import logo from './logo.svg';
import { Button, Space } from 'antd';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<BB></BB>
</header>
</div>
);
}
const BB: React.FC = () => {
alert('hello')
var nu: string[]
nu = ['张三', '李斯', '许三多']
return (
<Space wrap>
{
nu.map((valeu) => {
return (
<>
<Button type="primary">{valeu}</Button>
<Button type="primary">{valeu}</Button>
</>
)
})
}
</Space>
)
};
export default App;
recat 中对与数组,对象的操作 尽量不要对原数据直接添加,最好生成新的对象数组,避免不要要的bug,页面不重新渲染
aap.js
import * as React from "react";
import { Routes, Route, Link} from "react-router-dom";
import AppForm from './views/from';
import './App.css';
function App() {
return (
<div className="App">
<h1>hello!React</h1>
<AppForm></AppForm>
<Routes>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Routes>
</div>
);
}
// App.js
function Home() {
return (
<>
<main>
<h2>home</h2>
</main>
<nav>
<Link to="/about">About</Link>
</nav>
</>
);
}
function About() {
return (
<>
<main>
<h2>About</h2>
</main>
<nav>
<Link to="/">Home</Link>
</nav>
</>
);
}
export default App;
from(函数)组件
import React, { useState, useEffect } from 'react';
import { Button, Space } from 'antd';
const myMethod = (setData,c) => {
setData({
a: c
});
};
const AppForm = React.memo(() => {
const [data, setData] = useState({ a: '1' });
useEffect(() => {
// 加载和调用方法,setData useEffect第一个参数异步此时打印的是1
myMethod(setData,'wwwwwwwwwww');
console.log( data.a);
}, []);
return (
<Space wrap>
<Button type="primary">{data.a}</Button>
<Button>Default Button</Button>
</Space>
);
});
export default AppForm;
state
immer简化不可变对象操作
拷贝出一个新的值,可以直接对拷贝出的值进行操作
状态重置处理问题
props(只读不能修改,可以运算)
import './App.css';
function App() {
return (
<div className="App">
<AppForm name='hello'></AppForm>
</div>
);
}
const AppForm = ((props) => {
console.log(props)
//此行代码页面会报错
props.name='不能修改,会报错,所以props是只读'
return (
<h1>{props.name}</h1>
);
});
export default App;
扩展...传值
props 对组建标签进行属性限制 prop-typs
refs
字符串ref(官网已经不推荐)
拿到的是真实dom
回调函数ref
c-当前节点,赋值给当前对象,然后从当前对象取值
注意事项 更新组件的时候内联函数会执行2次
将ref的回调函数,定义成class的绑定函数
createRef
react事件处理
- 通过onXXX属性指定事件chuli函数(注意大小写)
- Reacr使用的是自定义(合成)事件,而不是使用的原生DOM事件--为了更好的兼容性
- React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)--为了更高效
- 通过event。target得到发生事件的dom元素对象---不要过度使用ref
受控组件和非受控组件
收集表单数据
现用现取非受控组件
受控组件
高级函数和函数柯里化
高级函数
【】中括号读变量名 取值
柯里化
其他写法
生命周期
render
调用时机:初始化渲染,状态更新之后
componentDidMount
组件挂载完毕调用一次
componentWillUnmount()
组件将要卸载调用(卸载前)
旧版
新版生命周期 17
可以用来获取页面更新之前的数据(使用概率极低 )
diffing
错位
初始dom和更新后的dom对比, key0 小张变小王,内容发生变化,对比input 发现内容一样,使用旧的,真实dom 的 input 不会重新更新,以此类推会导致数据错位
react脚手架
npx安装创建(官方推荐)
npx:是一种在npm中安装工具,在 npm version >= 5.2.0 开始,自动安装了npx。目的是提升包内提供的命令行工具的使用体验。
npx create-react-app 是固定命令,create-react-app是React脚手架的名称。
npx 命令会帮助我们临时安装create-react-app包,然后初始化项目完成之后会自自动删掉,所以不需要全局安装create-react-app
npx create-react-app my-app
cd my-app
npm start
指定React版本安装
npx create-react-app my-app安装默认都是最新的版本,因为React18与React17的语法有些差别如果想使用React17的版本,需要我们指定版本,执行如下代码进行版本降级:
npm install react@17.x react-dom@17.x --save
注意:npm install 安装库@版本号 --save
17.x 表示的更新范围为>=17.0.0&&< 18.0.0
17.2.x 表示的更新范围为>=17.2.0&&< 17.3.0
降级完成之后,对src下的入口文件index.js进行修改,如下:
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
// 18
// const root = ReactDOM.createRoot(document.getElementById('root'));
// root.render(
// <React.StrictMode>
// <App />
// </React.StrictMode>
// );
// 17
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
项目结构介绍
index.html
创建类组件
函数组件在上面from组件
vscode中的react插件
rcc -类组件
rfc-快速生成函数式组件
react ajax 配置代理
axios
单个代理
3000没有的资源找5000
多代理setupProxy.js. 文件名固定
案例
连续解构复制
案例二
父组件
子组件
react兄弟组件交互 消息订阅与发布PubSubJS
案例
app.js---展示 父组件
search---子组件
list---子组件
app
searc h传数据给list
list届收订阅消息
list输出
React路由
插件 react-router-dom 版本5,目前已更新到版本6
路由组件和一般组件
<navLink>
修改默认激活点击样式
封装navlink
标签体(开始标签和结束标签中的文本)中的内容也会被收集到props属性中,默认key是 children
封装MyNavLink
使用
总结
<Switch> 新版以废弃
匹配到hone组件后,就不会继续往下匹配
解决多级路径刷新页面样式丢失问题
路由的模糊匹配和精准匹配 exact
<Redirect> 重定向
嵌套路由
路由匹配是按照注册顺序的,如果子路由不加home前缀,会先匹配最开始注册的路由,由于没有/news 路由,所以会重定向到about,加了前缀home 会进行模糊匹配,先匹配到home路由,然后再往下匹配
home下的子路由
向路由组建传递参数(props)
第一种params参数
组件接收
传递search参数
取参数
传递state参数(路由组件独有的参数,和组件的state没有任何关系)
地址栏不带信息
注意:清空浏览器缓存 数据会丢失
传递的是个对象
接收参数
push 与replace模式 默认是push
push 有历史痕迹,
路由历史是栈
开启replace模式 (会替换,如果所有的路由都开启,就没有浏览痕迹)
编程式路由导航(代码操作路由跳转)
replace 跳转
push跳转
一般组件使用路由组件的api withRouter
withRouter的返回值是一个新组建
BrowserRouter和HashRouter的区别
React路由6
概述
使用案例
index.js
app.js
重定向 navigate
路由跳转模式,默认是push 可以开启replace
caseSensitive 区分路由大小写(默认不区分)
使用 caseSensitive 区分大小写
navlink自定义高亮
路由表(useRoutes)
使用
嵌套路由
修改路由表 配置子路由
home
点击子级路由取消父级高亮 在父级 路由标签加end 属性
路由传参
message的子路由
message 传参的地方
params参数
路由表 占位符
子路由组件 Detail 获取参数
search参数
路由表不需要占位符
message传参数的地方
detail接收参数
setSearch 更新传入的search参数 (了解即可)
state参数
路由表不需要占位
message传参
Detail接收参数
编程式路由导航uaseNavigare
其他
redux(状态管理)
精简版
store.js
.count_reducer.js
组件中使用
。初始化调用countRedecur 是 获取的0
调用修改redux中的状态值
redux只管理状态,不会调用render 所以状态变化的页面不会渲染,需要监听一下redux中状态的变化,只要有变化,就重新渲染组件
上面的方法如果有多个组件,每个组件都需要写
方法二
直接在渲染整个外层的组件(入口文件),有diff算法不会影响效率问题
完整版redux
count_action.js 抽出固定判断对象
组件使用
异步函数 dispatch传入的是对象是同步,传入的是函数就是异步
组件
第二种写法
react-redux faceBook 出品
redux文件创建和上一章节一样
容器组件
容器组件和ui组件关联
最终
index.js
优化
不需要我们在手动监测
app.js
给容器传递store
优化 app.js 和 index.js
入口文件index.js,把store传给所有组件
redux文件
,第一个constant 放常量的,没有截图,知道就行
容器组件
可以使用count_action
定义的 方法再精简一下
可以传递多个方法,用逗号隔开
优化
ui组件
调用父组件传递的jia方法
接收参数
整合ui组件和容器组件
ui组件拿到容器组件就行
redux多组建共享一个状态
写一套和count一样的redux
修改store.js 汇总reducers
此时state 是个对象,注意区值方式
容器中掌握了所有的redux
纯函数
React扩展
setState
更新状态的两种写法
第一种
第二种
lazyLoad 路由懒加载
loding不能做懒加载
Suspence 加载中显示的内容
Hooks
useState
useEffect
加空数组 组件初始化执行
useRef
Fragment 类似 空标签 <></>
区别 fragment 可以有个key 属性,用来遍历
解决嵌套无用的div标签
Context 组件之间通信(一般常用后代组件传递,父子直接使用props)
用Provider 包围下的所有子组件都可以获取到
注意想要使用必须要声明一下
第一种只支持类组件
第二种方式 支持类组件和函数组件
组件优化 类组建继承Component的问题
所有类组件都继承 PureComponent
注意 :以下写法,修改的是同一对象,因为PureComponent底层比较的是对象地址,所以render不会被调用,即使内容有所改变,页面也不会重新渲染,因为obj和state指向的是同一地址
render props 向组建内部动态传入带内容的结构(标签)
this.props.children 拿到A标签的方法体
B标签可以通过方法动态替换,类似vue的插槽技术
错误边界
在容易发生错的父组建动手脚
假设一个会报错的子组件
解携users可定会报错
把错误限制在父组件
注意:此方法只适用于打包后,测试只会出来一瞬间
注意只能捕捉生命周期的错误