React基础

1、渐进式MVC框架,专注视图层,单向数据流
2、可以使用create-react-app脚手架进行搭建,内部集成webpack,使用npm eject可以暴露出配置,此过程不可逆
3、使用jsx语法进行页面的编写,react dom在渲染所有输入时,会将输入项进行转义,所有内容在渲染前都会被转义称为字符串,这样可以有效防止XSS(跨站脚本)攻击
4、babel会将jsx转译成为一个React.createElement()的函数调用
5、仅使用 React 构建的应用通常只有单一的根 DOM 节点。如果你在将 React 集成进一个已有应用,那么你可以在应用中包含任意多的独立根 DOM 节点。将所要渲染的元素传入ReactDOM.render()中
6、定义组件的方式有两种,一种是之前的通过class方式进行编写,一种是v16之后新增的函数编写,也就是React-Hook
  * 在class组件中常用的方法
    * constructor 此class组建的构造函数,常在这里进行数据的初始化,需要注意的是,如果使用props,必须在此处进行一项super(props)的操作,不然会报错
    * render 此方法用来渲染组件的内容,该方法返回值就是这个class所要输出渲染的内容
    * 在class组件中可以使用react的内置生命周期函数进行操作,常用的生命周期函数见下文
  * 函数组件
    * 函数组件在v16之后也可以进行状态管理,使用hook进行相关操作
    * 在函数组件中不存在生命周期
    * 写法较于class组件更简便
7、常用的生命周期函数 - class组件
  * 挂载阶段 - 当组件实例被创建并插入DOM时,生命周期调用如下
    * constructor()
    * static getDerivedStateFromProps()
    * render()
    * componentDidMount()
  * 更新阶段 - 当组件的state或者props发生变化时会触发组件更新
    * static getDerivedStateFromProps()
    * shouldComponentUpdate()
    * render()
    * static getSnapshotBeforeUpdate()
    * componentDidUpdate()
  * 卸载阶段 - 组件从dom中移除时触发
    * componentWillUnmount
  * 错误处理 - 当渲染过程、生命周期或者子组件的构造函数抛出错误的时候触发
    * static getDerivedStateFromError()
    * componentDidCatch()
  * 生命周期函数详解
    -- 常用 --
    * render()
      * 此函数是class组件中唯一必须要实现的方法
      * 函数应该是纯函数,在state或者props不改变的情况下,每次调用应该返回相同的结果
      * 当该方法被调用时,会检查state或者props的变化并作出相关的返回
      * shouldComponentUpdate返回false的时候不会触发render方法的执行
    * constructor(props)
      * 如果不初始化state或者不进行方法的绑定,不需要为React组件实现构造函数
      * 在挂载前执行,如果React.component子类实现构造函数时没有进行super(props)的调用,this.props在构造函数中会出现未绑定的bug
      * 在构造函数使用this.state = {} 进行state的初始化,不可在此处进行setState的操作
      * 避免在constructor中进行存在副作用的操作或者订阅,相关操作应该移到componentDidMount中进行操作
      * 避免将this.props的值直接赋值给this.state
    * componentDidMount()
      * 组件挂载结束后调用
      * 依赖于dom节点的操作应该在此处,或者ajax请求
      * 在此处添加订阅函数,同时在componentWillUnMount进行订阅的取消
    * componentDidUpdate(prevProps, prevState,snapshot)
      * 在更新后会被立即执行,首次渲染不会执行
      * 在该声明周期函数中使用setState需要注意的是必须在一个条件判断语句中,否则会死循环
      * 如果组件实现了getSnapshotBeforeUpadte()生命周期--不常用,那么这个函数的返回值会作为第三个参数传递给componentDidUpdate,否则此参数为undefined
    * componentWillUnmount()
      * 组件卸载之前执行
      * 通常在此处进行订阅的取消或者网络请求的关闭
      * 不要在此处调用setState,因为组件被卸载,不会重新渲染
    -- 不常用 --
    * shouldComponentUpdate(nextProps, nextState)
      * 根据该函数的返回值判断组件是否需要进行更新操作,会在props或者state变化时,在更新之前执行
      * 首次渲染或者forceUpdate()时不会触发
      * 该方法仅作为性能优化的方式,不要企图使用该方法阻止渲染
      * 不要在该方法中进行深层比较或者JSON.stringfy(),这样非常影响效率
      * 可以将 this.props 与 nextProps 以及 this.state 与nextState 进行比较,并返回 false 以告知 React 可以跳过更新。请注意,返回 false 并不会阻止子组件在 state 更改时重新渲染。
    * static getDerivedStateFromProps(props, state)
      * 在render之前会触发
      * 返回一个对象更新state
      * 常用于state的值在任何情况都依赖于props的情况下
    * getSnapshotBeforeUpdate(prevProps, prevState)
      * 在最近的一次渲染之前进行调用
      * 在dom发生变化之前传回信息,此方法的任何返回值会传递给componentDidUpdate
      * 常用于需要实时获取dom信息的场景,如滚动位置
      * 应该返回snapshot值或者null
    * Error boundaries
      * 在子组件实例的任何位置捕获错误,展示降级UI
      * 如果在class组件中使用componentDidCatch(error, info)或者static getDerivedStateFromError(error),那么这个组件就会成为一个error boundaries
      * 不要用他来做流程控制
    -- Unsafe,未来可能会被弃用的生命周期 --
      * UNSAFE_componentWillMount()
      * UNSAFE_componentWillReceiveProps(nextprops)
      * UNSAFE_componentWillUpdate()
