二、React18简介

郁子大约 5 分钟约 1643 字笔记React18李立超

(一)Hello World

  • React 就是用来代替 DOM

1. DOM 操作

  • 通过 DOM 向页面中添加一个 div
// 创建一个div(DOM元素)
const div = document.createElement("div");
// 向div中设置内容
div.innerText = "我是一个div";
// 获取root
const root = document.getElementById("root");
// 将div添加到页面中
root.appendChild(div);

2. React 操作

  • 通过 React 向页面中添加一个 div
// 创建一个div(React元素)
const div = React.createElement("div", {}, "我是React创建的div");
// 获取根元素对应的React元素
const root = ReactDOM.createRoot(document.getElementById("root"));
// 将div渲染到根元素中
root.render(div);

(二)三个 API

1. React.createElement()

  • 用来创建一个 React 元素

1)参数

  • 元素名(组件名)
    • HTML 标签名,必须小写
  • 标签中的属性( id 等)
    • class 属性需要使用 className 来设置
    • 设置事件时,属性名需要修改为驼峰命名法,如 onClick
  • 元素的子元素(内容)

2)React 元素

  • React 元素最终会通过虚拟 DOM 转换为真实 DOM 元素
  • React 元素一旦创建就无法修改,只能通过新创建的元素进行替换
const button = React.createElement(
  "button",
  {
    id: "btn",
    type: "button",
    className: "hello",
    onClick: () => {
      alert("你点我干嘛!");
    },
  },
  "点我一下",
);
const div = React.createElement("div", {}, "我是一个div", button);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);

// 修改已存在的React元素
// 获取按钮对象
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
  // 点击按钮后修改div中button的文字为click me
  const button = React.createElement(
    "button",
    {
      id: "btn",
      type: "button",
      className: "hello",
      onClick: () => {
        alert("你点我干嘛!");
      },
    },
    "click me",
  );
  const div = React.createElement("div", {}, "我是一个div", button);
  // 修改React元素后,必须重新对根元素进行渲染
  // 当调用render渲染页面时,React会自动比较两次渲染的元素,只在真实DOM中更新发生变化的部分,没变化的保持不变
  root.render(div);
});

2. ReactDOM.createRoot()

  • 用来创建 React 根元素
  • 需要一个 DOM 元素作为参数
const root = ReactDOM.createRoot(document.getElementById("root"));

3. root.render(div)

  • 用来将 React 元素渲染到根元素中
  • 根元素中所有的内容都会被删除,被 React 元素所替换
  • 当重复调用 render 时, React 会将两次的渲染结果进行比较,会确保只修改那些发生变化的部分,对 DOM 做最少的修改
    • DOM Diffing 算法【差分算法】
// 老版本
// ReactDOM.render(div, document.getElementById('root'));

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);

(三)JSX

  • JSX,JS 扩展,JavaScript Syntax Extension

1. script标签

  • 设置 JS 代码被 babel 处理
<body>
  <div id="root"></div>
</body>

<script type="text/babel"></script>

2.创建一个 React 元素: <button></button>

1)命令式编程

const button = React.createElement("button", {}, "我是按钮");
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(button);

2)声明式编程

  • React 中可以通过 JSX 来创建 React 元素,需要被翻译为 JS 代码才能被 React 执行
  • 要在 React 中使用 JSX ,必须引入 babel 来完成“翻译”工作
  • JSX 就是 React.createElement('button', {}, '我是按钮') 的语法糖
  • JSX 在执行之前都会被 babel 转换为 JS 代码
const div = (
  <div>
    我是一个div
    <button>我是按钮</button>
  </div>
);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(button);

3.注意事项

  • JSX 不是字符串,不要加引号
  • JSXhtml 标签应该小写, React 组件应该大写开头
  • JSX 中有且只有一个根标签
  • JSX 的标签必须正确结束(自结束标签必须写 /
  • JSX 中可以使用 {} 来嵌入表达式
    • 有值的语句就是表达式
  • 如果表达式是空值、布尔值、 undefined 等,都不会显示在页面上
  • JSX 中,属性可以直接在标签中设置
    • class 需要使用 className 代替
    • style 必须使用对象设置
    • 事件需要使用 半驼峰命名
const name = "aaa";
const fn = () => {
  return "hello";
};

const div = (
  <div>
    我是一个div
    <ul>
      <li>列表项</li>
      <li>列表项</li>
    </ul>
    <input type="text" />
    <div
      id="box"
      onClick={() => {
        alert("哈哈哈");
      }}
      className="box"
      style={{ backgroundColor: "lightblue" }}
    >
      {name}
      <br />
      {1 + 1}
      <br />
      {fn()}
      <br />
      {/* {if(true){...}}<br/> */}
      {null}
      <br />
    </div>
  </div>
);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(div);

4.渲染列表

  • {} 中只能放 JS 表达式,不能放 JS 语句(iffor
  • JS 语句中可以操作 JSX
// const name = 'aaa';
// const div = (
//   <div>
//     Hello, {name}
//   </div>
// );

const name = "bbb";
const lang = "en";
let div;
if (lang === "en") {
  div = <div>Hello, {name}</div>;
} else if (lang === "cn") {
  div = <div>你好, {name}</div>;
}
  • JSX 中会自动将数组中的元素在页面中显示
const arr = ["a", "b", "c"];
// const list = <div>{arr}</div>
const list = (
  <ul>
    {arr.map((item) => (
      <li>{item}</li>
    ))}
  </ul>
);

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);

(四)虚拟 DOM

  • React 中操作的元素被称为 React 元素,并不是真正的原生 DOM 元素
  • React 通过虚拟 DOM ,将 React 元素和原生 DOM 进行映射
  • 虽然操作的是 React 元素,但是这些操作最终都会在真实 DOM 中体现

1.虚拟 DOM 的好处

  • 降低 API 复杂度
  • 解决兼容性问题
  • 提升性能(减少 DOM 的不必要操作)

2.注意点

  • 每当调用 root.render() 时,页面就会重新渲染
    • React 会通过 Diffing 算法,将新元素和旧元素进行比较
    • 找到发生变化的元素,并且只对变化的元素进行修改,没变化的元素保持不变
  • 比较两次数据时, React 会先比较父元素
    • 父元素如果不同,直接替换所有元素
    • 父元素一致,再逐个比较子元素,直到找到所有发生变化的元素为止
  • 当我们在 JSX 中显示数组时,数组中每一个元素都需要设置一个唯一 key
    • 重新渲染页面时, React 会按照顺序依次比较对应的元素,当渲染一个列表时如果不指定 key ,同样会按照顺序进行比较
    • 如果列表的顺序永远不会发生变化,没有 key 不会引发其他问题
    • 如果列表的顺序发生变化,可能会导致性能问题,列表项中有表单项时页面渲染会有错误
    • key 的作用相当于 ID ,但是不在页面中显示, React 会根据 key 顺序比较新旧元素,未指定 key 时按顺序比较
  • 开发中一般使用 id 作为 key
  • 尽量不要使用元素的 index 作为 key
    • index 索引会跟着元素顺序的改变而改变,所以使用索引和没有 key 是一样的
    • 当列表顺序不变时,用索引没有问题
const arr = ["a", "b", "c"];
const list = (
  <ul>
    {arr.map((item, index) => (
      <li key={index}>{item}</li>
    ))}
  </ul>
);
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(list);

document.getElementById("btn").onclick = function () {
  const arr = ["a", "b", "c"];
  const list = (
    <ul>
      {arr.map((item) => (
        <li>{item}</li>
      ))}
    </ul>
  );
  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(list);
};
上次编辑于: