react学习笔记二:react原理

一、react原理的初步了解:

1)setState()的说明

2)JSX语法转化

3)组件更新机制

4)组件性能优化

5)虚拟DOM和diff算法

1、setState()的说明

作用:修改state,更新UI

1)setState()异步更新数据

this.state = {
  a: 0
}

this.setState({
  a: this.state.a + 1
})

console.log(this.state.a)

2)多次调用setState(),合并成一次render,提高页面渲染性能;

下面的setState虽然调用两次,但是第二次不能依赖第一次的结果做处理,因为是异步更新

this.state = {
  a: 0
}

this.setState({
  a: this.state.a + 1  // 0 + 1
})

this.setState({
  a: this.state.a + 1   // 0 + 1
})

console.log(this.state.a)}  // 0

render() {
  return (
    <p>fhdufhud</p>
  )
}

下面的语法也是异步更新,但是在回调中拿到的是最新的state

this.state = {
  a: 0
}

this.setState((state, props) => {
  return {
    a: state.a + 1  // 0 + 1
  }
})

this.setState((state, props) => {
  // state是更新后的数据
  return {
    a: state.a + 1  // 1 + 1
  }
})

console.log(this.state.a)}  // 0

render() {
  return (
    <p>fhdufhud</p>
  )
}

3)setState第二个参数fn

this.setState((state, props) => {}, () => {console.log('在状态更新之后,立即执行某个操作')})

2、JSX语法转化过程

1)JSX是createElement的语法糖

2)JSX语法被插件@babel/preset-react编译为createElement()方法

3)React元素:对象,描述在DOM上看到的内容

 3、组件更新机制

setState()两个作用:修改state、更新UI

过程:父组件重新渲染,也会重新渲染当前组件的子组件

4、组件性能优化

1)减轻state:只存储跟组件渲染相关的数据,不用做渲染的数据不放在state中,因为state里面的数据更新会触发组件的render

对于在多个方法中公用的变量,但是不用于渲染,则放在this中

2)避免不必要的重新渲染

组件更新机制:父组件重新渲染,也会重新渲染当前组件的子组件

问题:子组件没有任何变化也会更新

解决方式:使用钩子函数shouldComponentUpdate(nextProps, nextState)

作用:返回true表示要渲染,false不需要渲染

const { threadId } = require("worker_threads");

shouldComponentUpdate(nextProps, nextState) {
   //  更新值和当前值做比较
  return nextState.number !== threadId.state.number
}

3) 使用纯组件:React.pureComponent

纯组件React.PureComponent与React.component功能相似

区别:内部实现了shouldComponent钩子,不需要手动比较

原理:纯组件内部分别对比前后两次props  state的值,决定是否重新渲染组件

说明:纯组件内部的对比是shallow compare

对于引用类型只比较对象的地址是否相同:注意如果props或者state中属性值为引用类型,需要创建新数据,不要直接修改原数据

const { threadId } = require("worker_threads")

// 对于objetc,创建新数据
const newObj = {...this.state.obj, number: 2}
this.setState({
  obj: newObj
})

// 对于array:不要用push pop  unshift shift等直接修改原数组的方法
// 用返回新数组的方法:concat  slice map 等
this.setState({
  list: [...this.state.list, {新数据}]
})

5、虚拟DOM和diff算法

1)更新视图思想:state变化就重新渲染视图

2)理想状态:部分更新,只更新变化地方

3)虚拟DOM本质上上JS对象

执行过程

1)初次渲染,React会根据初始state,创建虚拟DOM对象(树)

2)根据虚拟DOM生成真正的DOM,渲染到页面

3)当数据变化后(setState()),重新根据新的数据,创建新的虚拟DOM对象(树)

4)与上次得到的虚拟DOM对象,用diff算法对比,得到需要更新的内容

5)最后,React只将变化的内容更新(patch)到DOM中,重新渲染到页面

diff算法触发时机

1)组件render后,根据状态和JSX结构,生成虚拟DOM对象

2)diff算法发生在render之后

虚拟DOM的真正价值

虚拟DOM让React脱离了浏览器环境的束缚

二、路由基础学习

1)React路由的作用

2)react-router-dom的基本使用

3)路由的执行过程

4)使用编程式导航跳转路由

5)默认路由

6)React路由的匹配模式

1、React路由的作用

前端路由功能:让用户从一个视图导航到另外一个视图

前端路由是一套映射规则,是URL路径与组件的对应关系

使用React路由就是配置路径和组件(配对)

2、react-router-dom的基本使用

基本使用

1)安装路由包:react-router-dom

npm i react-router-dom

2) 导入路由三个核心组件Router/Route/Link

import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

3) 使用Router组件包裹整个应用

<Router>
  <div className="app"></div>
</Router>

4) 使用Link组件作为导航菜单(路由入口)

<Link to="/first">page one</Link>

5) 使用Route组件配置路由规则、要展示的组件(路由出口)

const First = () => (<p>page one content</p>)

<Router>
  <div className="app">
    <Link to="/first">page one</Link>
    <Route path="/first" component={First}></Route>
  </div>
</Router>

常用组件说明

1)Router组件“包裹整个应用,一个React应用只需要用一次

2)两种常用Router:HashRouter和BrowserRouter

3)hashRouter:使用url的hash值实现

4)BrowserRouter(推荐使用这种模式):使用H5的的history API实现

5)Link组件:用于指定导航连接(a标签):Link被编译成a,在BrowserRouter中,to相当于location.pathname

6)  Route组件:指定路由展示组件相关信息,path路由规则,component:展示的组件

3、路由的执行过程

1)点击Link组件(a标签),修改浏览器地址栏中的url

2)React路由监听到地址栏url的变化

3)React路由内部遍历所有的Route组件,使用路由规则(path)与pathname比较

4)当路由规则path能够匹配地址栏中的pathname,则展示该Route组件内容

4、编程式导航

编程式导航:通过js代码实现页面跳转

this.props.history.push('/home')

history是React路由提供的,用于获取浏览器历史记录相关信息

1)push(path):跳转到某个页面,path表示跳转路径

2)go(n):前进或后退到某个页面,(-1后退到上一页面,1前进到下个页面)

5、默认路由

默认路由:表示进入到页面时就会匹配的路由

1)默认路由path为:/

<Route path="/" component={Home}></Route>

6、匹配模式

1)模糊匹配模式

问题:当Link组件的to属性值为"/login",默认路由也会匹配上

原因:默认情况下React路由是模糊匹配模式

模糊匹配规则:只要pathname以path开头就会匹配成功

import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const Home = () => (<p>默认页面</p>)
const Login = () => (<p>登录页面</p>)

const App = () => {
  <Router>
    <div className="app">
      {/* 点击这里,会将Home  Login都渲染 */}
      <Link to="/login">登录页面</Link>
      {/* 默认路由 */}
      <Route path="/" component={Home}/>
      <Route path="/login" component={Login}></Route>
    </div>
  </Router>
}

2)精确匹配

定义:给Route组件添加属性exact属性,就会变成精确匹配

精确匹配:当path和pathname完全匹配才会展示该路由

{/* 默认路由 精确匹配*/}
<Route exact path="/" component={Home}/>

给默认路由添加exact属性

路由基础总结

1)React路由可以有效管理多个视图(组件),实现SPA

2)Router组件包裹整个应用,只用一次

3)Link组件是入口,Route组件是出口

4)通过props.history实现编程式导航

5)默认模糊匹配,添加exact变精确匹配

6)React路由的一切都是组件

猜你喜欢

转载自blog.csdn.net/tangxiujiang/article/details/114459864