8、常用api
  * setState(updater,[callback])
    * 更新state的唯一方法
this.setState((state, props) => {
return {counter: state.counter + props.step};
}, () => {});
View Code
    * 不要再setState之后立即使用state数值,因为state的更新可能是异步的
    * 在react的方法或者生命周期函数中表现为异步,在原生方法或者setTimeout中表现为同步
    * React会将多次调用的setState合并
  * forceUpdate()
    * component.forceUpdate(callback)
    * 默认情况下,当组件的 state 或 props 发生变化时,组件将重新渲染。如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。
  * defaultProps
    * 设置class接受的props初始值
class A extends React.Component{}
A.defaultProps = {something: init}
View Code
9、React的事件处理
  * react使用小驼峰写法来定义事件
  * 需要将事件函数传递给事件,而不是字符串
  * 在React中无法使用return false;来阻止默认行为,必须显示的调用preventDefault()
  * 事件绑定
    * 通过 onClick = {this.clickFnc} 使用的方法必须要在constructor中进行绑定
this.clickFnc = this.clickFnc.bind(this)
View Code
    * 使用箭头函数不需要绑定
onClick = {() => this.clickFnc()}
View Code
  * 事件处理函数参数
onClick = {() => this.clickFnc(id, e)};
onClick = {this.clickFnc.bind(this, id)};
View Code
    * 这两种情况是等价的,React会将事件对象作为第二个参数进行传递,不同的是使用箭头函数必须显示的进行传递,普通函数会被隐式传递
10、列表渲染
  * 渲染列表时需要为每一项增加key值作为唯一标识
  * key会告诉React那些组件发生了变化
  * key要放在数组的就近上下文
11、导入导出
  * 使用export default进行默认导出
  * 使用export A {}进行批量导出
  * 使用import A from ''获取默认导出的文件
  * 使用import { A } from ''获取批量导出,获取到的是一个对象
  * 可以使用React.lazy进行动态引入
 const SelfComponent = React.lazy(() => import('...'))
View Code
    * 使用React.lazy引入的文件必须要使用Suspense组件包裹,可以包裹多个懒加载组件
    * 使用方法:<Suspense fallback={loading...}></Suspense>,fallback接受的是一个在加载阶段渲染的React元素
12、Context
  * Context提供了一种全局的数据共享,而不是只能通过props层层传递
  * 常见于用户的身份信息、网站主题、网站语言等
  * 基本用法 - 仅展示class组件中的context用法,不涉及react-hook
const ThemeContext = React.createContext(...) // 参数为要传递的数值
<ThemeContext.Provider value="..."></ThemeContext.Provider> // 使用ThemeContext.Provider包裹要接受Context数值的组件
let value = this.context; // 指定 contextType 读取当前的 theme context。
<Button theme={value}></Button>
View Code
  * createContext()会提供一个Proider跟一个Consumer属性
    * 使用Provider包裹需要参数传递的组件
    * 在子组件中使用Consumer进行组件包裹,Consumer接受一个函数{value => ...}
  * value 值为父组件传递的context数值
    * 返回一个渲染的reactDom
  * Context.displayName
    * 接受一个字符串作为参数,React.devtools使用该参数来确定context要显示的内容
