React学习笔记

309 阅读5分钟

旧的生命周期方法

  1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    1. constructor()
    2. componentWillMount()
    3. render()
    4. componentDidMount()
    
  2. 更新阶段:由组件内部this.setState()或父组件render触发
    /**
    * 0. componentWillReceiveProps()会在父级重新渲染调用
    */
    1. shouldComponentUpdate()
    2. componentWillUpdate()
    3. render()
    4. componentDidUpdate()
    
  3. 卸载组件:由ReactDom.unmountComponentAtNode()触发
    1. componentWillUnmount()
    

总结:旧的废弃了componentWillReceiveProps,componentWillMount,componetnWillUpdate,新增 static getDerivedStateFromProps(props, state),getSnapshotBeforeUpdate

新的生命周期

  1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
    1. constructor()
    2. getDerivedStateFromProps
    3. render()
    4. componentDidMount()
    
  2. 更新阶段:由组件内部this.setState()或父组件重新render触发
    /**
    * 0. componentWillReceiveProps()会在父级重新渲染调用
    */
    1. getDerivedStateFromProps
    2. shouldComponentUpdate()
    3. render()
    4. getSnapshotBeforeUpdate
    5. componentDidUpdate()
    
  3. 卸载组件:由ReactDom.unmountComponentAtNode()触发
    1. componentWillUnmount()
    

JSX嵌入变量

- 当变量是Number,String,Array类型时,可以直接显示
- 当变量是null,undefined,boolean类型时,内容为空

React-router-dom 路由

    1.activeClassName 设置激活路由样式
    2.路由组件:接收到三个固定的属性
        history:
            go: fn go(n)
            goback: fn goback()
            goForward: fn goForward()
            push: fn push(path,state)
            replace: fn replace(path,state)
        location:
            pathname: "/about"
            search: ""
            state: undefined
        match:
            params: {}
            path: "/about"
            url: "/about"

Switch的使用

Switch 包裹 标签可以提高路由匹配效率(单一匹配)

路由的严格匹配与模糊匹配

    1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)
    2.开启严格匹配:<Route exact={true} path="/about" component={About}/>
    3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由

Redirect的使用

    1.一般写在所有路由注册的最下方,当所有路由都无法匹配时,挑战到Redirect指定的路由
    2.具体编码
    <Switch>
        <Route path="/about" component={About}/>
        <Route path="/home" component={Home}/>
        <Redirect to="/about"/>
    </Switch>

向路由组件传递参数

    1.params参数
        路由链接(携带参数):<Link to='/demo/test/tom/18'>详情</Link>
        注册路由(声明接收):<Route path='/demo/test/:name/:age" component={Test}/>
        接受参数: const {id,title} = this.props.mathch.params
    2.search参数
        路由链接(携带参数):<Link to='/demo/test?name=tom&age=18'>详情</Link>
        注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
        接收参数: const {search} = this.props.location
        备注: 获取到的search是urlencoded编码字符串,需要借助querystring解析
    3.state参数
        路由链接(携带参数):<Link to={{path:'/demo/test'},state:{name:'tom',age:18}}}>详情</Link>
        注册路由(无需声明,正常注册即可):<Route path="/demo/test" component={Test}/>
        接收参数:const { state } = this.props.location
        备注:刷新也可以保留住参数,参数保存在history对象上,清空缓存失效

给一般组件传递路由组件的api

    import {Component} from 'react'
    import {withRouter} from 'react-router-dom'
    
    class Header extends Component
    
    export default withRouter(Header)
    
    通过withRouter给普通组件包裹下

BrowserRouter与HashRouter的区别

1.底层原理不一样: BrowserRouter使用的是H5的histroy API,不兼容IE9及以下版本。 HashRouter使用的是URL的哈希值 2.path表现形式不一样 BrowserRouter的路径中没有# HashRouter的路径中包含# 3.刷新后对路由state参数的影响 BrowserRouter没有任何影响。因为state保存在history对象中 HashRouter刷新后会导致路由state参数的丢失

Hooks

useEffect

  1. 会在首次render的之后必定执行一次
  2. 如果返回了函数,那么在下一次render之前或组件unmount之前必定会运行一次返回函数的代码
  3. 如果指定了依赖数组,且不为空,则当数组里的每个元素发生变化时,都会重新运行一次
  4. 如果数组为空,则只在第一次render时执行一次
  5. 如果在useEffect中更新了state,且没有指定依赖数组,或state存在与依赖数组中,则会造成死循环

