Advertisement

React基础知识点个人笔记整理

阅读量:

React

文章目录

    • React

      • react项目移植出现的问题
      • 1. react是什么
      • 2. React的特点:
      • react 高性能的体现:虚拟DOM
      • 3.React cli创建react项目:
      • 4. React使用:
      • 5. JSX语法:
      • jsx总结
      • 6. react组件
        • 使用函数创建组件
    • 绑定事件

      • 7.有状态组件和无状态组件
        • state的基本使用
    • setState()修改状态(数据)

      • 8. 表单处理
        • 受控组件:
    • 非受控组件

  • 9. 组件间的数据传输props

    • props的作用:
    • props的特点:
    • 组件之间通信的主要方式有三种:
      • 父组件到子组件的数据传输

      • 子组件至父组件的数据传输

      • 兄弟组件之间的数据传输

      • Context实现跨组件传递数据 * props高级

组件在声明过程中经历的三个关键阶段
* 初始阶段(挂载前)
* 更新过程
* 解散过程

复制代码
* 11\. render-props和高阶组件
* * render-props模式
  * 高阶组件
    1. 探析React核心原理
  • 关于useState()的工作原理

    • 对JSX语法转换流程进行深入解析
    • 组件生命周期管理机制的具体实现细节
    • 常见组件性能优化策略探讨
  • 13. Virtual DOM与Difference Algorithm

  • 14. React Router

    • 路由基本使用

    • 路由执行流程

      • 编ographical导航(注:此处可能存在笔误或术语不准确的情况)
        • 匹配模式描述
          • 模糊匹配模式:模糊匹配策略用于处理输入数据的不精确或不完整情况。
          • 精准匹配模式:精准匹配机制确保只有完全符合要求的数据才能通过验证。
      • 好客租房项目阶段

react项目移植出现的问题

当将我的React项目迁移到另一台电脑时,由于需要通过npm安装依赖项,但采用npm安装的方式可能会导致一些库的版本冲突问题.我尝试了多种方法才找到解决方案,简单的方法就是使用yarn进行包管理.通过这种方式,在新的环境中不会因版本冲突而导致错误.

1. react是什么

React是一个用于构建用户界面的js库,

React主要作用是来写html页面,或构建web应用

从MVC视角出发来看,在Vue架构中(或采用Vue架构时),React仅负责Vue这一层(或即仅处理前端界面的显示),而实际上并未实现前后端分离。

2. React的特点:

\1. 声明式,你只需要描述UI什么样子,跟写html页面一样

这里是用到了jsx语法创建react元素:

复制代码
    Const jsx = <div>react帅哦</div>;
    
    
      
    
    代码解读
  1. 采用组件化开发模式,在React框架中占据核心地位的是组件这一概念;即为页面中的一部分内容

\3. 学习一次,随便使用,可以开发网页,手机app、vr技术

react 高性能的体现:虚拟DOM

过去我们通过document.querySelector()的方式进行 DOM 操作。整个过程实际上是 从 HTML 文档中解析出 DOM 结构,并将其转换为变量对象来进行处理。而 React.js 则引入了一种基于 虚拟 DOM 的变量化表示(JSX 与 state 结合),这种表示方式使得所有操作 和计算都在这些虚拟变量内部完成。值得注意的是,在这种模式下,并非所有的数据修改都会立即反映到 实际 DOM 结构上;只有在最终渲染阶段才会将这些虚拟数据转化为实际 DOM 树进行渲染展示。相比于传统 DOM 方法,在 React 中完全避免了直接操作真实 DOM 树这一复杂过程,从而提升了性能表现,并且在架构设计上实现了与主流 MVC 模型的本质分离。

真实价值并非仅在于性能提升,
而是通过使用虚拟DOM可以让React元素脱离浏览器限制,
使其能够在其他Android设备及VR环境中正常运行。
在开发React应用时始终将虚拟DOM作为核心考量。

