以下的新语法,都是固定的用法,不涉及原理性的东西,老师也讲的很快很简略,记住基本用法就行了,等真正做项目的时候可以仔细看文档。其实新语法还有很多老师没有讲,文档是一定要看的。
注意:setState是用在类组件里面的,函数式组件里面使用useState()了。
1、对象式的setState
一般我们使用的是对像式的写法,同时省略了第二个参数。setState函数本身是同步的函数,但是react底层的渲染更新是异步的。下面是证明:
xxxxxxxxxx201import React, { Component } from "react";23export default class Demo extends Component {4 state = {5 count: 0,6 };7 increment = () => {8 const { count } = this.state;9 this.setState({ count: count + 1 });10 console.log("第10行的count值为:",this.state.count);11 };12 render() {13 return (14 <div>15 当前结果为:{this.state.count}16 <button onClick={this.increment}>点我+1</button>17 </div>18 );19 }20}
注意看:页面结果更新为1,但是第10行的输出是0。说明react渲染过程是异步的。
对象式setState的第二个参数写一个箭头函数,可以输出结果看一下:
xxxxxxxxxx231import React, { Component } from "react";23export default class Demo extends Component {4 state = {5 count: 0,6 };7 increment = () => {8 const { count } = this.state;9 // callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用10 this.setState({ count: count + 1 },() => {11 console.log("第10行的count值为:",this.state.count);12 });13 console.log("第12行的count值为:",this.state.count);14 };15 render() {16 return (17 <div>18 当前结果为:{this.state.count}19 <button onClick={this.increment}>点我+1</button>20 </div>21 );22 }23}
2、函数式的setState
xxxxxxxxxx261import React, { Component } from "react";23export default class Demo extends Component {4 state = {5 count: 0,6 };7 increment = () => {8 // 函数式的setState第一个参数是一个函数,返回的是stateChange对象的函数。可以接收到state和props9 this.setState((state,props)=>{10 return {11 count:state.count + 112 }13 })14 15 // 简写方式16 this.setState((state,props) => ({count:state.count+1}))17 };18 render() {19 return (20 <div>21 当前结果为:{this.state.count}22 <button onClick={this.increment}>点我+1</button>23 </div>24 );25 }26}总结:setState更新状态的2种写法
xxxxxxxxxx141(1). setState(stateChange, [callback])------对象式的setState21.stateChange为状态改变对象(该对象可以体现出状态的更改)32.callback是可选的回调函数, 它在状态更新完毕、界面也更新后(render调用后)才被调用45(2). setState(updater, [callback])------函数式的setState61.updater为返回stateChange对象的函数。72.updater可以接收到state和props。84.callback是可选的回调函数, 它在状态更新、界面也更新后(render调用后)才被调用。9总结:101.对象式的setState是函数式的setState的简写方式(语法糖)112.使用原则:12(1).如果新状态不依赖于原状态(比如说获取后端数据) ===> 使用对象方式13(2).如果新状态依赖于原状态 ===> 使用函数方式14(3).如果需要在setState()执行后获取最新的状态数据, 要在第二个callback函数中读取
xxxxxxxxxx121import { lazy, Suspense } from "react"23//1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包4const Login = lazy(()=>import('@/pages/Login'))56//2.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义loading界面,这个界面挂载到fallback属性上。也可以自定义一个组件,然后直接引入,写在这里。7<Suspense fallback={<h1>loading..</h1>}>8 <Switch>9 <Route path="/xxx" component={Xxxx}/>10 <Redirect to="/login"/>11 </Switch>12</Suspense>示例:
xxxxxxxxxx241import React, { Component, lazy, Suspense, Fragment } from "react";2import { Link, Route, Routes } from "react-router-dom";34const Home = lazy(() => import("./Home"));5const About = lazy(() => import("./About"));67export default class index extends Component {8 render() {9 return (10 <Fragment>11 <h2>切换路由</h2>12 <Link to="/about">About</Link>13 <Link to="/home">Home</Link>1415 <Suspense fallback={<h1>loading......</h1>}>16 <Routes>17 <Route path="/about" element={<About />} />18 <Route path="/home" element={<Home />} />19 </Routes>20 </Suspense>21 </Fragment>22 );23 }24}将浏览器的disable cache勾选上,然后选择慢速网络,就可以看到效果了。

如果想更多的了解hooks的用法,可以查看阮一峰的文章:https://www.ruanyifeng.com/blog/2019/09/react-hooks.html,https://www.ruanyifeng.com/blog/2020/09/react-hooks-useeffect-tutorial.html。
xxxxxxxxxx21(1). Hook是React 16.8.0版本增加的新特性/新语法2(2). 可以让你在函数组件中使用 state 以及其他的 React 特性
xxxxxxxxxx31(1). State Hook: React.useState()2(2). Effect Hook: React.useEffect()3(3). Ref Hook: React.useRef()
说实话,用起来也蛮好用的,但是定义多个变量,要一个一个定义,不知道一个复杂组件里面能不能定义一个复杂对象,对象的监听会不会有问题,这些都要等实际操作的时候才能知道。
xxxxxxxxxx171import React, { useState } from "react";23export default function Demo() {4 // Demo这个函数式组件,调用的次数是1+n次,1指的是初始化渲染,n次指的是n次的重新渲染,那么在n次重新渲染时,下面这行代码会重复执行吗?如果重复执行,岂不是count值每次都会重新初始化为0?其实react做了处理,只有在初始化时指定的值在内部作缓存,其余时候使用的是缓存。5 const [count, setCount] = useState(0);6 function increment() {7 setCount(count + 1); // 写法1,这里有一点我不理解,为什么可以直接写count+1?因为这是在函数里面,已经定义了count,当然可以作为参数传入进去了。8 // setCount((count) => count + 1); // 写法29 }10 return (11 <div>12 <div>当前结果为:{count}</div>13 <button onClick={increment}>点我加1</button>14 </div>15 );16}17s
xxxxxxxxxx121(1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作2(2). 语法: const [xxx, setXxx] = React.useState(initValue)31、xxx 指的是定义的状态变量名42、setXxx 是更新状态值的函数,命名方法是 set + 状态变量名(首字母大写),比如说:定义count变量,那么更新它的函数就命名为 setCount53、initValue指的是状态变量的初始值67(3). useState()说明:8参数: 第一次初始化指定的值在内部作缓存9返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数10(4). setXxx()2种写法:11setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值12setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
需求:让结果每隔1秒+1,显示出来。
分析:在类组件中可以使用生命周期钩子componentDidMount()和componentWillUnmount()来处理相关逻辑,那函数式组件里面没有生命周期钩子,怎么办呢?就要使用useEffect()来执行副作用操作(相当于模拟类组件中的生命周期钩子,总结中说明了useEffect()相当于三种生命周期的组合,那如果我要用别的生命周期钩子,该怎么办呢?可能原因就是react设计者们认为别的生命周期钩子没有什么作用了,或者说用别的hooks可以达到目的,到时候如果我遇到了问题,再搜索答案吧)。
xxxxxxxxxx371import React, { useState, useEffect } from "react";2import ReactDOM from "react-dom/client";3// react@18中,要在应用的index.js中将root暴露出来,使用root.unmount()方法来卸载组件。4import root from "../../index.js"56export default function Demo() {7 // Demo这个函数式组件,调用的次数是1+n次,1指的是初始化渲染,n次指的是n次的重新渲染,那么在n次重新渲染时,下面这行代码会重复执行吗?如果重复执行,岂不是count值每次都会重新初始化为0?其实react做了处理,只有在初始化时指定的值在内部作缓存,其余时候使用的是缓存。8 const [count, setCount] = useState(0);9 function increment() {10 setCount(count + 1); // 写法111 // setCount((count) => count + 1); // 写法212 }1314 // 卸载组件15 function unmount() {16 // ReactDOM.unmountComponentAtNode("root"); // 此方法在react@18中已废弃,要使用这种方法:https://blog.csdn.net/weixin_43842973/article/details/13207211617 root.unmount()18 }1920 useEffect(() => {21 // 在此可以执行任何带副作用操作22 let timer = setInterval(() => {23 setCount(count + 1);24 }, 1000);2526 return () => { // 在组件卸载前执行。这里相当于类组件的componentWillUnmount()27 clearInterval(timer);28 };29 }, [count]);// 含义:监测组件中的state参数,可以是多个,所以是数组,如果数组里面的任意state参数更新了,那么副作用函数就执行。如果设置为[], 回调函数只会在第一次render()后执行,就相当于类组件的componentDidMount()执行。如果不写这个参数,就相当于监测所有state,那么副作用函数只要页面更新了就会执行。举例:这里的stateValue,如果写成[count],指的就是监测count的更新,那么副作用函数会执行。30 return (31 <div>32 <div>当前结果为:{count}</div>33 <button onClick={increment}>点我加1</button>34 <button onClick={unmount}>点我卸载组件</button>35 </div>36 );37}
xxxxxxxxxx211(1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)2(2). React中的副作用操作:3发ajax请求数据获取4设置订阅 / 启动定时器5手动更改真实DOM6(3). 语法和说明: useEffect有两个参数,第二个参数的含义要弄清楚。7useEffect(() => {89// 在此可以执行任何带副作用操作1011return () => { // 在组件卸载前执行。这里相当于类组件的componentWillUnmount()1213// 在此做一些收尾工作, 比如清除定时器/取消订阅等。1415}16}, [stateValue]) // 含义:监测state参数,可以是多个,所以是数组,如果数组里面的任意state参数更新了,那么副作用函数就执行。如果指定的是[], 回调函数只会在第一次render()后执行,就相当于类组件的componentDidMount()。如果不写这个参数,就相当于监测所有state,那么副作用函数只要页面更新了就会执行。举例:这里的stateValue,如果写成[count],指的就是监测count的更新,那么副作用函数会执行。1718(4). 可以把 useEffect Hook 看做如下三个函数的组合19componentDidMount()20componentDidUpdate()21componentWillUnmount()
xxxxxxxxxx431import React, { useState, useEffect,useRef } from "react";2import root from "../../index.js"34export default function Demo() {5 const [count, setCount] = useState(0);6 7 // 定义一个ref8 const myRef = useRef()9 10 function increment() {11 setCount(count + 1);12 }1314 function unmount() {15 root.unmount()16 }1718 function show(){19 // 获取ref里面的值20 console.log(myRef.current.value)21 }2223 useEffect(() => {24 let timer = setInterval(() => {25 setCount(count + 1);26 }, 1000);2728 return () => { 29 clearInterval(timer);30 };31 }, [count]);32 return (33 <div>34 {/* ref挂载 */}35 <input type="text" ref={myRef} />36 37 <div>当前结果为:{count}</div>38 <button onClick={increment}>点我加1</button>39 <button onClick={unmount}>点我卸载组件</button>40 <button onClick={show}>点我显示input里面的内容</button>41 </div>42 );43}
xxxxxxxxxx71(1). Ref Hook 可以在函数组件中存储/查找组件内的标签或任意其它数据2(2). 语法:3import {useRef} from "react"4定义:const refContainer = useRef()5挂载:<input type="text" ref={refContainer} />6使用:console.log(refContainer.current.value)7(3). 作用:保存标签对象,功能与React.createRef()一样
xxxxxxxxxx61// 完整写法2import {Fragment} from "react"3<Fragment><Fragment>45// 简写方法6<></>
1、可以不用必须有一个真实的DOM根标签了。原来无论是类组件还是函数式组件,暴露出去的标签必须只有一个根节点,一般写成div,这个div也真实地渲染在html中,但是这些标签没有实际的意义,那么就可以使用Fragment了。
2、一般情况下写 Fragment 或 <> 都是可以的,但是 <> 不能指定任意属性,就只能这样写
<></>。而Fragment可以指定一个key属性(只能指定key属性,指定别的属性会报错),用于循环渲染的情况:<Fragment key={item.id}></Fragment>。3、如果使用Fragment,必须先引入
import {Fragment} from "react"。但使用<></>不需要引入,直接使用。
一种组件间通信方式,常用于【祖组件】与【后代组件】间通信。
一般用于【祖组件】和【孙组件】或更低层级的后代组件间的通信,因为父子组件传值使用props是最简单的。
xxxxxxxxxx2611) 创建Context容器对象。这个对象必须创建在【祖组件】和【后代组件】都访问的到的地方,比如说可以新建一个文件暴露出来,然后引入使用即可。2 const XxxContext = React.createContext() // 注意:变量名首字母大写,因为这个要作为标签名的。而react规定自定义组件的标签名首字母必须大写。3 42) 在【祖组件】中渲染【子组件】时,外面包裹XxxContext.Provider, 通过value属性给【孙组件或更低层级的后代组件】传递数据:5 <XxxContext.Provider value={数据}>6 <子组件 />7 </XxxContext.Provider>89注意:只需要在【子组件】上传递(后代组件都不需要进行传递),后代组件就都可以收到了。类似react-redux中的Provider用法。【子组件】同样可以收到value值,但是千万不要这么做,因为父子组件间传值,props是最简单的方式。10113) 后代组件读取数据:1213 //第一种方式:仅适用于类组件 14 static contextType = XxxContext // 声明接收context。这一句是固定套路,必须声明才能使用。15 this.context // 读取context中的value数据16 17 //第二种方式: 函数组件与类组件都可以18 <XxxContext.Consumer>19 {20 value => ( // value就是context中的value数据21 22 要显示的内容23 24 )25 }26 </XxxContext.Consumer>xxxxxxxxxx11在应用开发中一般不用context, 一般都用它封装react插件
xxxxxxxxxx741import React, { Component, createContext } from "react";23const MyContext = createContext();4const { Provider } = MyContext;56export default class A extends Component {7 state = {8 name: "tom",9 age: 18,10 };11 render() {12 const { name, age } = this.state;13 return (14 <div>15 <h2>我是A组件</h2>16 {/* 通过context传值给后代组件 */}17 <Provider value={{ name, age }}>18 {/* 虽然B组件可以拿到context传递过来的值,但是使用props是最简单的 */}19 <B shuxing={{name,age}}/>20 </Provider>21 </div>22 );23 }24}2526class B extends Component {27 render() {28 const { name, age } = this.props.shuxing;29 return (30 <div>31 <h2>我是B组件</h2>32 <h3>33 我的父级组件的名字是:{name},年龄是:{age}34 </h3>35 <C />36 </div>37 );38 }39}4041// 类组件读取数据42class C extends Component {43 // 声明接收Context44 static contextType = MyContext;45 render() {46 // 注意,是直接从context属性上拿的。47 const { name, age } = this.context;48 return (49 <div>50 <h2>我是C组件</h2>51 <h3>52 我的祖父组件的名字是:{name},年龄是:{age}53 </h3>54 <D />55 </div>56 );57 }58}5960// 函数式组件读取数据61function D(){62 return (63 <div>64 <h2>我是D组件</h2>65 <h3>我的祖祖父组件的名字是:66 <MyContext.Consumer>67 {68 value => `${value.name},年龄是:${value.age}`69 }70 </MyContext.Consumer>71 </h3>72 </div>73 )74}显示效果:

这里的Component指的是import {Component} from "react"这个Component。
- 只要执行setState(),即使不改变状态数据( this.setState({}) ),组件也会重新render() ==> 效率低
- 只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据 ==> 效率低
只有当组件的state或props数据发生改变时才重新render()
Component中的生命周期函数shouldComponentUpdate()总是返回true
xxxxxxxxxx101办法1:2重写生命周期函数shouldComponentUpdate()3比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false4办法2:5使用PureComponent替换Component6PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true7注意:8只是进行state和props数据的浅比较(就是比较两个数据之间的内存地址是否相同), 如果只是数据对象内部数据变了, 返回false9不要直接修改state数据, 而是要产生新数据10项目中一般使用PureComponent来优化
react中数据的更新,都要产生新的数据,不要在原有数据上进行修改,这是很重要的一点。
xxxxxxxxxx61答案:2Vue中:3使用slot技术, 也就是通过组件标签体传入结构 <A><B/></A>4React中:5使用children props: 通过组件标签体传入结构6使用render props: 通过组件标签属性传入结构,而且可以携带数据,一般用render函数属性
上面这段话是什么意思?上面这段话很突兀,因为这是老师对问题的总结。但是真正的问题是什么?是想把组件写在一起形成层级关系,然后传递组件的状态给下级组件。
比如说:下面的这段代码,是一直学到现在都在使用的标签编写方式,在一个组件里面写另一个组件的标签,就会形成组件之间的父子关系。
xxxxxxxxxx341import React, { Component } from 'react'23export default class Parent extends Component {4 render() {5 return (6 <div>7 <h2>我是Parent组件</h2>8 {/* Parent是A组件的父组件 */}9 <A />10 </div>11 )12 }13}1415class A extends Component{16 render(){17 return (18 <div>19 <h2>我是A组件</h2>20 {/* A是B组件的父组件 */}21 <B/> 22 </div>23 )24 }25}26class B extends Component{27 render(){28 return (29 <div>30 <h2>我是B组件</h2>31 </div>32 )33 }34}但是如果写成这样,可以吗?
xxxxxxxxxx361import React, { Component } from 'react'23export default class Parent extends Component {4 render() {5 return (6 <div>7 <h2>我是Parent组件</h2>8 {/* 直接在A标签的标签体里面写B标签,可以吗? */}9 <A>10 <B/>11 </A>12 </div>13 )14 }15}1617class A extends Component{18 render(){19 return (20 <div>21 <h2>我是A组件</h2>22 {/* 这里不写B组件的标签了 */}23 {/**<B/>**/} 24 </div>25 )26 }27}28class B extends Component{29 render(){30 return (31 <div>32 <h2>我是B组件</h2>33 </div>34 )35 }36}显示效果:

并不现实B组件的内容。为什么呢?因为标签体的内容是放在子组件的 this.props.children 上面的(在讲NavLink的时候有讲到),要展示出来才行。
xxxxxxxxxx261import React, { Component } from 'react'23export default class Parent extends Component {4 render() {5 return (6 <div>7 <h2>我是Parent组件</h2>8 {/* 引入自定义的组件一般使用自闭合标签,使用标签属性向子组件传值 */}9 {/* <A /> */}1011 {/* 但是如果A标签写成双标签的形式,标签体里面写一些内容,可以正常显示吗?答案是不行。为什么呢?因为标签体的内容传递给了子组件,但是挂载在 this.props.children 属性上,子组件并没有展示出来(在讲NavLink时有讲到)。 */}12 <A>Hello!!!</A>13 </div>14 )15 }16}1718class A extends Component{19 render(){20 return (21 <div>22 <h2>我是A组件</h2>23 </div>24 )25 }26}
xxxxxxxxxx341import React, { Component } from 'react'23export default class Parent extends Component {4 render() {5 return (6 <div>7 <h2>我是Parent组件</h2>8 <A><B/></A>9 </div>10 )11 }12}1314class A extends Component{15 render(){16 return (17 <div>18 <h2>我是A组件</h2>19 {/* 要展示出来才能正常显示 */}20 {this.props.children}21 </div>22 )23 }24}2526class B extends Component{27 render(){28 return (29 <div>30 <h2>我是B标签</h2>31 </div>32 )33 }34}
那么加个需求,这种方式怎么将A里面的状态传递给B呢?因为A组件的定义里面根本没有B标签,无法通过标签属性传递数据。需要写成这样:<A render={(data) => <B data={data}></B>}></A>。
xxxxxxxxxx421import React, { Component } from "react";23export default class Parent extends Component {4 render() {5 return (6 <div>7 <h2>我是Parent组件</h2>89 {/* 通过render属性来传递 */}10 <A render={(data) => <B data={data}></B>}></A>11 </div>12 );13 }14}1516class A extends Component {17 state = {18 name: "迈巴赫",19 };20 render() {21 const { name } = this.state;22 return (23 <div>24 <h2>我是A组件</h2>25 {/* 读取A组件传入的数据,这里不好理解,为什么呢?因为本身就处于A组件中,还搞个A组件传入的数据。固定套路,多写几遍。 */}26 {this.props.render(name)}27 </div>28 );29 }30}3132class B extends Component {33 render() {34 return (35 <div>36 <h2>我是B标签</h2>37 {/* 接收到A组件传递过来的数据 */}38 <h3>我接收到的A传递过来的值是:{this.props.data}</h3>39 </div>40 );41 }42}显示:

这样做的好处在哪里?可以把render={}里面的组件改成任意需要A状态的组件,就相当于Vue里面的插槽技术。这个技术非常好用,一定要会。
xxxxxxxxxx51<A>2<B>xxxx</B>3</A>4{this.props.children}5问题: 如果B组件需要A组件内的数据, ==> 做不到
xxxxxxxxxx31<A render={(data) => <C data={data}></C>}></A>2A组件: {this.props.render(内部state数据)}3C组件: 读取A组件传入的数据显示 {this.props.data}
错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面。
这种方法只适用于“生产环境”,“开发环境”会执行一下错误边界,但接着会显示报错信息。目的是让开发者知道错误的信息。
只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误
在使用子组件的父组件里面,使用生命周期函数 getDerivedStateFromError(),同时配合使用生命周期函数`componentDidCatch()。
xxxxxxxxxx141// 生命周期函数,一旦父组件的后代组件报错,就会触发2static getDerivedStateFromError(error) {3 console.log(error);4 // 在render之前触发5 // 返回新的state6 return {7 hasError: true,8 };9}1011componentDidCatch(error, info) {12 // 统计页面的错误。可以发送请求反馈给后台。13 console.log(error, info);14}案例:
xxxxxxxxxx301// Parent.js23import React, { Component } from "react";4import Child from "./Child";56export default class Parent extends Component {7 state = {8 hasError: false,9 };10 static getDerivedStateFromError(error) {11 console.log(error)12 return {13 hasError: true,14 };15 }16 componentDidCatch(error,info){17 console.log(error.info)18 }19 render() {20 return (21 <div>22 <h2>我是Parent组件</h2>23 {/* 如果子组件的生命周期函数里面产生错误,就可以捕获到,避免渲染出现问题 */}24 {25 this.state.hasError ? <h3>当前网络出现问题,请稍后再试。</h3> : <Child />26 }27 </div>28 );29 }30}xxxxxxxxxx251// Child.js23import React, { Component } from "react";45export default class Child extends Component {6 state = {7 users: null, // 这里模仿获取后台数据,本来预期是数组,但是后台返回了null或者空字符串,肯定是不能渲染的。8 };9 render() {10 return (11 <div>12 <h2>我是Child组件</h2>13 <ul>14 {15 this.state.users.map(item => {16 return (17 <li key={item.id}>{item.name}-----{item.age}</li>18 )19 })20 }21 </ul>22 </div>23 );24 }25}开发环境下显示效果:

报错信息是这样的,其实报错信息可以在控制台看到。

生产环境下是这样的,用serve库。没有报错信息,给用户很好的体验。

xxxxxxxxxx911.props:2(1).children props3(2).render props42.消息订阅-发布:5pub-sub、event等等63.集中式管理:7redux、dva等等84.context:9生产者-消费者模式
xxxxxxxxxx31父子组件:props2兄弟组件:消息订阅-发布、集中式管理3祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(开发用的少,封装插件用的多)
课程虽然学习完成了,但远远不够,因为我偶然间打开material-ui库看了一下,发现其中很多写法我还是不会的,说明很多东西还是要继续学习的,所以我为自己安排一下后续的学习过程:
1、先跟着做一个react项目,把一些项目基本点给搞清楚。
2、学习material-ui和antd库,把用法搞清楚就行了,有时间可以看一下别人写的源码,真的可以借鉴他们的写法。
3、学习单元测试,学习写文档,学习写英文注释。
4、学习react的API,把一些常见的api要用熟,并且能够解释给别人听。
5、其中穿插着可以看react设计原理和vue设计原理,我觉得差不多可以看了。
6、这个老师讲得蛮好的,抽空看一下他讲的vue3课程,如果没时间,一定要看vue-router和vuex或者pinia,这些概念其实我还很混沌。
7、觉得想学react-native了,就直接学,当然首先要把react知识全部过一遍。
可以看知乎这个问答https://www.zhihu.com/question/343314784,原因肯定是之前的class类组件使用上有些不便的地方,所以要改成这样。但是什么样的不便,我是没有经验的。
我对于这个问题的经验就是:尚硅谷这门课的老师主要讲的是class创建组件,函数创建组件只是一笔带过,但是我必须什么都要会用,因为一个公司中不会一直都是最新的技术,有项目会新写、但有项目总是要进行维护的,最新技术的引入总有一个过程,在面试的时候我就可以将新旧知识都讲一下,这样就会把我的知识都体现出来。如果方法实在太多、记不起来,也要能够查找资料来使用,不至于被卡住。总之就是别人会的我也会,别人不会的我照样会,这样才有竞争力。
可以参考知乎的这个问答https://www.zhihu.com/question/60548673,如果是大企业,最大的可能性是现场写一个小项目,比如说todolist,别人可以从中看出很多东西,我个人认为这种方式我目前是没有办法准备好的,因为没有好的习惯,也没有例子可以参照,但是呢如果有机会,就大胆上,别人可以给我提意见,我就可以改进。如果是中小企业,大概就是考察知识点,知识点需要搜索一下,最好有答案的那种。这个答案看起来不错。

react的核心语法其实比vue要少,但是这是建立在很多功能需要第三方库提供的前提下的,其实语法的数量都差不多。其次就是react的编写思想需要特别注意,因为数据是单向流动的,所以很多地方不方便。最后就是JS的功底,如果JS功底差,就根本看不懂别人的写法,更不用说自己写了。
不过这也是一个好处,正因为难,所以会的人不多,会的人不多,人的单价就高一些,那我学会react就更有价值。否则就是什么都会,一顿操作猛如虎,一看工资2500,有什么用呢?
但是这个转变是很有难度的,所以才会有很多知乎提问:为什么有vue了,还会有react?https://www.zhihu.com/question/472143922/answer/2227673336,https://www.zhihu.com/question/356637220/answer/2288975075,https://www.zhihu.com/question/270380742/answer/2925270944。
我现阶段也是不习惯,有一个回答我觉得很好,这里贴出来。可以找一些更适合用react写的项目来学习,这样会快一些。
