文章目录
React总结
React技术栈 概述
React简介
- 是一个用于构建用户界面的 JavaScript 库
- 主要用于构建UI
- 性能较高,代码逻辑简单
React特点
- JSX — JS语法的扩展
- 声明式设计
- 高效 — 虚拟DOM,提高复用,减少与DOM的交互
- 灵活 —与已知的库或框架配合
- 组件 — 容易复用
- 单向响应的数据流 — 减少重复代码,父组件到子组件
相关技术
- React Native —— 原生移动应用
- React VR —— 虚拟应用程序
React安装
-
利用React脚手架工具
-
构建工具(webpack - 模块打包机) cd <fileName> --进入到某一个文件内 cd.. -返回上一层文件夹 npm init (-y) 项目初始化 npm i webpack webpack-cli -g -g是全局安装 npm install <packageName> == npm i <packageName> npm i <pname> --save-dev == npm i <pname> -D 安装开发依赖 npm i <pname> 后面不加参数,默认是项目依赖 卸载:npm uninstall <packageName> 打包 npm i webpack webpack-cli --save-dev npm i webpack webpack-cli -g webpack-dev server html-webpack-plugin 监听代码的变化,实时构建 配置命令 package.json 中,在 scripts 配置 start 以后启动项目执行 npm start
-
创建React项目过程 npx create-react-app my-app cd my-app npm start
-
React基础语法
JSX语法
- JSX
-
JavaScript 和 XML 结合的一种格式
-
利用 HTML 语法来创建虚拟 DOM
-
实例
React操作的是数据 插值表达式 const root = ReactDOM.createRoot( document.getElementById('root') ); 1、字符串 const title = "React"; 2、新的React元素 const title = {<span>hello</span>} 3、三目运算符 const title = {100>50?txt:"200"} 4、函数调用 const renderTxt = (txt) => { return txt; } const ele=<span>{renderTxt("React")}</span> const ele = <span>{title}</span>; root.render(ele);
-
- React元素 —— 实际为一个普通对象
- Babel编译(将声明式的代码转成对象)
- 把 JSX 转换成 React.createElement( ) 调用,返回 JS 对象
- React.createElement( type, props, …children )
元素渲染
-
”根“DOM节点
-
元素渲染
- 将 React 元素传递给 ReactDOM.render( ) 渲染到页面上
-
更新渲染元素
- React元素不可变,创建后无法改变内容和属性
- DOM比较算法
-
条件渲染(三目运算符/短路操作)
-
const flag = false; const ele = flag ? <div>react</div> : null //切换元素 const ele2 = flag && <div>react</div> //是否显示
-
-
循环渲染
-
1、 const list = ( <ul>{[<li>111</li>, <li>111</li>]}</ul> ) 2、 const data = [111, 222, 333, 444, 555, 666] const list = ( <ul>{data.map(item => <li>{item}</li>)}</ul> ) root.render(list);
-
组件
-
组件
- React组件是可复用的小代码片段
- 返回React元素用于渲染页面
- 类定义、函数定义
-
函数定义组件
-
快捷生成代码:rafce
-
接收props对象,返回React元素
-
props
- 从父组件传给子组件的属性
- 只读
- 名称大写字母开头
- 验证使用的是 PropTypes,传入数据无效时抛出警告
- 类组件默认含有,直接this.props使用
- 函数组件只是为了呈现,无法写具体功能;类组件可以写具体功能
-
eg:
1、 function App() { return ( <div> <header> ddd </header> </div> ); } 2、 const App = ()=>{ return <h1>Hello React{props.data}</h1> } export default App; props应用: const App=(props)=>{ console.log(props); return <h1> title:{props.title} id:{props.id} </h1>; } const root = ReactDOM.createRoot( document.getElementById('root') ); root.render(<App title="React" id="100"/>)
-
-
类定义组件
-
React.Component :React内的抽象基础类
-
继承React.Component 方式使用
-
至少定义一个render()
-
类组件基础语法举例
-
class Hello extends React.Component { render( ) { return <h1>Hello</h1>; } }
-
-
-
State
-
私有的、完全受控于当前组件,组件外部无法修改
-
类定义组件特有属性
-
状态声明(构造函数是唯一能够初始化 this.state 的地方 )
-
constructor( ){ super(); this.state = {name:’React’} } super传递props,在constructor中才能获取到this.props constructor(){ super();//把父级this传给子类,务必先写 //super 传递props,在constructor中才能获取到this.props this.state = { type: "类" } setTimeout(() => { this.setState({ type: "函数" }) }, 2000 }
-
直接state={}
-
-
-
生命周期函数
- 某一个时刻组件会自动执行的函数
- 类定义的组件中才有
- 阶段
- 初始化 —— constructor( )
- 装载前被调用
- 在任何其他的表达式之前调用super(props)
- 作用:
- 初始化状态,通过赋值一个对象到 this.state
- 绑定事件处理函数到一个实例
- 挂载
-
static getDerivedStateFromProps( ) —— 实例化后或接受新属性时调用
-
render() —— 类组件唯一、必须的方法
-
componentDidMount( ) —— 挂载后调用,发送请求 (fetch请求)
-
fetch('https://cnodejs.org/api/v1/topics') .then(res => res.json()) .then(res =>res.data ))//这里获取的data是一个数组,里面是对象
-
-
- 更新
- static getDerivedStateFromProps( )
- shouldComponentUpdate( ) —— 渲染前调用
- render()
- getSnapshotBeforeUpdate( ) —— 渲染提交前调用,返回值作为传参
- componentDidUpdate( )
- 卸载 —— componentWillUnmount( )
- 错误 —— componentDidCatch( )
- 初始化 —— constructor( )
事件处理
-
事件绑定
- 属性命名:驼峰式写法
- 传入一个函数作为事件处理函数
-
事件处理函数绑定this
-
bind绑定
- 绑定事件后 .bind(this)
-
箭头函数
-
const renderTxt = (txt) => { return txt; } const renderTxt = (txt) => txt; const renderTxt = t => {return t}; const renderTxt = t => t;
-
-
传参
-
函数声明时事件对象作为最后一个参数传入
-
onClick={(e) => this.show(id, e)} e 为事件对象
-
-
箭头函数的事件对象显示传入;bind 会隐式传入
-
onClick={this.show.bind(this, id)}
-
-
-
受控组件和非受控组件
- 受控组件
- React控制输入值的表单元素
- setState( )方法更新可变状态
- 非受控组件
- 数据在DOM中
- defaultValue :指定初始值
- refs :获取表单的值
- refs
- 访问在 render 方法中创建的 DOM 节点或 React 元素
- 适用
- 处理焦点、文本选择或媒体控制
- 触发强制动画
- 集成第三方 DOM 库
- 可以声明式实现,尽量避免使用 refs
DOM Elements
- React实现了一套与浏览器无关的 DOM 系统
- className
- onChange —— 处理输入
- htmlFor
- dangerouslySetInnerHTML —— 相当于innerHTML
- style —— 小驼峰命名;接收JS对象
PropTypes —— 类型检查
defaultProps —— 设置默认值
组件间交互
- 父组件向子组件通信
- 直接属性来传,在子组件调用this.props.函数名/参数名
- 子组件向父组件通信
- 直接传值无法实现
- 父组件传给子组件一个更新值的方法,子组件通过调用方法更新值
- 状态提升 —— 传函数子传父/传参父传子
- 两个子组件之间数据传递需要状态提升
- 当有多个组件需要使用相同的数据时,将这份数据提升到两子组件的共同父组件中进行管理
- 跨级组件间通信:使用 context 对象
- 实现跨越多层级交互
- 通过组件树提供了传递数据的方法 ,避免逐层手动传递props
- API
- React.createContext —— 创建上下文对象
- Provider —— 提供状态;只出现一次
- Consumer —— 获取状态
- 单独一个Context.js文件设置,用来放全局的状态
- 非嵌套组件间通信
- 利用二者共同父组件的 context 对象进行通信
- 使用自定义事件的方式
HOC(高阶组件)
- 重用组件逻辑
- 是一个函数,接收一个组件作为参数,返回新组件
Hooks
-
Hook是React 16.8新增特性
-
在不编写 class 的情况下使用 state 以及其他 React 特性
-
使用规则
- 只在最顶层使用 Hook
- 只在 React 函数中调用 Hook
-
基础Hooks Api —— 只能用于函数组件
-
useState —— 声明状态,可以多个
-
会将最新状态的值赋给初始值
-
const [num, setNum] = useState(0); num为参数,setNum为操作方法
-
const [plants, setPlants] = useState([]); setPlants( plants.map(item => { if (item.plantID == plant.plantID) { return { ...item, isCollect: !item.isCollect } } return item; }) )
-
为数组对象添加属性
<button>{item.isCollect ? "已收藏" : "收藏"} </button> 按钮名称改变
-
-
useContext —— 组件树功能
-
useEffect
-
异步操作,定时器等
-
操作有副作用的代码
-
代替生命周期
- componentDidMount
- componentDidUpdate:每次更新执行,return挂载执行完后执行
- componentWillUnmount
-
useEffect(()=>{ ... },[num]) 表示在num发生变化时执行 不写参数,只执行一次,相当于ComponentDidMount、componentDidUpdate
-
-
useReducer
-
const initState={ num:0, val:"", list:[] } const reducer=(state,action)=>{} const [state, dispatch] = useReducer(reducer,initState); const add =()=>{ dispatch({type:"add+1"}) })
- dispatch :派发更新
- action:是一个对象,必须有一个type属性,描述更新的内容
- reducer:是一个纯函数,记录着状态更新的规则
-
-
useCallback
- 用来缓存一个函数,仅在某个依赖项改变时才会更新
- 用法同useEffect(()=>{},[])
-
useMemo
-
const memoizedValue =useMemo(callback,array)
-
callback是一个函数用于处理逻辑
-
array 控制useMemo重新执⾏行的数组,array改变时才会 重新执行useMemo
- 不传数组,每次更新都会重新计算
- 空数组,只会计算一次
- 依赖对应的值,当对应的值发生变化时,才会重新计算(可以依赖另外一个 useMemo 返回的值)
-
useMemo的返回值是一个记忆值,是callback的返回值
-
优点
- 减少不必要的DOM循环和子组件渲染
-
-
useRef
-
存储不需要引起页面渲染的数据
-
返回值是一个可变的ref对象
-
修改useRef值的唯一方法是修改.current
-
const inputEle = useRef(); const add = () => { console.log(inputEle.current.value); } return <div> <input ref={inputEle} type="text" /> <button onClick={add}>添加</button> </div>
-
-
虚拟DOM与性能优化
虚拟DOM
- 介绍
- 编程概念
- 用于表示视图的对象
- 采用React的声明式API
- fiber对象来存储dom结构,差分算法diff可用于更新元素
- 优点
- 提升性能
- 实现跨端应用
- 差分算法(diff)
- 同级比对但意义不大
- 比对发生在state发生变化时
性能优化
-
利用key值提升性能
-
PureComponent
- React提供的类
- 比较前后props,state,不变则不渲染
-
memo
- memo会比较组件前后的props,如果没有变化就不更新
-
类组件可用memo和PureComponent 函数组件只可用memo,因为没有state,函数组件改变状态使用useState
-
useMemo
-
useCallback
React路由
路由配置
-
React 路由
- react-router 是浏览器和原生应用的通用部分
- react-router-native 是用于原生应用的
- react-router-dom 是用于浏览器的
-
安装
- npm install --save react-router-dom
- npm i react-router-dom@5.3.0
-
引入
-
import { BrowserRouter as Router,Route,Link} from 'react-router-dom'; …… class Hello extends React.Component { render( ) { return ( <Router> <div> <Route exact path='/' component={Home}/> <Route path='/about' component={About}/> </div> </Router> ); } }
-
-
BrowserRouter VS HashRouter
- 都是路由的基本组件,需将其放在最外层
- BrowserRouter 的 URL 是指向真实 URL 的资源路径,页面和浏览器的 history 保持一致
- HashRouter 使用 URL 中的 hash(#)部分去创建路由
- Router在整个项目中只会出现一次(一般最外层)
-
-
匹配路径、挂载组件
-
<Route exact path='/home' component={ Home }/> exact : 严格匹配 在匹配 /home 时不会再匹配到 / 的内容 path : 字符串类型,用来匹配url component : 值是一个组件,在 path 匹配成功后挂载这个组件
-
Route放在哪里切换哪里
-
-
<Redirect to = “…” >
-
当被挂载时,将路由重定向为 to 属性指定的地址
-
<Route path="/home" render={( )=><Redirect to="/other“ />}/>
-
-
from 和 exact 两个属性只能用在
组件下的 < Redirect /> -
<Switch> <Redirect from = '/old‘ to = ‘/new‘ /> <Route path='/new' component={ New }/> </Switch>
-
-
-
<Switch > … </Switch>
-
只会挂载与 路径匹配成功的第一个
-
子节点只能是 或
-
为根路径精准匹配,防止出现其他页面的同时渲染根路径内容;先写长的
-
<Route component={()=><h1>您访问的页面不存在</h1>}/> 在Switch中加入这样一项路由匹配,防止都匹配失败时显示首页 任何路径不存在时显示页面
-
-
<Link to = “…” > … </Link>
-
<Link to="/home">Home</Link> 点击改变地址栏地址 通过Link改变地址,Route在监听地址栏,以此改变页面,二者没有直接关联 Link为a标签
-
-
<NavLink to = “…” > … </NavLink>
- NavLink 是 Link 的子类
- activeClassName:string,被选中时添加的类名
- activeStyle:object,被选中时添加的行内样式
- exact:boolean,严格匹配
动态路由
-
路由内挂载的组件,是拥有四个属性(history、location、match、[[Prototype]]
对象)的对象
-
数据接收
-
match
- 包含** **匹配路径参信息的对象
- params、url、path、isExact
-
location.search
-
数据存放在 this.props.location.search
-
通过 URL 模块解析
-
npm install url –save url.parse(urlStr : string,parseQueryStr : true)
-
-
-
数据获取举例
1、 Link内可以传参数 <Link to="/?a=100&id=200">Home</Link> 通过props.location.search拿到 从而兄弟组件之间可以路由传递数据 2、 const NewsDetail = (props) => { return <div> {props.match.params.id} </div> } <Route path="/news/:id" component={NewsDetail} /> <Link to="news/1">News1</Link> 通过props.match.params.id 拿到id
-
路由Hooks
-
两种引入组件方式 1、 <Route path="/" component={Home} /> 2、不具备props的四个属性 <Route path="/"> <Home /> </Route>
-
useHistory
-
import {useHistory} from "react-router-dom"; const history = useHistory();
-
-
useLocation
-
import { useLocation} from "react-router-dom"; const location = useLocation();
-
-
useRouteMatch
-
useParams
-
import {useParams} from "react-router-dom"; const params = useParams();
-
-
优点
- 引入所需要的对象即可,避免通过props引入四个对象
封装好的代码组件
-
Axios
-
安装:npm i axios
-
文档用法:https://www.axios-http.cn/
-
使用方式: axios.get("xx") .then(res=>{}) eg: import axios from 'axios'; const baseURL = 'xx'; export const getPlants = () => { return axios.get(`${baseURL}/getPlants`) } export const getA = () => { return axios.get(`${baseURL}/aaaa`) } 在其他组件内调用: 引入:import { getPlants } from '...' 获得res值: getPlants() .then(res => { setPlants(res.data.result.plantList) })
-
-
Ant design
- 安装:npm i antd
- 文档
- https://ant.design/
- https://mobile.ant.design/