目录
一.React属性
1.PureComponent
(1)介绍PureComponent
PureComponent是react中创建组件的一种方式,可以减少不必要的更新,进而提升性能,每次更新会自动帮你对更新前后的props和state进行一个简单对比,来决定是否进行更新,浅比较通过一个函数来完成
如果定义了 shouldComponentUpdate(),无论组件是否是 PureComponent 它都会执行shouldComponentUpdate结果来判断是否update。如果组件未实现shouldComponentUpdate() ,则会判断该组件是否是PureComponent,如果是的话,会对新旧 props、state 进行 shallowEqual 比较,一旦新旧不一致,会触发
update。
(2)为什么用 PureComponent ?
PureComponent 是优化 React 应用程序最重要的方法之一,易于实施,只要把继承类从 Component 换成 PureComponent 即可,可以减少不必要的 render 操作的次数,从而提高性能,而且可以少写 shouldComponentUpdate 函数,节省了点代码。
import React, {PureComponent, Component} from ‘react’;
import React, { PureComponent,Component } from 'react';
class App extends PureComponent {
state = {
name: "东鹏特饮",
list: ["运动饮料1", "运动饮料2", "运动饮料3"]
}
render() {
let { name, list } = this.state;
return (
<div>
<h1>{name}</h1>
<ul>
{
list.map((item, index) => {
return <li key={index}>{item}</li>
})
}
</ul>
<button onClick = { () => {
this.setState({name:"红牛"})
}}>升级</button>
<button onClick={() => {
list.push("新口味");
this.setState({
list:[...list]
})
}}>扩大</button>
</div>
)
}
}
export default App;
当继承PureComponent时,list:[…list]必须写成这样扩大的这个按钮才会新增数据的; 当继承Component时, list:[…list]也可以写成list
(3)PureComponent优点
不需要开发者自己实现shouldComponentUpdate,就可以进行简单的判断来提升性能。
(4)PureComponent缺点
可能会因深层的数据不一致而产生错误的否定判断,从而shouldComponentUpdate结果返回false,界面得不到更新。
2.ref
(1)ref是什么?
ref是React提供的用来操纵React组件实例或者DOM元素的接口
(2) ref使用方式
a. string类型绑定
类似于vue中的ref绑定方式,可以通过this.refs.绑定的ref的名字获取到节点dom
class App extends React.Component{
showData(){
// 通过自己设定的 refs名称获取对应的元素
const {myInput} = this.refs; // 返回该元素
alert(myInput.value)
}
render(){
return (
<div>
{ /* 通过 ref属性绑定这个 input标签 */ }
<input type="text" ref="myInput" placeholder="search something" />
{/* 事件绑定会在下面讲 */}
<button onClick={this.showData}>Show Data</button>
</div>
)
}
}
注意: 这种方式已经不被最新版的react推荐使用,有可能会在未来版本中遗弃
b. react.CreateRef()
通过在class中使用React.createRef()方法创建一些变量,可以将这些变量绑定到标签的ref中那么该变量的current则指向绑定的标签dom
class App extends React.Component{
// 使用 React.createRef() 创建一个 ref容器
myRef = React.createRef();
showData = ()=>{
// 在容器中获取 DOM元素
const {current} = this.myRef;
alter(current.value);
}
render(){
return (
<div>
{/* 将DOM元素绑定在容器中 */}
<input ref={this.myRef} placeholder="点击提示数据" type="text"/>
<button onClick={this.showData}>ShowData</button>
</div>
)
}
}
c. 函数形式
在class中声明函数,在函数中绑定ref
使用这种方法可以将子组件暴露给父组件以使得父组件能够调用子组件的方法
React.Component{
showData(){
const {myInput} = this; // 返回该元素
alert(myInput.value)
}
render(){
return (
<div>
{/* 回调函数的参数为该元素本身,通过函数绑定在 this上 */}
<input type="text" ref={ e => this.myInput = e } placeholder="search something" />
<button onClick={this.showData}>Show Data</button>
</div>
)
}
}
3. children
向组件内部动态传入带内容的结构(标签)
组件标签对之间的内容会被当做一个特殊的属性 props.children 传入组件内
操作children
如果你看过React的文档你就会说“children是一个不透明的数据结构”。从本质上来讲, props.children 可以使任何的类型,比如数组、函数、对象等等。
React提供了一系列的函数助手来使得操作children更加方便。
父组件:
class Parent extends React.Component {
render() {
return (
<Child>
<span>{'child node'}</span>
</Child>
);
}
子组件:
class Child extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
}
4.dangerouslySetInnerHTML
- (1) dangerouslySetInnerHTMl 是React标签的一个属性,类似于angular的ng-bind;
- (2) 有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;
- (3) 既可以插入DOM,又可以插入字符串;
- (4) 不合时宜的使用 innerHTML 可能会导致 cross-site scripting (XSS) 攻击。 净化用户的输入来显示的时候,经常会出现错误,不合适的净化也是导致网页攻击的原因之一.dangerouslySetInnerHTML 这个 prop 的命名是故意这么设计的,以此来警告,它的 prop 值( 一个对象而不是字符串 )应该被用来表明净化后的数据。
import React, {PureComponent} from 'react';
let message = `<h1hahaha</h1>
<p>heihei</p>`
class App extends PureComponent {
render(){
return (
<div dangerouslySetInnerHTML={{
__html:message
}}>
</div>
)
}
}
export default App;
5.key
(1) react中key有什么作用?
简单的来说就是为了提高diff的同级比较的效率,避免原地复用带来的副作用,
vue和react本身都是采用diff的算法vue采用的是更为细粒的更新组件方式,即是给每一个属性绑定监听,
react采用的是自顶而下的更新策略,每次小的改动都会生成一个全新的的vdom,从而进行diff,如果不写key,就会发生本来应该更新却没有更新
(2) 原理
因为在reactelement中有一个属性是key,该属性默认是为空值,所以一般情况下,只要组件不加上key值,react是不会去校验组件的key,而是直接采用diff算法进行对比,一旦组件加上了key值,react就会在渲染时对该组件的身份进行校验,首先校验新旧组件的key值是不是一致,不一致的话,该组件直接销毁,然后在新建该组件;如果一致,则比较组件的属性是否发生变化,如果发生变化,则采用diff算法进行对比,然后得出差异对象,如果属性没发生变化,则认为该组件不需要改变;
流程图:
案例
在react,组件每次更新时,会生成一个虚拟DOM, 和原油的虚拟DOM进行对比; 如果在批量生成一组元素,那么react就会根据key值去做对比
一个列表中的每一项key是惟一的, 如果列表中发生顺序等操作变化,key一定要用数据的id
import React, { PureComponent } from 'react';
class App extends PureComponent {
state = {
data: [
{
id: 0,
content: "第1条数据"
},
{
id: 1,
content: "第2条数据"
},
{
id: 2,
content: "第3条数据"
},
{
id: 3,
content: "第4条数据"
},
{
id: 4,
content: "第5条数据"
}
]
}
render() {
let { data } = this.state;
return (
<div>
{
data.map((item, index) => {
return <p key={item.id}>
{item.content}
<a onClick={() => {
data = data.filter(itemData => itemData !== item)
this.setState({
data: [...data]
})
}}>删除</a>
</p>
})
}
</div>
)
}
}
export default App;
- key相同:若组件属性有所变化,则react只更新组件对应的属性;没有变化则不更新。
- key值不同:则react先销毁该组件,然后重新创建该组件。
二.函数式组件
- 组件的第0个参数是props - 接受父级传递过来的信息
- 组件的中 return(必写) 定义该组件渲染的内容
- 没有生命周期 没有this 没有state
function Child(props){
return <h1>{props.info}</h1>
}
function App(){
// console.log(this)
return <Child info="哈哈哈"/>
}
export default App;
三.Hooks
官方英文文档 : https://reactjs.org/docs/hooks-intro.html
官方中文文档: https://reactjs.bootcss.com/docs/hooks-intro.html
React hooks 是React 16.8中的新增功能,无需编写类即可使用状态和其他React功能
Hook 使用规则
- 只在最顶层使用 Hook 不要在循环,条件判断或者子函数中调用.
- 只在 React 函数中调用 Hook
- React 函数组件中 React Hook 中 自己定义 hook
时,可以调用别的hook
所有的 hook 必须 以 use
React Hooks 优势
- 简化组件逻辑
- 复用状态逻辑
- 无需使用类组件编写
- 完全可选的
四.useState
本身是一个函数,来自react包,参数和返回值,返回一个数组
参数:作用是给创建出来的状态一个默认值
返回值:数组
元素1:当前state的值
元素2:设置新的值时,使用的一个函数
useState 让函数式组件拥有状态
let [状态的值,修改状态的方法] = useState(状态的初始值)
App.js
import React,{useState} from 'react';
import Child from './Child'
/*
let [状态的值,修改状态的方法] = useState(状态的初始值)
*/
function App(){
// console.log(this)
let [data,setData] = useState({
name:"小刘",
age: 22
});
return <div>
<Child data={data}/>
<button onClick={()=>{
setData({
name:"嘿哈嘿哈",
age:data.age
});
}}>变变变</button>
</div>
}
export default App;
Child.js
import React from 'react';
function Child(props){
console.log(props);
let {data} = props;
return <div>
<h1>name:{data.name}</h1>
<h1>age:{data.age}</h1>
</div>
}
export default Child;
五.useEffect
相当于类组件中的 componentDidMount(挂载完成); componentDidUpdate(数据更新完成); componentWillUnmount(即将卸载) 这三个的集合体.
可以在组件中多次使用useEffect;
useEffect 你更新了信息,会触发组件信息更新
没加return就是挂载,更新. 但是会先挂载
在 return 之后,就是卸载
在最后可以绑定监听一个变量,只有这些变量变动时,useEffect 才会执行
App.js
import React,{useState} from 'react';
import Child from './Child'
/*
let [状态的值,修改状态的方法] = useState(状态的初始值)
*/
function App(){
// console.log(this)
let [data,setData] = useState({
name:"小刘",
age: 22
});
let [show,setShow] = useState(true)
return <div>
{show?<Child data={data}/>:""}
<button onClick={()=>{
setData({
name:"嘿哈嘿哈",
age:data.age
});
}}>变变变</button>
<button onClick={()=>{
setShow(false)
}}>卸载</button>
</div>
}
export default App;
Child.js
import React,{useState,useEffect} from 'react';
function Child(props){
let {data} = props;
let [age,setAge] = useState(8);
useEffect(()=>{
console.log("挂载了");
},[]);
useEffect(()=>{
return () => {
console.log("卸载了");
}
},[]);
useEffect(() => {
console.log("更新了");
},[data]);
return <div>
<h1>name:{data.name}</h1>
<h1>age:{age}</h1>
<button onClick={()=>{
setAge(++age)
}}>长一岁</button>
</div>
}
export default Child;
六.总结:
今天学习了react的五个属性PureComponent, ref, children, dangerouslySetInnerHTML, key值
React Hook 在项目中逻辑比较简单的