React實現(xiàn)點(diǎn)擊刪除列表中對應(yīng)項
點(diǎn)擊刪除按鈕,刪除列表中對應(yīng)項本來是React比較基礎(chǔ)的應(yīng)用,可是應(yīng)用情況變得復(fù)雜了以后,我還真想了一會兒才搞定。
簡化一下應(yīng)用場景:點(diǎn)擊新增按鈕,增加一條輸入框,點(diǎn)擊輸入框旁邊的按鈕,刪除該輸入框(不能刪錯了啊)。
先說第一種方法
問題剛上手,首先規(guī)劃級別:一個輸入框和對應(yīng)刪除按鈕為一個子組件,整體為父組件即可方便處理。
注意的點(diǎn):生成的一坨輸入框是一個數(shù)組,為了準(zhǔn)確刪掉對應(yīng)項,生成時要編號。點(diǎn)擊刪除按鈕要反饋對應(yīng)編號,然后進(jìn)行刪除。
現(xiàn)在的邏輯是:整個待展示列表(由子組件組成的數(shù)組)是個state,添加按鈕會增加一個元素到這個state里面,添加的方法如下:
add(){
var lists=this.state.lists;
lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);
this.setState({lists:lists})
}
注意一點(diǎn),這個index屬性是固定的,子組建生成后就固定了,這就為你未來挖了一個坑。
刪除按鈕當(dāng)然就是從這個state列表里刪除對應(yīng)元素了,問題一來了,我怎么知道是第幾個元素?一拍腦袋這還不簡單,event.target 獲取點(diǎn)擊的標(biāo)簽,在標(biāo)簽上寫個index屬性告訴delete方法是第幾個元素不就得了?試了發(fā)現(xiàn)不行,看看文檔,event.target確實獲取dom元素沒毛病,但是index這個屬性原生dom根本不承認(rèn)啊,怎么辦?data-index就行了,前面加 data- 就是dom承認(rèn)的自定義屬性了。
寫完了又想起了兩個方法,一個是在刪除按鈕綁定刪除事件的時候,.bind(this,index),index是你準(zhǔn)備刪掉的是第幾個或者表示出來你要刪哪個就行。另一個是搞個閉包,就能把index參數(shù)傳進(jìn)去了(事件綁定一個立即執(zhí)行的方程傳入?yún)?shù),該方程返回目標(biāo)方程)。
第一個問題解決,刪除的方法如下:
delete(e){
var index=e.target.getAttribute("data-index");
var lists=this.state.lists;
lists.splice(index,1);
this.setState({lists:lists})
}
data-index告訴你要刪除第幾個元素,然后把它從state里踢出去就行了。這回掉進(jìn)了一個真正意義上的坑:有時候刪的不是對應(yīng)的元素!亂套了!
好吧,我沉思了5分鐘,想到了為什么:生成列表的時候index已經(jīng)固定,但刪除列表的時候我們只告訴他刪除的是第index項!問題嚴(yán)重了,舉個例子,有兩項,index 0和1 你點(diǎn)0,好吧第0項刪掉了,你再點(diǎn)1,疑?沒反應(yīng)了,因為你打算刪除第1項,而列表中目前只有第0項(就是原來的第一項,原來的第0項刪除后他就成了第0項)!這會導(dǎo)致各種亂套,考慮到生成列表的index是列表長度表示的就更亂了。
解決方式:delete方法里修改一行:
lists.splice(index,1,"");
好了,刪除的元素我用空字符串代替,這樣順序和刪除的項,還有以后添加的項的index都不會亂了,給自己點(diǎn)贊。到這里第一種方法實現(xiàn)了目標(biāo)。
Code pen 地址:http://codepen.io/huanqingli/pen/dNyQez
完整代碼:
class List extends React.Component {
render() {
return (<div><input type="text" defaultValue={this.props.index}/>
<span onClick={this.props.delete} data-index={this.props.index}>X</span></div>)
}
}
class Lists extends React.Component {
constructor(props) {
super(props);
this.add=this.add.bind(this);
this.delete=this.delete.bind(this);
this.state={
lists:[]
}
}
add(){
var lists=this.state.lists;
lists.push(<List key={this.state.lists.length} index={this.state.lists.length} delete={this.delete}/>);
this.setState({lists:lists})
}
delete(e){
var index=e.target.getAttribute("data-index");
var lists=this.state.lists;
console.log(index)
lists.splice(index,1);
this.setState({lists:lists})
}
render() {
return (<div>
<span onClick={this.add}>添加</span>
{this.state.lists}
</div>)
}
}
ReactDOM.render(
<Lists/>,
document.getElementById('lists')
);
這種方法有利有弊,所以我找到了第二種方法,具體情況擇優(yōu)使用。
第二種方法。總體來講推薦這種方法。
在state里保存要展示的數(shù)據(jù),在render里動態(tài)生成子組件組,然后添加刪除都是操作保存數(shù)據(jù)的state,render里的子組件會自動刷新。這種方式應(yīng)該是更貼近React思路的,用數(shù)據(jù)展現(xiàn)界面。如果你要展現(xiàn)一組數(shù)據(jù),這種方法很自然,但如果展現(xiàn)的是一個動態(tài)的表單,稍微麻煩一點(diǎn),但也可以做,而且我依然推薦用這種方式。
這種方法做個todolist就很簡單,這里依然做上文的例子,稍微麻煩一點(diǎn),也會理解的更深入一點(diǎn)。
整體結(jié)構(gòu)和第一種方法一樣,只不過這次state里面不是子組件,先用空字符串組成的數(shù)組代替,僅僅是為了render的時候知道有幾個子組件而已。添加的時候也要push空字符串,等輸入框輸入數(shù)據(jù)后,更新state中的內(nèi)容,做到數(shù)據(jù)和界面同步。
render子組件的部分:
{this.state.lists.map(function (item,index) {
return <List key={index} index={index} delete={this.delete}/>
}.bind(this))}
添加的方法變成:
add(){
var lists=this.state.lists;
lists.push("");
this.setState({lists:lists})
}
這就能跑了,這有個小坑,稍有不慎你發(fā)現(xiàn)你怎么刪都是刪列表的最后一項,其實數(shù)據(jù)操作沒問題,關(guān)鍵是這個存在感比較低的key,必須特定項有給定的key你用動態(tài)的index他就懵了,不知道刪哪個了,他就吧最后一個刪了。廢話不多說(該程序因為key鍵取值的問題有一個小問題):
Code pen 地址:http://codepen.io/huanqingli/pen/xgxNYN
整體代碼:
class List extends React.Component {
constructor(props){
super(props);
this.upData=this.upData.bind(this);
}
upData(e){
this.props.upData(this.props.index,e.target.value)
}
render() {
return (<div><input type="text" onBlur={this.upData} defaultValue={this.props.item?this.props.item:""}/>
<span onClick={this.props.delete} data-index={this.props.index}>X</span></div>)
}
}
class Lists extends React.Component {
constructor(props) {
super(props);
this.add=this.add.bind(this);
this.delete=this.delete.bind(this);
this.upData=this.upData.bind(this);
this.state={
lists:[]
}
}
add(){
var lists=this.state.lists;
lists.push("");
this.setState({lists:lists})
}
delete(e){
var index=e.target.getAttribute("data-index");
var lists=this.state.lists;
lists.splice(index,1);
this.setState({lists:lists})
}
upData(i,x){
var lists=this.state.lists;
lists[i]=x;
console.log(lists);
this.setState({lists:lists});
}
render() {
return (<div>
<span onClick={this.add}>添加</span>
{this.state.lists.map(function (item,index) {
return <List key={item?item:index} index={index} delete={this.delete} upData={this.upData} item={item}/>
}.bind(this))}
</div>)
}
}
ReactDOM.render(
<Lists />, document.getElementById('lists')
)
這種方法經(jīng)常也會有點(diǎn)小坑,也比較好解決。
總結(jié):兩種方法各有利弊,推薦第二種,符合REACT設(shè)計思路,但第一種有時候解決問題很方便。
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關(guān)文章
詳解React如何使用??useReducer???高階鉤子來管理狀態(tài)
useReducer是React中的一個鉤子,用于替代?useState來管理復(fù)雜的狀態(tài)邏輯,本文將詳細(xì)介紹如何在React中使用?useReducer高階鉤子來管理狀態(tài),感興趣的可以了解下2025-02-02
react使用axios進(jìn)行api網(wǎng)絡(luò)請求的封裝方法詳解
這篇文章主要為大家詳細(xì)介紹了react使用axios進(jìn)行api網(wǎng)絡(luò)請求的封裝方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03
React報錯Type '() => JSX.Element[]&apos
這篇文章主要為大家介紹了React報錯Type '() => JSX.Element[]' is not assignable to type FunctionComponent解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
react中form.setFieldvalue數(shù)據(jù)回填時 value和text不對應(yīng)的問題及解決方法
這篇文章主要介紹了react中form.setFieldvalue數(shù)據(jù)回填時 value和text不對應(yīng)的問題及解決方法,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07

