React 是 facebook 出的一款针对视图层的库(library)。它是基于单向数据流思想开发的,主要的一个功能就是针对视图显示,让我们把一个项目拆分成一个一个组件进行开发维护。
目前我们讲的 react 是基于 18.2 的版本。react 每一个版本更新之后会加入新的 api,但是同时也会保证向下兼容
<!DOCTYPE html> <html lang="en"> ?<head> ? ?<meta charset="UTF-8" /> ? ?<meta http-equiv="X-UA-Compatible" content="IE=edge" /> ? ?<meta name="viewport" content="width=device-width, initial-scale=1.0" /> ? ?<title>jsx语法</title> ?</head> ?<body> ? ?<div id="root"></div> ? ?<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script> ? ?<script ? ? ?crossorigin ? ? ?src="https://unpkg.com/react@18/umd/react.development.js" ? ?></script> ? ?<script ? ? ?crossorigin ? ? ?src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" ? ?></script> ? ?<script type="text/babel"> ? ? const App = () => { ? ? ? return ( ? ? ? ? <> ? ? ? ? ? <h1>这是一个组件</h1> ? ? ? ? </> ? ? ? ); ? ? }; ? ? ReactDOM.createRoot(document.querySelector("#root")).render(<App />); ? ?</script> ?</body> </html>
就是在 js 中可以直接写 html 标签
function 定义的组件又叫无状态组件。每一个组件都需要一个返回值,返回当前组件展示的 dom 结构
父传子,使用属性
子传父,使用方法调用
非相关组件,使用 context 上下文或者 redux 状态管理插件
组件内部嵌套的标签可以通过 children 属性获取
hooks 是 react16.8 之后新增的 API,可以在 function 定义的组件中设置局部状态数据和模拟组件生命周期
hooks 只能在 function 定义的组件内部使用,因为它内部实现的时候使用了数组和闭包,所以 hooks 不能放置在条件表达式和循环语句中。只能放在组件的最外层
最用式定义一个局部状态数据,当组件的状态或者属性改变的时候组件会重新渲染(即定义组件的这个方法会重新执行)
const Counter = () => { ?// useState定义一个状态数据 ?// 接收一个默认值作为参数,返回一个数组 ?// ? 数组的第一项表示可以使用的变量名 第二项表示改变数据的方法 ?// 一定要注意,数据改变只能调用方法二 ?const [count, setCount] = React.useState(0); ?return <button onClick={() => setCount(count + 1)}>按钮--{count}</button>; };
副作用,useEffect 接收两个参数,参数一是一个回调函数,参数二是一个依赖数组。当依赖数组中的数据改变之后,会触发回调函数重新执行。可以模拟组件的生命周期钩子函数
... useEffect(()=>{ ?console.log('执行了') ?return () => { ? ?// 此方法在组件销毁的时候执行 } }, [a, b, c]) ...
useEffect 的参数二有以下三种形式:
参数二为空数组。那么参数一的回调函数只有在组件初始化的时候执行一次
参数二中存在数据。那么参数二中的每一个数据改变,都会触发回调函数的执行
参数二不存在,就是只有参数一。那么每一次组件更新的时候,回调函数都会执行
useEffect 参数一的回调函数中,可以返回一个 function,这个返回的方法在组件销毁的时候执行
memo 的作用是对组件做缓存,当组件接收到的属性不改变的话,组件不会重新更新。以后会经常使用
推荐大家大量使用,主要做优化
useRef 的作用是获取 dom 元素,通过 current 属性实现
const App = () => { ?const hTag = React.useRef(); ?const pTag = React.useRef(); ?React.useEffect(() => { ? ?console.log(hTag); ? ?console.log(pTag); // .current属性可以获取dom元素 ? ?pTag.current.style.color = "red"; }, []); ?return ( ? ?<> ? ? ?<h1 ref={hTag}>这是一个组件</h1> ? ? ?<p ref={pTag}>这是一段话</p> ? ?</> ); };
作用是缓存一个 function,接收两个参数,参数一表示被缓存的方法,参数二表示依赖项。当依赖的数据不改变的话,回调被缓存的方法不会重新定义
React.useCallback(() => {}, []);
作用是缓存一个值,接收两个参数,参数一是被缓存的数据,参数二是依赖项。当依赖项不改变的时候,缓存的数据不会更新
useMemo 和 useCallback 的区别:useMemo 缓存一个值,useCallback 缓存一个 function
context 上下文,用来实现跨组件之间传参。useContext 可以获取 context 中的数据
useReducer 是另一种状态数据存储的方案,和 useState 不一样。类似于 redux 的实现
useReducer 接收两个参数,返回一个数组。它的数据改变只能通过 dispatch 一个 action 实现。两个参数分别为:
reducer 函数,这个方法接收两个参数。原始状态数据和一个 action,在方法体中根据 action 的 type 不一样,返回个新的数据作为状态数据值
初始值
useReducer 函数的返回值是一个数组,数组的第一项表示状态数据,第二项是 dispatch 方法。如果要改变数据,只能 dispatch 触发 reducer 函数执行。
... const [state, dispatch] = useReducer((state, action)=>{ ?switch(action.type) { ? ?case 'PLUS': ? ? ?return {...state, count: state.count+1} ? ?default: ? ? ?return state } }, initState) ...
就是自己定义一个 hooks,定义的时候把方法名按照 hooks 的命名方式写,比如 useXXX
class 定义的组件有自己的局部状态和生命周期钩子函数。class 定义的组件都继承者 Component 或者 PureComponent。
Component 和 PureComponent,他们两个都可以用来作为被继承的父类,实现 class 定义组件。PureComponent 定义的组件相当于做了缓存,在进行数据比较的时候是进行的浅比较,和 memo 效果类似。
function 定义的组件和 class 定义的组件两者是可以混合使用
class Counter extends React.Component { ?constructor(props) { ? ?super(props); ? ?this.state = { ? ? ?count: 1, ? ? ?title: "这是一个计数器组件", ? }; } ?// 每一个class定义的组件都需要render方法,这个方法返回一个dom元素,表示组件需要显示的节点内容 ?render() { ? ?return ( ? ? ?<> ? ? ? ?<h1>{this.state.title}</h1> ? ? ?</> ? ); } }
状态数据定义的时候使用 state 进行。改变状态使用 setState,setState 是异步的,我们想获取改变之后的最新值,可以使用 setState 的参数二,它是一个 function,可以在里面获取 state 的最新值
... this.setState({ ?count: this.state.count+1 }, () => { ?// 在此处可以获取state的最新值 }) ...
class Counter extends React.Component { constructor(props) { super(props); this.state = { count: 1, title: "这是一个计数器组件", }; } // 每一个class定义的组件都需要render方法,这个方法返回一个dom元素,表示组件需要显示的节点内容 render() { return ( <> <h1 ref="ht1">{this.state.title}</h1> <button onClick={() => { // refs获取所有设置了ref属性的标签 }} > 获取dom </button> </> ); } } Counter.contextType = context; // 设置了之后,就可以直接在组件中通过this.context获取上下文中的数据
16.3 之前
componentWillMount,将要挂载
render
componentDidMount【重要】,挂载完成,很重要。一般在这里进行调接口取初始化数据
componentWillReceiveProps,将要接收新的属性。属性数据改变之后执行
shouldComponentUpdate【重要】,判断组件是否需要更新,主要用来做组件性能优化。返回一个 bool 值,为 true 后续的更新阶段会执行;否则不执行更新阶段
componentWillUpdate,将要更新
render
componentDidUpdate,更新
componentWillUnmount,卸载
class 定义组件的生命周期和 function 组件的 useEffect 对应关系:
componentDidMount,对应参数二为空白数组
componentDidUpdate,对应参数二中有数据
componentWillUnmount,对应参数一返回的 function
嵌套组件的生命周期,在执行完父组件的 componentWillMount 之后,进行 render 时,开始解析 dom。发现子组件之后,就会执行子组件的创建到挂载的生命周期钩子函数,当子组件全部挂载完成之后,会执行父组件的挂载完成。
官方的脚手架,搭建项目
npx create-react-app first-react-app # 创建一个react项目 cd first-react-app npm start # 启动项目,默认3000端口
使用 vite 创建 react 项目
npm init vite@latest #
路由是一个组件,这个东西是你以后面试的时候几乎不会问的一个问题。
npm i react-router-dom # 安装插件,我们讲的是6.4的
常见的组件:
HashRouter,路由的最外层节点,所有的路由组件都需要放在它里面
Link,链接。需要一个 to 属性,可以添加 state 和 replace 等属性
Routes,Route 的外层节点
Route,每一个路由。需要 path 和 element 两个属性。path 表示路径,element 表示对应的组件
NavLink,链接。相对于 Link 来讲,多了一个选中样式
Navigate,实现跳转。通过 to 属性
常见的 hooks:
useParams,可以获取动态路由中的参数
useLocation,可以获取 location 数据,直接通过 search 或者 state 获取传递的参数
useNavigate,可以实现页面跳转。参数一表示地址,参数二是配置项。配置项中常用的有:state(传递的数据),replace(不生成历史记录)等
传参方式,有三种:
params,动态路由传参
search,url 中直接通过?拼接字符串
state,就是 state
直接写 Route 在对应的位置就好
可以使用 Outlet 组件,它表示子路由展示的位置
需要借助自定义组件的封装
ui 组件库
antd 出的一款图表插件https://charts.ant.design/zh
npm i @ant-design/charts # 安装插件
是一个状态管理插件,作用是实现项目中的数据共享。可以和任何一个框架结合,比如:react、angular、vue 都行。遵循单向数据流的机制:数据是单向流动的,我们在视图中 dispatch 派发一个 action 改变数据,数据改变之后视图重新渲染。
# redux是做数据管理的,所有的数据相关的操作都放在redux中 npm i redux # 安装核心库 npm i react-redux # 这个插件可以让我们redux数据和react项目关联
redux中常用的 api:
createStore,创建一个 redux 数据。目前(2022-11)已经不被推荐使用,建议使用 redux-toolkit 创建
combineReducers,合并多个 reducer 函数为一个
react-redux中常用的组件和 api:
Provider,组件。放在项目的最外层,通过 store 属性实现 redux 数据和 react 项目的关联
connect,高阶组件。作用是把 redux 中的数据和 dispatch 方法映射到组件的属性上。可以在 class 和 function 定义的组件中同时使用
useSelector,方法。作用是在 function 定义的组件中获取 redux 中的数据
useDispatch,方法。作用是在 function 定义的组件中获取 dispatch 方法
redux-thunk,这是一个中间件,用来解决 redux 中的异步操作。在 redux 中,所有的 action 都是一个 plain object,如果牵涉到异步,需要借助中间件实现。它的作用是判断我们的 action 数据类型,如果是一个对象,那么直接执行;如果是一个 function,那么会把 dispatch 函数当参数传给方法,在方法内可以调用 dispatch
作用是可以让我们快速的实现 redux 开发,封装好了各种功能
npm i @reduxjs/toolkit react-redux # 安装
权限控制分为前端和服务器端,都会做限制。我们前端会根据当前登录用户的角色展示不同的路由信息,每一次调接口的时候服务器端也会验证权限,没有权限的时候返回 401 状态码,我给用户提示。
展开讲讲:每一个路由上都会添加一个属性 role,我会根据用户登录之后服务器端返回的角色,进行动态路由展示的控制
就是在公司中可以直接拿来开箱即用的框架,不需要额外的做多余的配置
是蚂蚁金服出的一个框架,内置了路由等各种插件,可以直接拿来做项目开发
nvm,是一个 nodejs 的版本管理工具,可以在电脑上安装不同版本的 node。当然你也可以直接安装不同的 node 安装包
# 创建项目,国内建议使用pnpm # pnpm是一个node的包管理工具,超级好用 pnpm dlx create-umi@latest # or 使用npx创建项目 # npx create-umi@latest pnpm dev # or # npm run dev
npx @ant-design/pro-cli create pgsq-doctors-app # 创建一个antd pro项目
这是目前很流行的一个 css 库,可以让我们非常方便的实现页面布局。它内置了很多 css 效果,我们只需要按照样式名进行使用就好
中文翻译的文档,版本有些老
# 在vite项目中使用 npm install -D tailwindcss postcss autoprefixer # 安装 npx tailwindcss init -p # 初始化配置文件
是一个 react 的开发框架,可以让我们是用 react 做多页面开发和服务器端渲染。最新的版本是 13 的,十月份的时候刚更新的。这个内容是作为大家了解的知识点
npx create-next-app test-app # 创建一个next项目
SPA 单页面应用程序做 SEO 的解决办法:SPA 就是单页面应用程序,所有的页面都是只有一个入口 html 文件,没有办法做 SEO,为了解决这个问题我们可以使用 nuxt.js 或者 next.js 等这种服务器端渲染框架作为替代。早期的解决方案,就是制作一个专门用来做 SEO 的静态网站,判断访问我们的是搜索引擎的蜘蛛时,跳转到静态网站,用户访问的时候显示我们的真实项目。可以通过这个网站查站点的 seo 优化信息SEO综合查询 - 站长工具
pages 文件夹中的文件会自动的生成路径;其中 api 文件夹中的内容为服务器端数据接口
直接通过 api 文件夹中的接口
在页面中使用对应的方法
getServerSideProps,每一次请求页面的时候都会执行
getStaticPaths,编译的时候执行一次,用来生成静态页面
getStaticProps,编译的时候执行一次,用来根据 getStaticPaths 中路径参数生成对应路径的静态页面。两个方法需要配合使用
样式化组件,以后如果你进了一些好公司,做组件封装的时候可能会用到这个东西
antd mobile
mui
ionic
framework7