[学习笔记] React

85 阅读3分钟

React特性

始终整体"刷新"页面

传统页面采用的是局部刷新

image.png 当你想在ul里加入li时,需要append进去

react采用的是整体刷新, 也就是直接吧 ul 里的 li 全部删除之后再重新渲染

image.png

jsx

动态创建组件的语法糖

const ele = <h1>hello {name}</h1>
等同于
const ele = React.creatElement(
    'h1',
    null,
    'hello',
    name
)

约定:自定义组件以大写字母开头

1.React认小写的tag是原生DOM节点, 如 div
2.大写字母开头是自定义组件

生命周期

v2-1a5c5bf1bc035c8e3c7841953d25c048_1440w.jpg

constructor

1.用于初始化内部状态,很少使用
2.唯一可以直接修改 state 的地方

getDerivedStateFromProps

1.当state需要从props初始化时使用
2.尽量不要使用:维护两者状态-致性会增加复杂度
3.每次render都会调用
4.典型场景:表单控件获取默认值

componentDidMount

1.UI渲染完成后调用
2.只执行一次
3.典型场景:获取外部资源

componentWillUnmount

1.组件移除时被调用
2.典型场景:资源释放.

getSnapshotBeforeUpdate

1.在页面render之前调用, state已更新
2.典型场景:获取render之前的DOM状态

componentDidUpdate

1.每次UI更新时被调用
2.典型场景:页面需要根据props变化重新获取数据

shouldComponentUpdate

1.决定Virtual DOM是否要重绘
2.一般可以由PureComponent自动实现
3.典型场景:性能优化

组件

props + state => view

React 的核心机制是能够在数据发生变化的时候自动重新渲染 UI,那么势必要有一个让我们保存状态的地方,这个保存状态的机制就是 state。
react组件可以类比成一个函数,props可以当成型参,state跟props类似但是state是私有的。和函数一样,通过外界传入的型参(props)||自身的state 会返回一个view
组件绝不能修改自身的 props

组件定义&&渲染

组件有两种定义方式: 函数式组件 && class类组件
比如下面的CommentBox组件 和 CommentList组件 是函数式组件
CommentItem组件是class类组件

通过render()渲染

image.png

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="theme-color" content="#000000" />
  <meta name="description" content="Web site created using create-react-app" />
  <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
  <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
  <title>React App</title>
</head>
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <!--这是根节点 该节点内的所有内容都将由 React DOM 管理-->
  <div id="root"></div>
</body>
</html>

//index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
//声明根节点
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <App />
);

//App.js
import CommentBox from './components/CommentBox';

function App() {
//return 只能返回一个大的标签,所以需要在最外层添加一个div
  return (
    <div>
      <CommentBox name={'11'} />
      <CommentBox name={'12'} />
    </div>
  )
}
export default App;

//CommentBox.js
import React from "react";
import CommentList from "./CommentList";

const comments = [
  {
    author: "Nate",
    content: "Hello React! This is a sample comment.",
  },
  { author: "Kevin", content: "Hello Redux!" },
  { author: "Bood", content: "Hello Rekit!" },
];
//函数式组件
function CommentBox(props) {
  return (
    <div className="comment-box">
      {props.name}
      <h1>Comments ({comments.length})</h1>
      <CommentList comments={comments} />
    </div>
  );
}
export default CommentBox;

//CommentList.js
import React from "react";
import CommentItem from "./CommentItem";
//函数式组件
export default function CommentList (props) {
    //key是唯一标识 最好用id表示
    return (
      <div className="comment-list">
        {props.comments.map((comment,idx) => <CommentItem comment={comment} key={idx}/>)}
      </div>
    );
}

//CommentItem.js
import React, { PureComponent } from "react";
//class类组件
export default class Comment extends PureComponent {
  render() {
    const { author, content } = this.props.comment;
    return (
      <div className="comment-item">
        <span className="avatar" />
        <a href="#">{author}</a>
        <p>{content}</p>
      </div>
    );
  }
}

目录结构

components
  CommentBox.js
  CommentList.js
  CommentItem.js
App.js
index.js

单一责任原则

1.每个组件只做一件
2.如果组件变得复杂那应该拆分成小组件

数据状态管理 DRY原则

1.能计算得到的状态就要不单独存储
2.组件尽量无状态所需数据通过props获取