13、Refs转发
  * 在React中可以使用ref来获取dom元素,访问dom节点或者在render中创建的react元素
  * 常见用法
const ref = React.createRef()
// 父组件要引用子组件的元素,需要用到ref转发
<Test ref={ref}></Test>
const Test = React.forwardRef((props, ref) => (<div ref={ref}></div>))
View Code
  * 挂载结束后可以通过ref.current指向该dom元素
  * 常用来管理焦点、触发动画、文本管理,媒体播放
14、Fragments
  * 允许一个组件返回多个元素,但是不需要多余的节点
    * <React.Fragments>....</React.Fragments>
  * 渲染到页面的时候只会渲染内部的元素,不会渲染Fragments
  * 可以简写成为<></>
  * 常用于列表的渲染,但是不需要在列表的顶层加父级元素
15、高阶组件 -- HOC
  * 指的是接收组件作为参数,返回新组件的函数
  * 可用来扩展组件的功能,常用于组件的复用
  * 对原组件不做修改,HOC是纯函数,不存在副作用
  * 将不相关的props传递给被包裹组件而不是弃用用
  * 在render方法中不要使用HOC,因为会每次创建一个全新的组件
  * 复制静态方法
  * 使用React.forwardRef进行ref的传递
16、性能优化
  * 使用构建工具,create-react-app自带webpack构建
  * 虚拟化长列表,例如react-window
  * 使用shouldComponentUpdate(np,ns)进行渲染优化,默认总是返回true,可以使用React.PureComponent代替shouldComponentUpdate,它将当前与之前的props与state进行浅比较覆写了shouldComponentUpdate
17、Portals
  * 提供了一种将子节点渲染到父组件之外的DOM节点的解决方案
  * React.createPortal(child,container)
    * child -- 任何可以渲染的dom节点
    * container -- DOM元素
18、Profiler
  * 用来测量React渲染的代价
    * <Profiler id={string} onRender={callback}></Profiler>
  * 存在额外的性能开销,不建议在生产环境使用
19、协调
  * 设计动机
    * 基于Dom树的变化进行比较,得出最小的更新操作次数
    * 在以下的前提下提出一个O(n)的算法
    * 不同的元素构建不同的树
    * 通过设置key属性,得到哪些元素是修改过的从而不需要全局更新树
  * Diff算法
    * 首先比较两棵树的根节点
    * 当根节点为不同类型的元素时,会摧毁之前的树,新建一个新的
      * 比如当元素类型发生变化时,a->p,span->img等
  * 当根节点是相同的元素时,React会保留节点,仅比较属性的变化
  * 处理完当前节点后,会对子节点继续递归处理
  * 引入key值帮助react发现需要更新的元素
    * key建议使用id,如果使用index作为key的话,在列表顺序需要重新排序的时候,diff会变慢
    * 需要具备稳定、可预测、列表内唯一的特性
20、Render Props
  * 将渲染内容传递的一种方式
<A render={(data) => <B data={data} />}></A>
A.render {this.props.render(this.state)}
B.render {this.props.data}
View Code
  * 任何被用于告知组件需要渲染什么内容的函数 prop 在技术上都可以被称为 “render prop”
  * 可以使用Render prop实现大多数的HOC
  * 由于是在render是定义了渲染函数,所以每次渲染的时候prop都是不同,因此不建议同PureComponent一起使用
21、静态类型检查
  * PropTypes
import PropTypes from 'prop-types'
class A extends React.Component{
...
this.props.name
this.state.count
...
}
A.propTypes = {
name: PropTypes.string,
count: PropTypes.number
}
View Code
  * TypeScript -- 详情见TypeScript笔记
22、严格模式
  * StrictMode是一个用来突出程序中潜在问题的工具,同Fragment一样,不会渲染任何可见的UI
  * 仅在开发模式下运行,不会影响生产构建
    * <React.StriceMode>...</React.StrictMode>
23、受控组件、非受控组件
  * 受控组件即为可通过state进行控制的组件,数据通过react进行管理
  * 非受控组件是数据不通过react进行管理,交由dom元素自身进行管理
  * 非受控组件可以通过ref来获取dom节点的相关数据
posted @ 2022-04-27 17:15  清风环珮  阅读(37)  评论(0编辑  收藏  举报