useState

  1. 函数式组件每次重新渲染时 [count,setCount] = useState(1), setCount都是全相等

Redux

  1. 通过reduxcreateStore(reducer)创建一个store
  2. 通过store.dispatch派发action
  3. 通过store.getState() 获取reducer的state
  4. 通过store.subscribe(fn)订阅派发事件,,state变化触发更新

函数式组件

  1. 函数式组件会重新执行,方法内的局部变量(函数,对象)不全等

Generator

    // 2.生成器函数的定义
    // 生成器函数
    function* foo() {
      console.log("111");
      yield "Hello";
      console.log("222");
      yield "World";
      console.log("333");
      yield "coderwhy";
      console.log("444");
    }

    // iterator: 迭代器
    const result = foo();
    console.log(result);

    // 3.使用迭代器
    // 调用一次next, 就会消耗一次迭代器
    // const res1 = result.next();
    // console.log(res1);
    // const res2 = result.next();
    // console.log(res2);
    // const res3 = result.next();
    // console.log(res3);
    // const res4 =result.next();
    // console.log(res4);

    // 4.生成器函数中代码的执行顺序

    // 5.练习: 定义一个生成器函数, 依次可以生成1~10的数字
    function* generateNumber() {
      for (var i = 1; i <= 10; i++) {
        yield i;
      }
    }

    // const numIt = generateNumber();
    // console.log(numIt.next().value);

    // 6.generator和Promise一起来使用
    function* bar() {
      console.log("1111");
      const result = yield new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("Hello Generator");
        }, 3000);
      });
      console.log(result);
    }

    const it = bar();
    it.next().value.then(res => {
      it.next(res)
    })

记录

setState同步异步

  1. setState在合成时间和生命周期中是异步的,这里说的异步其实是批量更新,达到了优化性能目的 2.setState在setTimeout和原生事件中是同步的 3.在setState(fn,callback)中是同步的

React开发项目遇到问题

页面打开播放音乐报错<audio/>标签,不允许打开网页时就播放音乐

image.png

/**
* audio标签事件 
* onEnded 当歌曲播放完的时候
* onTimeUpdate 当歌曲播放时的时间 毫秒
* audio.currentTime 当前歌曲播放时间 毫秒
*/
const [isPlaying, setIsPlaying] = useState(false)

useEffect( () => {
    audioRef.current.src = getPlaySong(currentSong.id)
    audioRef.current.play().then(res=>{
      setIsPlaying(true)
    }).catch( err=> {
      setIsPlaying(false)
    })
  },[currentSong])
  
const playMusic = useCallback(() => {
    setIsPlaying(!isPlaying)
    isPlaying ? audioRef.current.pause() : audioRef.current.play()
  },[isPlaying])

Css Model小技巧

TSX中引用css类选择或者id选择器,需要安装插件typescript-plugin-css-modules

npm install typescript-plugin-css-modules -D

然后在tsconfig.json中添加配置

"compilerOptions":{
    "noImplicitAny": false,//参数没有设置类型,自动为any类型
    "plugins": [
          {
            "name": "typescript-plugin-css-modules"
          }
        ]
}

同时在 vscode 当前项目根目录下新建 .vacode/settings.json,内容如下

{
    "typescript.tsdk": "node_modules/typescript/lib",
    "typescript.enablePromptUseWorkspaceTsdk": true
}

react-i18next

npm install react-i18next i18next --save

Redux中间件公式

const middleware = (store) => (next) => (action) =>{}, 如下,打印日志的中间件

import { Middleware } from "redux"

const actionLog: Middlleware = (store) => (next) => (action) => {
    console.log("state 当前 ", store.getState())
    console.log("fire action ", action)
    next(action)
    console.log("state 更新", store.getState())
}

在JSX中加载html

dangerousllySetInnerHTML

<div dangerouslySetInnerHTML={{__html:'<span>abc<span>'}}></div>

centos docker 安装

//安装 yum 源
yum update
yum install epel-release -y
yum clean all
yum list

yum install docker-io -y

systemctl start docker

docker info //查看启动结果

docker 阿里云镜像加速器

  1. 打开登录阿里云官网,并登录
  2. 点击右上角控制台
  3. 打开产品与服务,选择容器服务镜像

image.png 4. 点击侧边栏镜像工具:镜像加速器,按照操作文档来即可

image.png