React 知识点记录

126 阅读4分钟

真实DOM

DOM 全称是 Document Object Model,指的是文档对象模型,是HTML和XML文档的编程接口,是W3C指制定的标准;HTML DOM简单理解就是HTML被加载时,浏览器会创建这个文档对象模型。

DOM提供了对整个文档的访问模型,将文档作为一个树形结构,树的每个结点表示了一个HTML标签或标签内的文本项。DOM树结构精确地描述了HTML文档中标签间的相互关联性

虚拟DOM

一个普通的 JavaScript 对象,包含了 tagpropschildren 三个属性

  • 优点:

    • 减少DOM 操作;可以将多次操作合并为一次操作;DOM diff 算法可以减少多余操作

      • 比如需要添加1000个节点时,DOM是一个一个添加的,而虚拟DOM 可以一次添加1000 个

      • 比如添加1000个节点,其实只有10个是新增的

    • 跨平台 虚拟DOM 不仅可以变成DOM,还可以变成小程序,iOS应用,安卓应用,因为虚拟DOM上本质只有一个JS对象,

  • 缺点:

    需要额外的创建函数,如React.createElement(),可用JSX简化语法

    <div>这种JSX语法就是简化了 React.createElement()的写法

React 组件传值

  • 父给子传值靠Props

  • 子组件时不能操作父组件里的数据,需要通过调用父组件的方法来实现;否则违背了React 当向数据流

    eg:子组件通过调用父组件的方法修改数据

    父组件

    <ul
          ref={(ul) => {
            this.ul = ul;
          }}
        >
          {this.state.list.map((item, index) => (
            // 子组件
            <TestItem
              key={index.toString()}
              prefix={"React base"}
              content={item}
              suffix={"有默认值的"}
              index={index}
              // 删除时子组件不能操作数据,只能将删除方法传递给子组件,让其调用
              deleteItem={this.deleteItem}
              list={this.state.list}
            ></TestItem>
          ))}
        </ul>
    

    子组件

      render() {
        return (
          <li onClick={this.handleClick}>
            {this.props.prefix} - {this.props.content} - {this.props.suffix}
          </li>
        );
      }
    
      handleClick() {
        // 调用父组件的删除方法来删除,不能操作数据
        this.props.deleteItem(this.props.index);
      }
    
  • 绑定this 尽量在构造函数中,这样会提高性能

  • 使用PropTypes 来定义组件的值

    使用PropTypes校验传递值

     TestItem.propTypes = {
       content: PropTypes.string,
       index: PropTypes.number,
       deleteItem: PropTypes.func,
       prefix: PropTypes.string.isRequired, // 必须传值的属性,不传回报错
     };
    

    定义默认值

    TestItem.defaultProps = {
      suffix: "Demo",
    };
    
  • ref 的使用

    • 使用前需要绑定DOM,建议使用箭头函数(ES6)
    <input
        className="input"
        id="Action"
        // -------- 箭头函数绑定DOM元素
        ref={(input) => {
          this.input = input;
        }}
        value={this.state.inputV}
        onChange={this.inputChange}
      ></input>
    
    • ref 使用遇到的坑

    setState()方法是异步的,会导致ref的值更新不是最新的,应该在setState()回调函数中来获取

      this.setState(
       {
         list: [...this.state.list, this.state.inputV],
         inputV: "",
       },
       () => {
         const children = this.ul.querySelectorAll("li");
         console.log("setState 执行完毕---" + children.length); // 准确的值
       }
     );
    
     const children = this.ul.querySelectorAll("li");
     console.log("ref 使用注意事项---" + children.length);
    
  • PureComponent和Component的区别

    PureComponent通过prop和state的浅比较来实现shouldComponentUpdate,可以用PureComponent提升性能

  • React只对一个<div> 其他的DOM 不受影响

  • npm install 用法

    • npm install xxx: 安装到项目目录下,不会将模块依赖写入devDependenciesdependencies
    • npm install -g xxx-g 将模块安装到全局,具体安装到磁盘哪个位置,要看 npm cinfig prefix的位置
    • npm install -save xxx-save 将模块安装到项目目录下,并在package文件的dependencies节点写入依赖,线上也会依赖此开源库,打包时资源会包含在内
    • npm install -save-dev xxx-save-dev 将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,只有开发debug 模式才会安装依赖,release模式不会打包此资源。不影响包大小
  • 使用 axiso 请求数据

...

React 中避免直接对数据修改

两种改变数据的方式。

  • 直接修改变量的值,

  • 使用新的一份数据替换旧数据

    优点:

    • 简化复杂的功能

    • 跟踪数据的改变

    • 确定在 React 中的重新渲染时机,提高性能

函数组件

如果组件只包含一个 render 方法,并且不包含 state,可使用函数组件更简单

通过map()构建动态列表时,都要指定一个合适的 key

  • 如果要对列表进行重新排序、新增、删除操作时,把数组索引作为 key 是有问题的

    因为每当一个列表重新渲染时,React 会根据每一项列表元素的 key 来检索上一次渲染时与每个 key 所匹配的列表项。如果 React 发现当前的列表有一个之前不存在的 key,那么就会创建出一个新的组件。如果 React 发现和之前对比少了一个 key,那么就会销毁之前对应的组件。如果一个组件的 key 发生了变化,这个组件会被销毁,然后使用新的 state 重新创建一份

  • 如不需要重新排序、新增、删除,使用索引作为 key 是安全的

组件的数据定义为props还是state?

通过以下三个问题,可得知数据是否属于 state:

  1. 该数据是否是由父组件通过 props 传递而来的?如果是,那它应该不是 state。
  2. 该数据是否随时间的推移而保持不变?如果是,那它应该也不是 state。
  3. 你能否根据其他 state 或 props 计算出该数据的值?如果是,那它也不是 state。

ReactNode 和 ReactElement 区别

查看声明文件如下~

ReactNode: 包括了 ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

image.png

ReactElement: ReactElement是含有 props 和 type 属性的对象

image.png

JSX.Element: J继承React.Element. 并且函数式组件一般返回JSX.Element

image.png