key 的问题
在 React ,组件每次更新时,会生成一个 虚拟DOM,和原有的虚拟DOM进行对比,从而优化性能
- 如果是批量生成的一组元素,那React就会根据 key 值去做对比
- 一个列表中的每一项 key 是唯一的,不能重名
- 如果明确列表更新前后,节点顺序不变,可以使用索引值,否则建议使用数据 id
PureComponent
PureComponent
类 提供了一个具有浅比较的 shouldComponentUpdate 方法,其他功能和 Component 完全一致
如果更新前后值一样,则不进行更新
但是如果数据是一个引用类型,就会同样造成数据不会更新,所以在改变引用类型的时候需要返回一个新的引用
import React, { PureComponent } from "react";
export default class App extends PureComponent {
state = {
name: { title: "lc" }
};
render() {
console.log(1);
let { name } = this.state;
return <div id="todoapp">
{name.title}
<button onClick={() => {
name.title = "修改title";
this.setState({
name: { ...name }
});
}}>修改</button>
</div>;
}
}
ref
- 如果在 react 中需要获取真实 DOM 节点可以通过 ref 属性来进行获取
- createRef()
- 注意:在组件挂载完成之后及更新之后使用
import React, { Component, createRef, Fragment } from "react";
export default class App extends Component {
input = createRef();
p = createRef();
// 在组件挂载完之后或更新完之后去获取 DOM节点
componentDidMount() {
console.log(this.input.current);
this.input.current.focus();
console.log(this.p.current);
}
render() {
// 组件渲染完时,会自动让输入框获得焦点
return <Fragment>
<input type="text" ref={this.input} />
<p ref={this.p}>p标签</p>
</Fragment>;
}
}
children
- 组件标签对之间的内容会被当做一个特殊的属性 props.children 传入组件内容
- 可以自定义结构的组件的常用形式
- children
- 传递函数
- 传递子组件
父组件在子组件中写html标签,会通过props传递给子组件中的children值中去
import React, { Component } from "react";
import PopWin from "./popWin";
export default class App extends Component {
render() {
return <div>
<PopWin
title="弹窗标题"
>
<div>这是弹出框的内容</div>
<div>这是弹出框的内容</div>
</PopWin>
</div>;
}
}
子组件通过使用props中的children来展示父级传递的html标签
import React, { Component } from "react";
export default class PopWin extends Component {
render() {
let { title, children } = this.props;
return <div id="popChild">
<h1>{title}</h1>
{children}
</div>;
}
}
当使用{}
包裹html标签时,那到的是一个对象
import React, { Component } from "react";
import PopWin from "./popWin";
export default class App extends Component {
render() {
return <div>
<PopWin
title="弹窗标题"
>
{<div>这是弹出框的内容1</div>}
</PopWin>
</div>;
}
}
多个{}
时拿到的是对象数组
import React, { Component } from "react";
import PopWin from "./popWin";
export default class App extends Component {
render() {
return <div>
<PopWin
title="弹窗标题"
>
{<div>这是弹出框的内容1</div>}
{<div>这是弹出框的内容2</div>}
{<div>这是弹出框的内容3</div>}
</PopWin>
</div>;
}
}
dangerouslySetInnerHTML
直接设置标签的 innerHTML
有时候后端可能会返回一个html格式的数据
但是react中不能直接插入标签格式的字符串
dangerouslySetInnerHTML就能实现这个需求
import React, { Component, createRef } from "react";
let inner = `<header>
<h1>Hello React</h1>
<p>111</p>
</header>`;
export default class App extends Component {
render() {
return <div
dangerouslySetInnerHTML={{
__html:inner
}}
></div>
}
}
利用ref插入html
在挂载阶段时做dom操作
import React, { Component, createRef } from "react";
let inner = `<header>
<h1>Hello React</h1>
<p>111</p>
</header>`;
export default class App extends Component {
div = createRef();
componentDidMount() {
this.div.current.innerHTML = inner;
}
render() {
return <div ref={this.div}></div>;
}
}
但是由于需要重新绘制DOM的原因,所以性能差
函数式组件
- 本质就是一个普通函数,该函数必须有 return,return中定义是该组件要渲染的视图
- 组件会接收一个参数,是组件的props,用于接收父组件传递过来的信息
- 在 React 16.7 之前,函数组件没有办法定义 state,也会没有生命周期函数,所以也被称之为纯渲染组件或无状态组件
import React from "react";
function App(props) {
return <h1>hello react</h1>;
}
export default App;