React特性
始终整体"刷新"页面
传统页面采用的是局部刷新
当你想在ul里加入li时,需要append进去
react采用的是整体刷新, 也就是直接吧 ul 里的 li 全部删除之后再重新渲染
jsx
动态创建组件的语法糖
const ele = <h1>hello {name}</h1>
等同于
const ele = React.creatElement(
'h1',
null,
'hello',
name
)
约定:自定义组件以大写字母开头
1.React认小写的tag是原生DOM节点, 如 div
2.大写字母开头是自定义组件
生命周期
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()渲染
//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获取