Ant Design Pro中Transfer穿梭框的實際用法(與后端交互)
該控件的屬性以及屬性的作用在ADP的官方文檔中都有介紹,但沒有講如何與后端交互,本文旨在講解該控件與后端的交互。
Ant Design官方文檔
先來看需求是怎樣的,以及實現的效果
需求:管理某個場館中的活動,可以對這個場館進行加入活動和移出活動。
如圖,初始進入到這個頁面后,韻苑體育館中有兩個活動:活動1、活動5,其余活動在右邊的框中(不屬於該場館)。選中右邊框中的活動,可以進行移入操作。選中左邊的活動,可以進行移出活動。
第一步:從后端取數據
(1)首先,我在該model(namesapce為themeList)的state中定義了兩個數據
activitys: {
list: [],
},
emptyActivitys: {
list: [],
}
activitys是上圖中屬於左邊框的活動,即場館中的活動。emptyActivitys是上圖中右邊框的活動,即不屬於該場館中的活動。這兩個集合沒有交集。
(2)接下來就是該頁面在加載的時候從后端取數據並放到這兩個屬性中,這里需要熟悉Ant Design Pro框架的用法以及React交互原理,就不再這里進行贅述了。
第二步:引進該控件
方便起見,我在使用這個控件時沒有做代碼規范,直接在該頁面的代碼上添加了該控件代碼。
@connect(({ themeList, loading }) => ({
themeList,
submitting: loading.effects['themeList/'],
}))
class App extends React.Component {
handleChange = targetKeys => {
const {
themeList: { emptyActivitys },
} = this.props; //從model中取出emptyActivitys
const { dispatch, themeList } = this.props;
var addList = []; // 需要添加到當前場館的活動
var removeList = []; // 需要移出當前場館的活動
//每次點擊按鈕,都會判斷是否有移出的活動或者移入的活動
// 移出
for (var i = 0; i < targetKeys.length; i++) {
var key = targetKeys[i];
var has = false;
for (var j = 0; j < emptyActivitys.list.length; j++) {
if (emptyActivitys.list[j].key == key) {
has = true;
break;
}
}
if (has) continue;
removeList.push(key);
}
//targetKeys是右框中活動的Key,不是選中的Key,是在點擊“移入”后(即用戶已經看到了活動移過去)才調用handleChange
// 移入
for (var i = 0; i < emptyActivitys.list.length; i++) {
var key = emptyActivitys.list[i].key;
var has = false;
for (var j = 0; j < targetKeys.length; j++) {
if (targetKeys[j] == key) {
has = true;
break;
}
}
if (has) continue;
addList.push(key);
}
//再利用兩個for循環,實現接口調用
for (var i = 0; i < addList.length; i++) {
dispatch({
type: 'themeList/api_addActivityToTheme',
payload: {
themeId: themeList.detailId,
activityId: addList[i],
},
});
}
for (var i = 0; i < removeList.length; i++) {
dispatch({
type: 'themeList/api_deleteActivityFromTheme',
payload: {
themeId: themeList.detailId,
activityId: removeList[i],
},
});
}
};
render() {
const {
themeList,
themeList: { activitys, emptyActivitys },
} = this.props;
var list = [];
var keys = [];
for (var i = 0; i < activitys.list.length; i++) {
// 把場館中的活動的id賦值給key屬性
activitys.list[i].key = activitys.list[i].activityId;
// 把場館中的活動加入到集合list中
list.push(activitys.list[i]);
}
for (var i = 0; i < emptyActivitys.list.length; i++) {
emptyActivitys.list[i].key = emptyActivitys.list[i].activityId;
list.push(emptyActivitys.list[i]);
keys.push(emptyActivitys.list[i].key);
} //keys保留着不屬於當前場館的活動ID
return (
<Transfer
dataSource={list}
showSearch
listStyle={{
width: 250,
height: 300,
}}
operations={['移出', '移入']}
targetKeys={keys} //targetKeys是頁面右邊的框:即不屬於當前場館的活動
onChange={this.handleChange}
titles={[themeList.detailName, '所有活動']}
render={item => `${item.title}-${item.label}`}
/>
);
}
}
1、@connect不用介紹,用於將該控件與指定的medel綁定。
2、該控件中只含有一個方法:handleChange
3、在transer控件的屬性中,targetKeys指的是右邊框中的集合的Keys,所以我首先自定義了一個空的keys,然后把empyActivitys的key放到keys中。dataSource指的是所有的集合,即左邊和右邊的合集。所以在render中會有兩個for循環,一個是將所有活動放在list中,另一個是將非場館活動放在keys中。
4、選中活動,點擊按鈕,會觸發handleChange函數(點擊按鈕才觸發,不是選中活動)。在該函數中,我定義了addList和removeList,用於指定哪些活動被添加或者被移除。
5、用兩個for循環,對addList和removeList進行填充。
6、再用兩個for循環,對addList和removeList中的每個元素進行相應接口的調用。
第三步:修改當前的activitys和emptyActivitys
在完成上述的加入和移出活動后,此時的activitys和emptyActivitys應該被改變,但在實際的model中他們是不會變的,所以只能自己手動的進行更改。
先看看model中的effects的方法:
*api_deleteActivityFromTheme({ payload }, { call, put }) {
var activityId = payload.activityId;
const response = yield call(api_deleteActivityFromTheme, payload);
if (isResponseSuccess(response)) {
// success
yield put({
type: 'save_deleteActivityFromStadium',
payload: activityId,
});
} else {
}
},
*api_addActivityToTheme({ payload }, { call, put }) {
var activityId = payload.activityId;
const response = yield call(api_addActivityToTheme, payload);
if (isResponseSuccess(response)) {
// success
yield put({
type: 'save_api_addActivityToStadium',
payload: activityId,
});
} else {
}
},
上述代碼正是那最后兩個for循環調用的接口
然后該改變是在model中的reducer中進行改變的:
save_api_addActivityToStadium(state, action) {
var l = null;
var list = [];
for (var i = 0; i < state.emptyActivitys.list.length; i++) {
if (state.emptyActivitys.list[i].activityId == action.payload) {
l = state.emptyActivitys.list[i];
} else {
list.push(state.emptyActivitys.list[i]);
}
}
state.emptyActivitys.list = list;
state.activitys.list.push(l);
return {
...state,
};
},
save_deleteActivityFromStadium(state, action) {
var l = null;
var list = [];
for (var i = 0; i < state.activitys.list.length; i++) {
if (state.activitys.list[i].activityId == action.payload) {
l = state.activitys.list[i];
} else {
list.push(state.activitys.list[i]);
}
}
state.activitys.list = list;
state.emptyActivitys.list.push(l);
return {
...state,
};
},
簡單來說,就是在加入和移出后,我要更新activitys和emptyActivitys這兩個數據,否則會造成邏輯的錯誤。