PureComponent
PureComponent 提供了一个具有浅比较的 shouldComponentUpdate 方法,其他和 Component 完全一致
浅比较:新修改的数据与原本的数据如果一样则不予更新,否则更新
1) 字符串正常
2) 对象的话,存的是地址,比较的也是地址,按照地址再去找具体的值,所以没更换新地址的话,那么原本去赋值就不太行,
需要解构赋值,this.setState({list:[…list]})
Component 不管与原数据是否一样都重新全部更新
–App.js
import React, {PureComponent, Component } from 'react';
// Component 不管与原数据是否一样都重新全部更新
// PureComponent 提供了一个具有浅比较的 shouldComponentUpdate 方法,// 其他和 Component 完全一致// 浅比较:新修改的数据与原本的数据如果一样则不予更新,否则更新// 1) 字符串正常// 2) 对象的话,存的是地址,比较的也是地址,按照地址再去找具体的值,// 所以没更换新地址的话,那么原本去赋值就不太行,// 需要解构赋值,this.setState({list:[...list]})class App extends
PureComponent {
state = {
name:"尖叫",
list:["运动饮料-01","运动饮料-02","运动饮料-03"]
}
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("新口味");
// 使用PureComponent时,注意使用解构赋值的方式!!!
this.setState({list:[...list]})
//this.setState({list}) //PureComponent下使用这个的话,扩大功能实现不了
}}>扩大</button>
</div>
)
}}
export default App;
–index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
// <React.StrictMode>
<App />,
// </React.StrictMode>,
document.getElementById('root'));
component与PureComponent的区别
如果使用Component,则不管与原数据是否一样都会重新全部更新;
以下是使用 PureComponent 的情况:修改的数据与原本的若一样则不予更新
ref
旧版 - string ref
主流 - createRef()
*注意:在 组件挂载完成之后及更新之后使用
本次结合一个滚动小插件来使用ref:
new BScroll():()内填入要滚动的对象,比较适用于移动端,可以拖拽,不能滚轮滑动
1.旧版用法示例:
import React, {PureComponent, createRef } from 'react';
import BScroll from "better-scroll"
// 滚动小插件:// new BScroll(),()内填入要滚动的对象// 注意:只能在 组件挂载完成之后及更新之后使用!!!!!!
// 新的小写法 ~ ~ ~
let list = [...(".".repeat(100))];
console.log(list)
class App extends PureComponent {
// 新版的一个小弊端:需要新的话需要再重新创建一个,再绑到一个新的
// box = createRef();// 2.新版ref写法(主流方式)----- 需要先在类里创建一个空的,存在box当中
// list = createRef();
componentDidMount(){
console.log(this); //新版的写法时,不在refs里了,多了一个box,box: {current: div}
console.log(this.refs); //ref的集合,旧版含有集合,新版写法里没有
console.log(this.refs.box);
// console.log(this.box.current);
new BScroll(this.refs.box);//1.旧版 ***
// new BScroll(this.box.current);//2.新版-----
}
render(){
return(
<div style={{
height:"300px",
border:"1px solid #000",
overflow:"hidden"
}}
ref="box" // 1.旧版*** 绑定 其他地方例如:挂载完成之后及更新之后的生命周期函数 可以获取到
// ref = {this.box} // 2.新版----- 绑到box上,box属性中存了一个ref
>
<ul style={{
margin:0,
padding:0,
listStyle:"none"
}}
ref="list"
// ref = {this.list} //输出this时,则会多出一个list属性 list: {current: ul}
>
{
list.map((item,index)=>{
return <li key={index}>这是第{index+1}个li</li>
})
}
</ul>
</div>
)
}
}
export default App;
children
组件标签对之间的内容会被当做一个特殊的属性 props.children 传入组件内容
可以自定义结构的组件的常用形式
children
传递函数
传递子组件
示例一:
dangerouslySetInnerHTML
直接设置标签的 innerHTML
import React, {PureComponent} from 'react';/*
只能接后端返回回来的校检过的安全的数据
*/
let message = `
<h1>夏天快乐</h1>
<p>夏天都快过去了</p>
`class App extends PureComponent {
render(){
return(
<div dangerouslySetInnerHTML={{
__html:message
}}>
</div>
)
}}
export default App;
key 的问题
在 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)=>{
{/* 尽量不要用下标索引值index为key,有一个变则会整体都变,很耗性能。
用id则会一一进行对比,看是否发生了改变,没变则不动,改变的则进行变动。则只会改变选中的id对应的数据,不会整体都变
DOM最耗性能,计算功能本来就是计算机擅长的
*/}
// return <p key={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;
自定义Hooks
react hooks 是 React 16.8 的新增特性。 它可以让我们在函数组件中使用 state 、生命周期以及其他 react特性,而不仅限于 class 组件。react hooks 的出现,标示着 react中不会在存在无状态组件了,只有类组件和函数组件。具体可查看官网。
优势:
- 函数组件不能使用state,遇到交互更改状态等复杂逻辑时不能更好地支持,hooks让函数组件更靠近class组件,拥抱函数式编程。
- 解决副作⽤问题,hooks出现可以处理数据获取、订阅、定时执行任务、手动修改 ReactDOM这些⾏为副作用,进行副作用逻辑。比如useEffect。
- 更好写出有状态的逻辑重用组件。
- 让复杂逻辑简单化,比如状态管理:useReducer、useContext。
- 函数式组件比class组件简洁,开发的体验更好,效率更⾼,性能更好。
- 更容易发现无用的状态和函数。
例子:
import React,{useEffect} from 'react'
//封装的Hooks⽤用use开头
const useChangeTitle= (title) =>{
useEffect(()=>{ document.title=title
},[title]) }
exprot default (props)=>{ useChangeTitle("⾃自定义修改标题Hooks") return (
<div> 测试⾃自定义Hooks
</div> )
}
- 只在顶层调⽤Hooks Hooks的调⽤,尽量只在顶层作⽤域进行调用不要在循环,条件或者是嵌套函数中调⽤Hook,否则可能会⽆无 ,确保每次组件渲染时都以相同的顺序调⽤Hook。
- 只在函数组件调⽤Hooks,React Hooks目前只支持函数组件,所以⼤大家别在class组件或者普通的函数⾥面调⽤Hook钩⼦函数
- React Hooks的应用场景在函数组件,自定义hooks
在未来的版本React Hooks会扩展到class组件,但是现阶段不能再class⾥使⽤。
useEffect
使用 Effect Hook
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
如果熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做
componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
无需清除的 effect
有时候,我们只想在 React 更新 DOM 之后运行一些额外的代码。比如发送网络请求,手动变更 DOM,记录日志,这些都是常见的无需清除的操作。因为我们在执行完这些操作之后,就可以忽略他们了。让我们对比一下使用 class 和 Hook 都是怎么实现这些副作用的。
使用 class 的示例
在 React 的 class 组件中,render 函数是不应该有任何副作用的。一般来说,在这里执行操作太早了,我们基本上都希望在 React 更新 DOM 之后才执行我们的操作。
这就是为什么在 React class 中,我们把副作用操作放到 componentDidMount 和 componentDidUpdate 函数中。回到示例中,这是一个 React 计数器的 class 组件。它在 React 对 DOM 进行操作之后,立即更新了 document 的 title 属性
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
注意,在这个 class 中,我们需要在两个生命周期函数中编写重复的代码。
这是因为很多情况下,我们希望在组件加载和更新时执行同样的操作。从概念上说,我们希望它在每次渲染之后执行 —— 但 React 的 class 组件没有提供这样的方法。即使我们提取出一个方法,我们还是要在两个地方调用它。
现在让我们来看看如何使用 useEffect 执行相同的操作。
使用 Hook 的示例
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useEffect 做了什么? 通过使用这个 Hook,你可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它。在这个 effect 中,我们设置了 document 的 title 属性,不过我们也可以执行数据获取或调用其他命令式的 API。
为什么在组件内部调用 useEffect? 将 useEffect 放在组件内部让我们可以在 effect 中直接访问 count state 变量(或其他 props)。我们不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。Hook 使用了 JavaScript 的闭包机制,而不用在 JavaScript 已经提供了解决方案的情况下,还引入特定的 React API。
useEffect 会在每次渲染后都执行吗? 是的,默认情况下,它在第一次渲染之后和每次更新之后都会执行。(我们稍后会谈到如何控制它。)你可能会更容易接受 effect 发生在“渲染之后”这种概念,不用再去考虑“挂载”还是“更新”。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。
react-router
react-router 是对你前端路由的管理配置.
注意
React项目的可用的路由库是React-Router,当然这也是官方支持的。它也分为:
- eact-router 核心组件
- react-router-dom 应用于浏览器端的路由库(单独使用包含了react-router的核心部分)
- react-router-native 应用于native端的路由
我用的web端路由库:
{
"react-router-dom": "^5.1.2"
}
安装
npm install --save react-router-dom
Router
就是说Router只是一个所有router组件的公共接口,要使用则用它的实现类组件:
<BrowserRouter>
<HashRouter>
<MemoryRouter>
<NativeRouter>
<StaticRouter>
这些就是我现在了解的一些react知识