不论在js
还是ts
中,数组和对象都是引用类型,直接赋值,传递的是变量的引用,所以在使用setState修改数组或者对象的值时候,要注意将变量进行拷贝
!!!!
| | 避免使用(会改变原始数组) | 推荐使用(会返回一个新数组) |
| -------- | -------------------------- | ---------------------------- |
| 添加元素 | push
、unshift
| concat
、[...,arr]展开语法 |
| 删除元素 | pop
、shift
、splice
| filter
、slice
|
| 替换元素 | splice
,arr[i]=...
赋值 | map
|
| 排序 | reverse
、sort
| 先将数组复制一份 |
在前面追加的方法同理。
import { useState } from "react" function App() { const [list,setList] = useState([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ setList([...list,{id:4,text:"ddd"}])//在后面追加元素 } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App
import { useState } from "react" function App() { const [list,setList] = useState([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ // setList([...list,{id:4,text:"ddd"}])//在后面追加元素 setList([...list.slice(0,1),{id:4,text:'ddd'},...list.slice(1)]) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App
注意在写tsx的过程中,要注意类型的匹配!,通过map方式遍历数组,改变数组的值以后返回的是一个新的数组。
import { useState } from "react" interface List{ id:number text:string } function App() { const [list,setList] = useState<List[]>([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ // setList([...list,{id:4,text:"ddd"}])//在后面追加元素 // setList([...list.slice(0,1),{id:4,text:'ddd'},...list.slice(1)]) setList(list.map((item):List=>{ if(item.id===2){ return {...item,text:"ddd"} } else{ return item } })) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App
使用浅拷贝反转数组。
import { useState } from "react" interface List{ id:number text:string } function App() { const [list,setList] = useState<List[]>([ {id:1,text:'aaa'}, {id:2,text:'bbb'}, {id:3,text:'ccc'}, ]) function hand(){ const cloneList = [...list] cloneList.reverse() setList(cloneList) } return ( <div> <button onClick={hand}>add</button> <ul> { list.map((e)=><li key={e.id}>{e.text}</li>) } </ul> </div> ) } export default App
不支持嵌套数组和对象的变化:当原始对象包含了嵌套的数组或对象,并且这些嵌套的数组或对象发生变化时,浅拷贝并不会触发对这些嵌套对象的拷贝。这意味着拷贝后的对象仍然会包含原始对象中的嵌套数组或对象的引用,而不是它们的独立副本。这可能导致无法实现预期的结果。
首先需要安装一个第三方库
npm install @types/lodash
同样实现反转数组的功能
通常使用的是浅拷贝的方式。.传播语法是浅的它只复制一层深的东西。这使它变得很快,但这也意味着如果你想更新一个嵌套的属性,你将不得不多次使用它。
import { useState } from "react" interface Info{ username:string age:number } export default function App(){ const [info,setInfo] = useState<Info>({ username:'lyt', age:22 }) function change(){ setInfo({ ...info, username:'liyatai' }) } return <div> <button onClick={change}>change</button><br /> {info.age} <br /> {info.username} </div> }
如果对象的属性还有对象,那么浅拷贝就不方便了,这里可以用上文提到的深拷贝。
import { cloneDeep } from "lodash" import { useState } from "react" interface Info{ username:{ first:string last:string } age:number } export default function App(){ const [info,setInfo] = useState<Info>({ username:{ first:"Bruse", last:"Lee" }, age:22 }) function change(){ const cloneList = cloneDeep(info) cloneList.username.first="David" setInfo(cloneList) } return <div> <button onClick={change}>change</button><br /> {JSON.stringify(info)} </div> }
深拷贝看似很方便,但是在性能上是有缺陷的,而浅拷贝就有比较好的性能,所以使用哪种方式要根据具体的使用场景而定。