React类组件的属性和函数组件里的hooks
PureComponent
PureComponent 提供了一个具有浅比较的 shouldComponentUpdate 方法,其他和 Component 完全一致;
import React,{PureComponent,Component} from 'react'
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('新口味')
this.setState({list:[...list, ]
})
// this.setState({list})
}}>扩大</button>
</div>
)
}
}
export default App;
注意:加上PureComponent之后,他只能浅显进行比较,如果数据是对象直接赋值没有结果,如果用结构赋值,可以触发,如果是字符串,或数值可以直接输出
// this.setState({list}) 没有值
// this.setState({list:[…list, ] 可以输出值
})
PureComponent和Component的区别:
PureComponent每次做修改,只有发生变化后才会修改;
Component:每次做修改,无论和原数组是否一样都会更新
ref
获取react的DOM的节点
旧版ref
通过ref绑定一个字符串;
通过this.refs接收;
案例:利用ref做一个滚动效果
1.首先: 安装better-scroll插件 npm install better-scroll
2.接着引入better-scroll
3.使用better-scroll 需要实例化(dom节点)
dom节点 通过ref设置,this.refs获取
import React,{PureComponent} from 'react';
import BScroll from 'better-scroll'
// new BScroll()
let list=[...(".".repeat(100))];
// console.log(list)
class App extends PureComponent{
componentDidMount(){
new BScroll(this.refs.box)
new BScroll(this.refs.list)
}
render(){
return (
<div
style={{
height:"300px",
border:"1px solid #000",
overflow:"hidden"
}}
ref="box"
>
<ul
style={
{
margin:0,
padding:0,
listStyle:"none"
}
}
ref='list'
>
{
list.map((item,index)=>{
return <li key={index}>这是第{index}个</li>
})
}
</ul>
</div>
)
}
}
export default App;
注意:控制台会出现警告,想要去掉警告,去掉index.js里面的 <React.StrictMode>标签,就没有警告了
新版ref
通过createRef创建一个节点,在通过ref获取
import React,{createRef, PureComponent} from 'react';
import BScroll from 'better-scroll'
// new BScroll()
let list=[...(".".repeat(100))];
class App extends PureComponent{
box=createRef();
list=createRef();
//挂载完成
componentDidMount(){
console.log(this)
new BScroll(this.box.current);
new BScroll(this.list.current);
}
render(){
return (
<div
style={{
height:"300px",
border:"1px solid #000",
overflow:"hidden"
}}
ref={this.box}
>
<ul
style={
{
margin:0,
padding:0,
listStyle:"none"
}
}
ref={this.list}
>
{
list.map((item,index)=>{
return <li key={index}>这是第{index}个</li>
})
}
</ul>
</div>
)
}
}
export default App;
注意:新版的ref获取的Dom节点不在refs里面,如果想获取多个DOM节点就要多创建几个节点
注意:ref是在组件挂载完成或者更新后执行;
children
组件标签里的内容可以通过props.children传入组件;
import React,{ PureComponent} from 'react';
class Child extends PureComponent{
render(){
console.log(this)
let {children}=this.props;
return (
<div>{children}</div>
)
}
}
class App extends PureComponent{
render(){
return (
<div>
<Child>
{/* <h1>今天天气真不错</h1>
<p>明天天气也这样</p> */}
{
['哈哈哈','呵呵呵']
}
</Child>
</div>
)
}
}
export default App;
dangerouslySetInnerHTML
直接设置标签的 innerHTML,类似于vue中的v-html,可以解析标签,将内容渲染在浏览器中;
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;
注意:dangerouslySetInnerHTML返回的是以一个对象,用__html接收,后面是要显示的内容,接收的数据是后端传过来的
key
在 React ,组件每次更新时,会生成一个 虚拟DOM,和原有的虚拟DOM进行对比。
如果是批量生成的一组元素,那React就会根据 key 值去做对比
key是唯一的
列表循环也可以用index
注意:最好用id,因为index无论改变没都会更新,而且他不稳定,因为索引会发生变化,而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条数据"
},
]
}
render(){
let{data}=this.state;
return (
<div>
{
data.map((item,index)=>{
return <p key={item.id}>
{item.content}
<a onClick={()=>{
data.filter(itemData=>itemData!==item)
this.setState({
data:[...data]
})
}}>删除</a>
</p>
})
}
</div>
)
}
}
export default App;
函数式组件
主要是用来渲染内容,函数名字就是组件名
import React from 'react';
function Child(props){
return <h1>{props.info}</h1>
}
function App(){
console.log(this)
return <Child info='呵呵'/>
}
export default App;
函数组件注意事项
1.组件的第0个参数是props----接收父级传过来的信息
2.组件中的 return(必须写)----定义该组件要渲染的内容
3.没有生命周期,没有this,没有state
4.在16.7之前, 函数组件一直当做纯渲染组件来使用
hook
作用
- 简化组件逻辑
- 复用状态逻辑
- 无需使用类组件编写
常用hook
useState
函数组件里定义状态值
先引用useState,接着定义
let [状态值,修改状态的方法名]=userState(状态的初始值)
修改状态值方法名是自己定义的
App.js
import React,{useState} from 'react';
function App () {
//定义 let [状态值,修改状态的方法名]=userState(状态的初始值)
const [ count, setCount ] = useState(0)
return (
<div>
点击次数: { count }
<button onClick={() => { setCount(count + 1)}}>点我</button>
</div>
)
}
注意:如果传的是对象不能这样用
App.js
import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)
function App(){
let [data,setName]=useState({
name:"毫克",
age:28
})
return<div>
<Child data={data}/>
<button onClick={()=>{
setName({
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 的第二个参数,有三种情况
1.什么都不传,组件每次 render 之后 useEffect 都会调用,相当于 componentDidMount 和 componentDidUpdate
2.传入一个空数组 [], 只会调用一次,相当于 componentDidMount 和 componentWillUnmount
3.传入一个数组,其中包括变量,只有这些变量变动时,useEffect 才会执行
App.js
import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)
function App(){
let [data,setName]=useState({
name:"毫克",
age:28
})
let [show,setShow]=useState(true)
return<div>
{show? <Child data={data}/>:""}
<button onClick={()=>{
setName({
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){
console.log(props);
let {data}=props;
let [age,setAge]=useState(8)
useEffect(()=>{
console.log('挂载了');
// return ()=> {
// // console.log("卸载时触发")
// }
},[])
useEffect(()=>{
return ()=>{
console.log('卸载了')
}
})
//检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法
return <div>
<h1>name:{data.name}</h1>
<h1>age:{age}</h1>
<button onClick={()=>[
setAge(++age)
]}>长一岁</button>
</div>
}
export default Child
注意1:挂载和更新在useEffect里面写,而卸载在return里面写
注意2:检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法
useRef
作用:在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx;
使用:
先引入useRef,然后创建一个空的useRef(),在通过ref来接收创建的那个空的useRef
App.js
import React,{useState} from 'react';
import Child from './Child';
// let [状态值,修改状态的方法]=userState(状态的初始值)
function App(){
let [data,setName]=useState({
name:"毫克",
age:28
})
let [show,setShow]=useState(true)
return<div>
{show? <Child data={data}/>:""}
<button onClick={()=>{
setName({
name:"疯狂节课",
age:data.age
})
}}>变身</button>
<button onClick={()=>{
setShow(false)
}}>卸载</button>
</div>
}
export default App;
Child.js
import React,{useState,useEffect,useRef} from 'react';
function Child(props){
let {data}=props;
let [age,setAge]=useState(8);
let ageP=useRef();
let [txt,setTxt]=useState('文字')
useEffect(()=>{
console.log(ageP.current);
},[])
//检测参数值发生变化才触发此方法 ,如果不写参数,怎样都不会触发这些方法
return <div>
<h1>name:{data.name}</h1>
<h1 ref={ageP}>age:{age}</h1>
<button onClick={()=>[
setAge(++age)
]}>长一岁</button>
<p>{txt}</p>
<input type='text' value={txt} onChange={({target})=>{
setTxt(target.value)
}}/>
</div>
}
export default Child
Hook 使用规则
- 只在最顶层使用 Hook
- 只在 React 函数中调用 Hook
- React 函数组件中
- React Hook 中 - 我自己定义 hook 时,可以调用别的hook
- 所有的 hook 必须 以 use
自定义组件
首先引入react,定义函数组件 开头必须是use,retuen里面写内容,在哪用就把组件引在哪;
利用hooks里的ref和useEffect写了一个滚动案例
hooks.js
import React,{useState} from 'react';
function useSize(){
return {
w:window.innerWidth,
h:window.innerHeight
}
}
//获取滚动条
function useScrollY(){
let [scrollY,setY]=useState(window.scrollY)
return [
scrollY,
(newScrollY)=>{
window.scrollTo(0,newScrollY);
setY(newScrollY)
}
]
}
export {useSize,useScrollY};
app.js
import React ,{useEffect}from 'react';
import {useSize,useScrollY} from './hooks'
// let [状态值,修改状态的方法]=userState(状态的初始值)
function App(){
let [scrollY,setY]=useScrollY();
useEffect(()=>{
window.onscroll=()=>{
setY(window.scrollY)
}
return()=> {
window.oncroll=null
}
},[])
return<div>
<ul>
{
[...(".".repeat(100))].map((item,index)=>{
return <li key={index}>这是第{index}个li</li>
})
}
</ul>
<a onClick={()=>{
setY(100)
}}
style={{
position:"fixed",
top:"50px",
left:"200px"
}}
>{scrollY}</a>
</div>
}
export default App;
总结
学习了react的类组件里的属性和函数组件hooks,受益匪浅,我这是个人了解,详细内容可以查看官网;