3.React cli创建react项目:

npm init react-app my-app

4. React使用:

复制代码
    导入react、react-dom包
    import React from 'react';
    import ReactDOM from 'react-dom';
    
    
    // 利用createElement()函数创建react元素,较为复杂
    
    // const title = React.createElement('h1', null, 'react是你hi');
    
    // 使用jsx的方式创建react元素
    const title = <h1>react 你好帅哦!</h1>;
    
    // 利用reactDOM进行渲染
    ReactDOM.render(title, document.querySelector('#wh'));
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

5. JSX语法:

JSX并不是标准的ECMAScript语法,他是ES的语法扩展。

必须在经过babel编译处理后,该应用才能在浏览器环境中使用.然而,在react-cli版本中已经预先配置好了相关的开发环境设置.因此,在搭建脚手架时就可以采用这种语法.

注意点:

react元素的属性名驼峰命名法

使用小括号包括jsx

复制代码
    const title = (<h1 className="w">react 你好帅哦!<span />	</h1>);
    
    
      
    
    代码解读

jsx总结

1.jsx是react的核心内容

2.jsx表示在js代码中写HTML节后,是React生命是的体现

3.使用jsx配合嵌入的js表达式、条件渲染、列表渲染可以描述任意UI结构

4.推荐使用className的方式给jsx添加样式

  1. React完全基于JS语言自身的强大能力开发用户界面(UI),而非通过"造轮子"来提升对DOM的支持能力。(这也正是React和Vue的主要区别;Vue则通过实现特定功能指令如v-for、v-model等来达到类似效果,而React则是完全依赖手动编写JavaScript脚本来进行组件渲染。)

react特色:只要能用到js的地方就绝对不会增加一个新的语法

6. react组件

使用函数创建组件
复制代码
    // 第一种创建方式,同归js的函数创建组件
    // 组件的首字母必须大写
    function Hello() {
    return (
        <div>hello,我是你 !</div>
    );
    }
    
    
      
      
      
      
      
      
      
    
    代码解读
