React 入门笔记

React 的历史与应用

React 是一个 JavaScript 库

React : A JavaScript library for building user interfaces.   ——Jordan Walke
  • 应用场景:

    • 前端应用开发,如 Facebook、Instagram、Netflex 网页版
    • 移动原生应用开发,如 Instagram、 Discord、Oculus
    • 结合 Electron,进行桌面应用开发
    • 3D开发:react-three-fiber
  • React 的历史

    • 2010年:Facebook 在其 php 生态中,引入了 xhp 框架,首次引入了组合式组件的思想,启发了后来的 React 的设计
    • 2011年:Jordan Walke 创造了 FaxJS ,也就是后来的 React 原型
    • 2012年:在 Facebook 收购 Instagram 后,该 FaxJS 项目在内部得到使用,Jordan Walke 基于 FaxJS 的经验创造了 React
    • 2013年:React 正式开源,在2013 JSConf 上 Jordan Walke 介绍了这款全新的框架
    • 2014年:生态大爆发,各种围绕 React 的新工具/新框架开始涌现

React 的设计思路

  • 原生 JavaScript UI 编程痛点

    • 状态更新,UI 不会自动更新,需要手动调用 DOM 进行更新
    • 欠缺基本的代码层面的封装和隔离,代码层面没有组件化
    • UI 之间的数据依赖关系需要手动维护,如果依赖链路过长会引起回调地狱 Callback Hell
  • 响应式与转换式

    • 转换式系统:给定输入求解输出,例如编译器、数值计算
    • 响应式系统:监听事件,消息驱动,例如监控系统、UI 界面
  • 响应式系统

    事件 -> 执行既定回调 -> 状态变更
  • 响应式的前端 UI 编程:

    事件 -> 执行既定回调 -> 状态变更-> UI 更新
  • React 响应式编程特点

    • 状态更新,UI 自动更新
    • 前端代码组件化,可复用,可封装
    • 状态之间的互相依赖关系,只需声明即可
  • 组件化

    • 组件是组件的组合/原子组件
    • 组件内部拥有状态,外部不可见
    • 父组件可将状态传入组件内部
  • 组件状态归属问题

    • 共享状态归属于两个组件节点的最近祖先节点,即状态提升
    • React 是单向数据流,永远是父组件给子组件传递状态,子组件只能调用函数更改状态
    • 使用状态管理库如 redux 解决状态不合理提升的问题
    • 如何修改 DOM : 将 JSX 文件转义为 JS 文件、利用虚拟 DOM 树和 diff 算法来更新 DOM
  • 组件设计

    • 组件声明了状态和 UI 的映射
    • 组件有 props 和 state 两种状态
    • 组件可由其他组件拼装而成
  • 组件特点:

    • 组件内部拥有私有状态 state
    • 组件接受外部的 props 状态提供复用性
    • 根据当前的 state 和 props 返回一个 UI

React Hooks 的写法

  • 最常用的两个 Hooks 是 useState 和 useEffect
  • useState:传入一个初始值,返回一个状态,和set该状态的函数,用户可以通过调用该函数,来实现状态的修改

    import React, { useState } from 'react';
    
    const Example = () => {
    const [count, setCount] = useState(0);
    return (
      

    You clicked {count} times

    ); }
  • useEffect:两个参数,一个是要执行的函数,一个是依赖项数组(可以不传依赖性)。有副作用的函数要传入到 useEffect 来执行。副作用表示除了单纯的计算之外还要做其他的事情,比如网络请求、更新 DOM 、localStorage 数据等。

    import React, { useState, useEffect } from 'react';
    const Example = () => {
    const [count, setCount] = useState(0);
    // 使用一个副作用,传入的[count]数组使得此副作用只有当count变量改变时才会被调用
    useEffect(() => {
      // 副作用:Update the document title using the browser API
      document.title = `You clicked ${count} times`;
    }, [count]);
    
    return (
      

    You clicked {count} times

    ); }
  • Hooks 的使用规则:

    • 只在最顶层使用 Hooks,不要在循环,条件或嵌套函数中调用 Hooks,确保总是在 React 函数的最顶层以及任何 return 之前调用他们。
    • 只在 React 函数中调用 Hooks,不要在普通的 JavaScript 函数中调用 Hooks,可以在 React 的函数组件中调用 Hooks,可以在自定义 Hooks 中调用其他 Hooks

React 的实现

  • React 是不能直接在浏览器中运行的,有这些问题

    • React 的 JSX 语法不符合 JavaScript 标准语法
    • 返回的 JSX 发生改变时,如何更新 DOM
    • state/props 更新时要重新触发 render 函数
  • 如何实现

    • 将 JSX 文件转译(transpile)成 JS 文件
    • 利用虚拟 DOM 树

      • 真实 DOM (Document Object Model)是浏览器创建页面的文档对象模型
      • 虚拟 DOM 树是在 JS 内存中维护的一个对象,具有和 DOM 类似的树状结构,并和 DOM 可以建立一一对应的关系
      • 利用虚拟 DOM 就不用操作真实 DOM 提供的 API 来修改 DOM 了:它赋予了 React 声明式的 API,告诉 React 希望让 UI 是什么状态,React 就确保 DOM 匹配该状态,前端工程师便可以从属性操作、事件处理和手动 DOM 更新这些操作中解放出来
    • 利用 Diff 算法

      • 状态改变时,先更新虚拟 DOM 树,而不是直接更新 DOM 树,通过 Diff 算法,求出最少要更新的节点,然后再去更新真正的 DOM 树
      • 完美的最小Diff 算法,需要O(n^3)的复杂度;牺牲理论最小 Diff,换取时间,得到了O(n)复杂度的算法

        不同类型元素 同类型元素 同类型的组件元素
        替换 更新 递归

React 状态管理库

  • 核心思想:将状态抽离到 UI 外部进行统一管理
  • 状态管理库的弊端:UI 依赖于外部的一个状态管理库会降低代码的复用性,因此状态管理库总是出现在业务代码中
  • 常见状态管理库:redux、xstate、mobx、recoil
  • 状态机:当前状态收到外部事件,迁移到下一个状态

你可能感兴趣的:(前端react.js)