React 属性, 函数式组件以及Hook
Posted ZZZ --- jh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React 属性, 函数式组件以及Hook相关的知识,希望对你有一定的参考价值。
属性以及函数式组件,Hook
五个属性: PureComponent、ref、children、dangerouslySetInnerhtml、key
React的五个属性
PureComponent
个人理解是PureComponent 是类组件的情况下,它是用来继承的
pureComponent 提供了一个具有浅比较,的shouldComponrentUpdate方法其他和component完全一致
是react中创建组件的一种方式,可以减少不必要的更新,易于实施,进而提升性能,每次更新会自动帮你对更新前后的props和state进行一个简单对比, 来决定是否进行更新.只要把继承类从 Component
换成 PureComponent
即可,可以减少不必要的 render
操作的次数,从而提高性能,而且可以少写 shouldComponentUpdate
函数,节省了点代码。
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:'yyqx')
>升级</button>
<button onClick=()=>
list.push('新人');
this.setState(list:[...list])
>扩大</button>
</div>
)
export default App;
以上这个案例当继承PureComponent时,list:[...list]
必须写成这样扩大的这个按钮才会新增数据的; 当继承Component时, list:[...list]
也可以写成list
ref
-
注意: 再组件挂载完成之后及更新之后使用
-
旧版 ref —> 字符串类型绑定
先安装
npm i better-scroll
再引入
import BScroll from "better-scroll";
import React, PureComponent, Component from 'react'; import BScroll from "better-scroll"; // new BScroll() let list = [...('.'.repeat(100))]; // console.log(list); class App extends PureComponent // 组件挂载完成之后 componentDidMount() // 通过this.refs绑定ref的名字来获取dom节点 // console.log(this.refs.box); new BScroll(this.refs.box); render() return ( <div style= height:'300px', border:'1px solid red', overflow:'hidden' ref='box' > <ul style= margin:0,padding:0,listStyle:'none' > list.map((item,index)=> return <li key=index>这是第index个li</li> ) </ul> </div> ) export default App;
这个案例中滚动效果是可以实现的,但是控制台会给一个提示
Warning: A string ref, "box", has been found within a strict mode tree. String refs are a source of potential bugs and should be avoided. We recommend using useRef() or createRef() instead. Learn more about using refs safely here
(字符串ref, “box”,在严格模式树中被发现。字符串引用是潜在错误的来源,应该避免); 可以把index.js中的<React.StrictMode></React.StrictMode>
这个标签删除掉就不会警告了; 此时就要用到下面的这个方法了. -
新版 ref —> createRef()
通过在class中使用createRef()方法创建一些变量,可以将这些变量绑定到标签的ref中,那么该变量的current则指向绑定的标签dom
import React, PureComponent, Component, createRef from 'react'; import BScroll from "better-scroll"; // new BScroll() let list = [...('.'.repeat(100))]; // console.log(list); class App extends PureComponent box = createRef(); componentDidMount() // console.log(this); // console.log(this.box.current); new BScroll(this.box.current) render() return ( <div style= height:'300px', border:'1px solid red', overflow:'hidden' ref = this.box > <ul style= margin:0,padding:0,listStyle:'none' > list.map((item,index)=> return <li key=index>这是第index个li</li> ) </ul> </div> ) export default App;
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;
-
可以自定义结构的组件的常用形式
- children
- 传递函数
- 传递子组件
import React, PureComponent from 'react'; class Popwindow extends PureComponent state = close:false render() // console.log(this); let close = this.state; let children = this.props; return ( <div style= border:'3px solid #ccc', display: close ? "none" : 'block' > children <button onClick=()=> this.setState( close:true ) >关闭</button> </div> ) class App extends PureComponent state = show:false, man:false render() let show, man = this.state; return ( <div> show?(<Popwindow > <h1>yyqx</h1> <p>qzh</p> </Popwindow>):'' man?(<Popwindow > <h1>qxx</h1> <p>byg</p> </Popwindow>):'' <button onClick=()=> this.setState(show:true) >显示弹框1</button> <button onClick=()=> this.setState(man:true) >显示弹框2</button> </div> ) export default App;
dangerouslySetInnerHTML
-
直接设置标签的innerHTML
-
要接收的插值只能是一个对象
-
有个固定的属性:
__html
-
可以用来接收数据,但是接收的只能是后端的数据,后端服务器发送过来的数据是校检过的,是安全的;不要接收前端自己写的数据
-
import React, PureComponent from 'react'; let message = `<h1>yyqx</h1> <p>qzh</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)=> 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;
函数式组件
16.7版本之后新增的
函数式组件中, 没有state和生命周期; 所以又称为无状态组件; 在早期16.7(react)版本中,被当前纯渲染组件来用
函数名就是组件名;
组件的第0个参数是 props - 接收父级传过来的信息
没有this; 没有state和生命周期;
必须要有return, return里面定义的是该组件渲染的内容
在16.7之前函数组件一直当做渲染组件来使用
<!-- app.js -->
import React from 'react';
function Child(props)
return <h1>props.info </h1>
function App()
// console.log(this); // undefined
// return <div>哈哈哈</div>
return <Child info='呵呵' />
export default App;
React hooks
react hooks 是react16.8中的新增功能. 无需编写class类的情况下使用state状态和其他react功能.
英文文档参考: https://reactjs.org/docs/hooks-intro.html
中文文档参考: https://reactjs.bootcss.com/docs/hooks-intro.html
什么是Hook
Hook 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。Hook 不能在 class 组件中使用 —— 这使得你不使用 class 也能使用 React.
React Hooks的优势
- 简化组件逻辑
- 复用状态逻辑
- 无需使用类组件编写
- 完全可选的
- 100%向后兼容. 不包含任何破坏性改动
- 现在可用
常用Hook
-
useState – 让函数式组件拥有状态
let [状态的值,修改状态的方法] = useState(状态的初始值);
let [state, setState] = useState(initialState);
useState 唯一的采纳数就是初始state.
<!-- app.js --> import React, useState from 'react'; import Child from './Child' // let [状态的值,修改状态的方法] = useState(状态的初始值); function App() let [data,setData] = useState( name:"yyqx", age:20 ); return <div> <Child data=data /> <button onClick=()=> setData( name:'Jackson', 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
做了什么? 通过使用这个 Hook,可以告诉 React 组件需要在渲染后执行某些操作。React 会保存你传递的函数并且在执行 DOM 更新之后调用它。为什么在组件内部调用
useEffect
? 将useEffect
放在组件内部让我们可以在 effect 中直接访问count
state 变量(或其他 props)。不需要特殊的 API 来读取它 —— 它已经保存在函数作用域中。Hook 使用了 javascript 的闭包机制,而不用在 JavaScript 已经提供了解决方案的情况下,还引入特定的 React API.useEffect
会在每次渲染后都执行吗? 是的,默认情况下,它在第一次渲染之后和每次更新之后都会执行。React 保证了每次运行 effect 的同时,DOM 都已经更新完毕。<!-- Child.js --> import React, useState, useEffect from 'react'; function Child(props) let data = props; let [age,setAge] = useState(8); // 第二个参数数组中放的是监测的内容 useEffect(()=> console.log('挂载了'); ,[]) // 卸载的时候记得卸载return里面 useEffect(()=> return ()=> console.log('卸载了'); ,[]) useEffect(()=> console.log('更新了'); ,[age]) return <div> <h1>name:data.name </h1> <h1>age:age </h1> <button onClick=()=> setAge(++age) >涨一岁</button> </div> export default Child;
<!-- app.js --> import React, useState from 'react'; import Child from './Child' function App() let [data,setData] = useState( name:"yyqx", age:20 ); let [show,setShow] = useState(true); return <div> show ? <Child data=data /> : "" <button onClick=()=> setData( name:'Jackson', age:data.age ); > 变身 </button> <button onClick=()=> setShow(false) >卸载
以上是关于React 属性, 函数式组件以及Hook的主要内容,如果未能解决你的问题,请参考以下文章