复制代码
    // 第二种创建组件方式类组件,使用ES6的class类创建的组件
    class Hello2 extends React.Component {
    render() {
        return (
            <div>hello2,react还是你 !</div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
    
    代码解读
绑定事件
复制代码
    //在类组件中添加事件,需要用到this才能触发函数
    class Hello2 extends React.Component {
    handlePrevent(e) {
        // e为事件对象,react中的事件对象叫做合成事件(对象)
        e.preventDefault();
        console.log("react 我被阻止啦");
    }
    render() {
        return (
            <div>
                <div>hello2,react还是你 !</div>
                <a href="http://www.baidu.com" onClick={this.handlePrevent}>我是React</a>
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
复制代码
    //在函数组件中,不需要用this
    function Hello() {
    
    function handleClick() {
        console.log(1);
    }
    
    return (
        // 事件绑定
        <div onClick={handleClick}>hello,我是你 !</div>
    );
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

7.有状态组件和无状态组件


  • 函数组件被称作无状态组件,在另一方面,则是类组件被称为有状态组件。
  • 它们不具备独立的数据存储能力,并被称为无状态结构。
  • 类_component不仅具备独立的状态管理能力,并且能够动态地更新UI界面。
state的基本使用

状态(state)相当于数据,在React中属于该组件内部的所有成员 exclusive property。只有当状态被赋值时才具有实际意义 value才有意义。其值对应一个对象 instance object。这个对象能够存储多个相关的属性 value并提供对这些属性的一致访问方式 consistent access pattern。

复制代码
    class Count extends React.Component {
    /*  constructor() {
         super();
         this.state = {
             count1: 1
         }
     } */
    // 简化语法
    state = {
        count1: 0
    }
    render() {
        return (
            <div>
                有状态组件{this.state.count1}
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
setState()修改状态(数据)
  • 状态具有可变性;
    • 语法:在代码中使用this.setState命令时,请确保所传数据是需要被更新的内容。
    • 建议避免直接更改state变量中的数值。如果希望对数据进行更新,请确保所有变更都在相应的 setState 方法内部执行。
复制代码
    class Count extends React.Component {
    
    /*  constructor() {
         super();
         this.state = {
             count1: 1
         }
     } */
    // 简化语法
    state = {
        count1: 0
    }
    // 这里只能使用箭头函数(this指向这个类),如果不用箭头函数,那么里面的this指向此handleAdd函数调用者,或者使用call()修改this指向
    handleAdd() {
    //调用setState()
        this.setState({ count1: this.state.count1 + 1 });
    }
    render() {
        return (
            <div>
                有状态组件:{this.state.count1}
                <button onClick={this.handleAdd}>+</button>
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

8. 表单处理

受控组件:

步骤:

  • 向state中新增一个状态变量。
  • 为表单绑定change事件,并将对应的表单元素值设置为state变量所持之值。
  • 在React框架下,默认情况下会将state与对应于表单元素的value属性进行关联绑定。
  • 受控组件的状态会受到React控制下的表单元素变化的影响。
非受控组件

借助于ref,使用原生DOM方式来获取表单元素值。

ref:ref就是用来获取DOM或组件的一个属性

使用步骤:

  1. 生成一个 ref 对象。
  2. 将创建好的 ref 对象添加到文本框中。
  3. 利用该 ref 对象获取其对应的文本框值。
复制代码
    class Whh extends React.Component {
    constructor() {
        super();
        // 创建ref
        this.myRef = React.createRef();
    }
    
    getTxt = () => {
        console.log(this.myRef.current.value);
    }
    render() {
        return (
            //以后this.myRef就代表表这个DOM框了
            <div>
                <input type="text" ref={this.myRef}></input>
                <button onClick={this.getTxt}>点我查看文字</button>
            </div>
        )
    }
    
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

9. 组件间的数据传输props

组件是封闭的,要接收外部组件的数据要通过props来实现

prop的作用:

接收传递给组件的数据

第一步:传递数据:给组件标签添加属性

复制代码
    // 渲染APP3组件(用于学习prop相关的知识点),传递数据:name、age

    ReactDOM.render(<App3 name="react" age="23" />, document.querySelector("#prop1"))
    
    
        
        
    代码解读

第二步:接收数据:

复制代码
    class App3 extends React.Component {
    // props是个对象
    // 在类组件中使用this.props来获取传递过来的props数组,在函数组件时,在函数的参数中传递props参数
    // name = this.props.name;
    props1 = this.props.name;
    
    render() {
        console.log(this.props); //props是个数组
        return (<div>props:{this.props1}</div>)
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
props的特点
  • 组件能够接收不同类型的参数
  • props被定义为不可修改的对象,并且仅用于获取属性值
  • 注意事项:在类组件中使用构造函数时,默认情况下不会继承父类的属性,请确保将props传递给super()以避免无法获取属性的问题
复制代码
     constructor(props) {
        super(props);
        console.log(props);
    }
    
    
      
      
      
      
    
    代码解读
组件之间通信的三种方式

父组件----》子组件

子组件----》父组件

兄弟组件之间通信

父向子组件传递数据:
  • 第一步:父组件提供要传递的state数据
  • 第二步:子组件接收数据
复制代码
    class Child extends React.Component {
    render() {
        return (
            // 父向子传递第二步:从父组键接收到的props数据
            <div>{this.props.name}</div>
        )
    }
    }
    class Parent extends React.Component {
    state = {
        name: "react"
    }
    render() {
        return (
            <div>
                // 父向子传递第一步:向子组件传递来自父组件的state数据
                传递数据给子组件<Child name={this.state.name} />
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
子组件向父组件传递数据:

思路:通过使用回调机制,在父组件触发或提供给子组件后执行操作,并将需要传递的数据作为参数进行处理。

  • 第一步:父组件提供一个用于接收数据的回调函数
  • 第二步:通过props将该回调函数传递给父组件
  • 第三步:子组件将通过props接收到的函数传递给父组件以发送参数
复制代码
    class Child extends React.Component {
    
    render() {
        console.log(this.props);
        // 子向父第三步:子向父通过prop接收到的函数来向父组件传递参数
        this.props.getmsg(" ");
        return (
            // 父向子传递第二步:从父组键接收到的props数据
            <div>{this.props.name}</div>
        )
    }
    }
    class Parent extends React.Component {
    // 子向父传递数据第一步,定义回调函数:
    getChildMsg = (msg) => {
        console.log("接收到的数据", msg);
    }
    state = {
        name: "react"
    }
    render() {
        return (
            /* 父向子传递第一步:向子组件传递来自父组件的state数据 */
            // 子向父传递数据第二步,通过props传递回调函数
            <div >
                传递数据给子组件<Child name={this.state.name} getmsg={this.getChildMsg} />
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读
兄弟组件之间传递数据:

将共享状态提升到最近的公共组件中,由公共组件管理这个状态

思想:变量提升

公共组件负责:1.提供共享状态 2.提供操作共享状态的方法

要通讯的子组件只需要通过props接收状态和操作状态的方法

Context实现跨组件传递数据

使用Context实现跨组件传递数据(比如主题,语言等)

使用步骤:

该函数被用来生成一个负责管理数据源的Provider组件以及一个处理数据请求的Consumer组件。

复制代码
    const { Provider, Consumer } = React.createContext()

    
    
         
    代码解读

// 第二步:用Provider包裹,即作为父节点

复制代码
     // 第二步:用Provider包裹,即作为父节点

            <Provider>
                <div>
                    <Nodes />
                </div>
            </Provider>
            
    
    
         
         
         
         
         
         
         
    代码解读

第三步:配置相应的属性以标识待传递的数据内容,在此过程中需要明确如何将这些信息进行传输

复制代码
     <Provider value="react ">
                <div>
                    <Nodes />
                </div>
            </Provider>
    
    
      
      
      
      
      
    
    代码解读
  1. 通过Consumer组件接收数据
复制代码
    <div>
    
            <Consumer>
                {data => <div>data</div>}
            </Consumer>
        </div>
    
    
      
      
      
      
      
      
    
    代码解读
props高级

props.children属性

children 属性:代表组件标签下的子元素。当组件带有子项时, props会继承或包含该属性,其取值范围包括文本信息、React 元素实例、其他组件引用以及 JavaScript 函数等丰富类型

复制代码
    class Hello3 extends React.Component {
    render() {
        // props的children属性
        console.log(this.props.children);
        return (
            <div>
                组件的子节点{this.props.children}
            </div>
        )
    }
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

props校验

props校验允许在创建组件的时候,就指定props的类型、格式等

功能:识别组件在使用过程中因属性(属性)而导致的问题,并提供清晰的错误信息以提升组件的鲁棒性

复制代码
    import PropTypes from "prop-type"
    Hello3.propsTypes = {
    // 校验的colors元素是否出现不符合
    colors: PropTypes.array
    
    }
    
    
      
      
      
      
      
      
    
    代码解读

常见的约束规则:

array、bool、func、number、object、string、element(react元素)

必选项:isRequired

props的默认值

给一些属性设置默认值:

复制代码
    App.defaultProps = {
    pageSize:10
    } //此时就可以不用传入pageSize属性,因为已经设置了默认值
    
    
      
      
      
    
    代码解读

10. 组件的生命周期

组件的声明周期即从组件注册开始;随后会完成挂载至页面运行的任务;当不再需要该组件时,则会执行卸载操作的过程。

在各个阶段上,周期总会有相关的方法被触发;这些触发的动作即被称为周期事件钩子。

只有类组件才有生命周期,函数组件没有生命周期。

声明周期的三个阶段

创建时、更新时、卸载时。(vue中是创建前后、更新前后、销毁前后)

创建时期(挂载阶段)

当组件创建时(页面加载时)会有三个钩子函数被调用:

constructor() => render() => componentDidMount()

constructor()构造钩子函数的作用在于为状态机组件提供状态初始化支持,并负责将事件处理程序与this对象关联起来

render()钩子函数作用:,每次组件渲染时就会调用,用于渲染UI

在组件进行挂载操作时(完成后),该钩子函数将立即触发并执行相应的操作序列。这一机制主要用于在网络请求处理方面(与Vue中的处理方式存在显著差异),具体包括但不限于接收外部数据(通常会在create方法内部进行处理)以及相关的DOM元素更新等。

更新时期

组件发生更新时触发。

会触发render()、再触发componentDidUpdate();

钩子机制不仅可以用于发起Ajax请求和DOM操作,在执行setState()时则需要将其包裹在一个if条件中

卸载时期

组件在页面中消失时触发。

WillUnmount()回调函数在页面消失时被调用,并且通常用来清除某些定时器,在页面消失时执行此操作。

11. render-props和高阶组件

React组件复用基于State的操作方法(即其状态处理机制)

主要有两种方式实现以上需求:render props模式 和高级组件(HOC)

请特别注意指出:这两种方法并非新的API接口,并非基于React自身的特性采用编码技巧经过长期实践总结形成的标准模式(其中一种实现方式),这有助于提升代码的一致性和可维护性。

render-props模式

使用步骤:

构建一个Mouse组件,并在其内部实现一种能够记录和处理药物服用状态的行为规范(第一部分负责记录状态信息;第二部分处理相应的操作流程)。

​ 2.将要复用的状态作为props.render(state)方法的参数暴露到组件外部

​ 3.使用props.render()的返回值作为作为要渲染的内容

复制代码
    import React from "react"
    // render props复用模式
    // 大致使用步骤:
    
    // 第一步:创建Mouse组件
    class Mouse extends React.Component {
    
    state = {
        // 鼠标位置
        x: 0,
        y: 0
    }
    // 鼠标移动事件的事件处理程序
    handleMove = e => {
        console.log(e.clientX);
        this.setState({
            //   e为鼠标对象,e.clientX为x坐标
            x: e.clientX,
            y: e.clientY
        })
    }
    // 监听鼠标移动事件
    componentDidMount = () => {
        window.addEventListener("mousemove", this.handleMove)
    }
    render() {
        return this.props.render(this.state)
    }
    }
    class App6 extends React.Component {
    render() {
        return (
            <div>
                <h1>render props模式</h1>
                // 
                <Mouse render={(mouse) => {
                    return (
                        <p>
                            鼠标位置:{mouse.x} {mouse.y}
                        </p>
                    )
                }}></Mouse>
            </div>
        )
    }
    }
    
    export { Mouse, App6 }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

高阶组件

通过封装模式进行封装的高阶组件负责处理状态复用问题。对模块进行封装以提升其性能。优化设计使整体性能得到显著提升。

高阶组件(HOC)相当于是一个函数,接收要包装的组件,返回增强的组件。

在高阶组件内部定义一个子组件,在该子组件中实现状态复用功能,并通过props机制将状态信息传递给嵌套组件

复制代码
    import React from "react"
    
    /* 高阶组件的使用 */
    
    // 创建高阶组件,
    // 创建一个函数,名字以with开头(约定),指定函数参数,参数为一个组件名字(首字母必须大写撒)
    function withMouse(WrappedComponent) {
    // 在函数内部必须创建一个类组件。提供复用的状态逻辑代码,并返回
    class Mouse1 extends React.Component {
        // 鼠标状态
        state = {
            x: 0,
            y: 0
        }
    
        handleMove = e => {
            console.log(e.clientX);
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }
        //控制鼠标状态的逻辑
    
        componentDidMount() {
            window.addEventListener("mousemove", this.handleMove)
        }
    
        componentWillUnmount() {
            window.removeEventListener("mousemove", this.handleMove);
        }
        render() {
            // 在该组件中,渲染参数组件,同时将状态通过props传递给参数组件
            return <WrappedComponent {...this.state}></WrappedComponent>
        }
    }
    // 设置高级组件的展示名字
    Mouse1.displayName = `WithMouse${getDisplayName(WrappedComponent)}`;
    return Mouse1;
    }
    function getDisplayName(wrappedComponent) {
    return wrappedComponent.displayName || wrappedComponent.name || 'component';
    }
    
    // 用来测试高阶组件
    const Position = (props) => {
    console.log(props);
    return (
        <p>鼠标当前位置:{props.x} {props.y}</p>
    )
    }
    // 调用高级组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中
    const NewPosition = withMouse(Position);
    export { NewPosition }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

组件极简模型:(state,props)=> UI

意思是:组件内部维护状态并接收外部传递过来的props参数。经过处理后,组件内部整合这些信息以生成你需要展示的UI结构。

12. react原理揭秘

setState()的说明

setstate()是异步的。

setState()推荐语法:

复制代码
    //跟之前的不同,传入的不是对象而是一个回调函数,其中的参数state为最新的state数据
    this.setState((state,props)=>{
    return {
        count: state.count+1
    }
    })
    
    
      
      
      
      
      
      
    
    代码解读
复制代码
    //setState()其实可以传入两个回调函数,即this.setState(回调1,回调2),回调2函数会在回调1函数执行完毕之后并且页面渲染完成后立即执行
    this.setState(
    (state,props)=>{
    return {
        count: state.count+1
    }
    	},
    ()=>{
        this.log("22")
    }
    )
    
    
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

JSX语法的转化过程

JSX仅仅是createElement()方法的语法糖(语法糖就是简化语法的意思撒)

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

react元素:是一个对象,用来描述你希望在屏幕上看到的内容

jsx语法 =》 createElement() =》 React元素

组件更新机制

setState()作用:1,修改当前state 2. 更新组件(UI)

当父级组件发生重绘时

组件性能优化

  1. 减轻state

在state仅存储与组件渲染直接相关的数据;未参与渲染的数据不应包含在state;诸如定时器id等不涉及渲染的数据则应归类于this变量

复制代码
    this.timeId = setInterval(()=>{},1000)
    
    
      
    
    代码解读
  1. 避免不要的重新渲染

基于组件的动态更新机制,在触发父节点变更时会自动导致相应子节点的状态变化。然而,在某些情况下,并非所有子节点都需要频繁地进行重 render。为了解决这一问题,请在shouldComponentUpdate函数中设置适当的条件判断逻辑:当检测到无需进一步渲染的情况时(即返回false),会阻止接下来的render钩子函数执行重 render操作。

复制代码
    shouldComponentUpdate(){
    	//根据条件,决定是否重新渲染组件
    return false;
    }
    // 若返回false,则就不会再调用render()钩子函数来渲染
    render(){}
    
    
      
      
      
      
      
      
    
    代码解读
  1. 纯组件

采用纯组件模式能够应对:正确父组件的状态变化问题,在这种情况下子组件无需频繁重 render。

该组件已被更改为ParticleComponent。具体而言,在检测到 props 未发生变化时,无需重新渲染。

复制代码
    import React, { Component,PureComponent } from 'react';
    
    class Son extends PureComponent {
    constructor(props) {
        super(props);
        this.state = {  }
    }
    render() { 
        console.log('son render')
        return (<div>
            {this.props.value}
        </div>  );
    }
    }
     
    export default Son;
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

13. 虚拟DOM和Diff算法

当组件仅包含一个DOM元素需更新时,请问是否有必要将整个组件的内容重新渲染至页面?显然并非如此!因为这种方法会导致React性能显著下降。

我们仅限于对其组件中的部分变更内容进行重新渲染。这依赖于虚拟DOM与diff算法协同作用来完成组件的部分更新。

虚拟DOM:本质就是一个js对象,用来描述你希望在屏幕上看到的内容(UI)。

Diff算法:

执行过程:

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

根据虚拟DOM生成真实的DOM,然后再渲染到页面中

当state数据发生变化时,在新数据出现后会重新生成相应的虚拟DOM树。

随后与前一次获得的虚拟DOM对象进行比对,并结合差分算法(用于查找差异)来识别变化点。其中核心在于利用patch()函数来处理更新内容。

React仅在发生变化的部分进行更新(利用patch()函数处理修改后的节点),并重新呈现页面界面

复制代码
    import React from "react"
    class App7 extends React.Component {
    state = {
        count: 0
    }
    handleClick = () => {
        this.setState((state, props) => {
            return {
                count: state.count + 1
            }
        })
    }
    // render方法调用并不意味着浏览器所有元素的重新渲染
    // render方法调用仅仅说明要进行diff,对比前后的虚拟DOM,把变化的内容更新到真实DOM树上,然后根据真实dom进行渲染
    render() {
        // el只是一个虚拟dom对象,不是真实dom
        let el = (
            <div>
                {this.state.count}
                <button onClick={this.handleClick}>
                    +1
                </button>
            </div>
    
        );
        return el;
    }
    }
    //修改app7的展示名字
    App7.displayName = "App77";
    export { App7 }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

14. React路由

现代前端开发中常见的是单页面应用(SPAs),它们通常仅包含一个单独的HTML文件。这些应用凭借其良好的用户体验和较低的服务器负载需求,在当今市场中非常受欢迎。为了将多个传统网页功能整合到一个单一的网页界面中以提升效率和用户体验,前端路由技术应运而生。

前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)

前端配置包含一组规则系统。在 React 中,默认情况下会建立 URL 路径与相应组件之间的对应关系。而使用 React 路由的话,则是指导开发人员去设置各个 URL 路径与其相应的组件之间进行(组合)。

路由基本使用

使用步骤:

  1. cnpm i react-router-dom
  2. 导入路由的三个核心组件:Router/Route/Link
复制代码
    // 导入路由三大组件
    import { BrowserRouter as Router, Route, Link } from "react-router-dom"
    
    
      
      
    
    代码解读
  1. 必须使用Router组件包裹整个应用(重要)
复制代码
    const App8 = function () {
    return (
        // 使用router组件进行包裹
        < Router >
            <div>
                <h1>react路由的使用</h1>
            </div>
        </ Router >
    );
    }
    
    
      
      
      
      
      
      
      
      
      
      
    
    代码解读
  1. 使用Link组件作为导航菜单(路由入口)
复制代码
     < Router >
            <div>
                <h1>react路由的使用</h1>
                // Link组件会被渲染为a标签,to会被渲染为href属性
                <Link to="/first">点我跳转到页面1</Link>
            </div>
     </ Router >
    
    
      
      
      
      
      
      
      
    
    代码解读
  1. 使用Router组件配置路由规则和要展示的组件(路由出口)
复制代码
     {/*第四步: 利用Route组件,path属性指定路由出口 */}
                <Route path="/first" component={First} />
    
    
      
      
    
    代码解读

整个流程:

复制代码
    import React from "react"
    // 第一步:导入路由三大组件
    import { BrowserRouter as Router, Route, Link } from "react-router-dom"
    
    /** * react路由使用
     */
    const First = () => <p>页面1内容</p>
    const App8 = function () {
    return (
        // 第二步:使用Router组件进行包裹
        < Router >
            <div>
                <h1>react路由的使用</h1>
                {/*第三步: Link组件为路由入口Link组件会被渲染为a标签,to会被渲染为href属性 */}
                <Link to="/first">点我跳转到页面1</Link>
    
                {/*第四步: 利用Route组件,path属性指定路由出口 */}
                <Route path="/first" component={First} />
            </div>
        </ Router >
    );
    }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

默认路由:当页面一加载时,就会匹配的路由;

复制代码
    <Route path="/",component={Home}></Route>
    
    
      
    
    代码解读

路由的执行过程

  1. 单击Link组件中的a标签后, 会变更浏览器地址栏中的url。
  2. React路由会被地址栏url的变化所监听。
  3. React路由会遍历所有Route组件, 并应用其路径规则至URL路径部分以实现匹配。
  4. 当其路径规则能够匹配到地址栏中的pathname时, 该Route组件的内容会被展示。

编程式导航

场景:点击登录按钮,登录成功后,通过js代码跳转到后台首页。

这就需要有编程式导航:通过js代码实现页面跳转

调用函数history.push(“路径”)执行操作。其中variable history是由React Router组件提供的变量,用于获取浏览器的历史数据以供参考。

用history对象的go(-1)函数进行跳转到上一个页面 props.history.go(-1);

复制代码
    import React from "react";
    import { BrowserRouter as Router, Route, Link } from "react-router-dom"
    class Login extends React.Component {
    
    handleClick = () => {
        // 编程式路由跳转页面,通过使用history对象的push方法
        this.props.history.push("/home")
    }
    render() {
        return (
            <div>
                <p>登录页面</p>
                <button onClick={this.handleClick}>react 点我登录撒</button>
            </div>
        );
    }
    }
    const Home = (props) => {
    let handleClick = () => {
        // 用history对象的go(-1)函数进行跳转到上一个页面
        props.history.go(-1);
    }
    return (
        <div>
            <h2>我是后台哟</h2>
            <button onClick={handleClick}>点我返回登录页面</button>
        </div>
    )
    }
    
    class App9 extends react.Component {
    render() {
        return (
            <Router>
                <div>
                    <h1>这里是编程式路由撒</h1>
                    <Link to="/login">点我跳往登录页</Link>
                    {/* 点击跳往登录页面 */}
                    <Route path="/login" component={Login}></Route>
                    <Route path="/home" component={Home}></Route>
                </div>
            </Router>
        )
    }
    }
    export { App9 }
    
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

匹配模式

1.模糊匹配模式

当link组件的to属性设置为" /login "时,默认路由" / "也会随之被匹配, 其根本原因在于这种配置实现了路径模糊化处理。

在默认情况下,React路由为模糊匹配模式

模糊匹配规则:当pathname(url中的路径名)以path开头时,不仅仅匹配pathname路由,并且也会匹配path路由。

2.精准匹配模式

问题:默认路由任何情况下都会展示,如何避免这种问题?

基于默认模糊匹配转为精确匹配策略的方法:在Route组件中加入Exact属性,并使其展示页面切换至精确匹配模式。

推荐:一般都会给默认路由添加exact属性

复制代码
    {/* 给组件加入exact属性时就会使其由模糊匹配变为精准匹配模式 */}          
    <Route exact path="/" component={() => { return (<div>我是主页</div>) }}></Route>
    
    
      
      
    
    代码解读

好客租房项目阶段

项目技术栈介绍:

React核心库:react、react-dom、react-router-dom

框架或工具:create-react-app(React框架的名称为create-react-app,在Vue中称为vue-cli)

npx create-react-app “项目名字”

或者 npm init react- app “项目名字”

数据请求:axios

UI组件库:antd-mobile(antDesign-mobile)阿里提供的移动端的组件库

其他组件库:React-Virtualized作为核心功能模块、Axios+Yup提供表单管理工具、React-Spring用于实现动态效果模块

百度地图API

全部评论 (0)

还没有任何评论哟~