我今年主要作活動,會遇到不少預定報名的功能,一個頁面,兩個報名表單(內嵌在頁面的表單和彈窗表單),其實兩表單內容功能都是同樣的,只是佈局會有些不一樣,可是由於咱們如今的項目並無加入什麼狀態管理的模塊,因此只能手動實現同步數據的功能。以前再遇到這種需求的時候由於時間問題,就寫了兩個表單組件分別管理本身的數據,可是這種解決方案真的是費力不討好,稍微有些改動就要兩個表單組件同時改,因此我就想了些優化方案:html
補充:我主要主要是寫在pc端同步表單的,若是在移動端的話,若是兩表單內容一致,可直接使用一個表單組件,在彈窗時,讓該表單組件固定定位,並使嵌入表單那一塊元素固定高度就能夠了vue
一.目標:vuex
一個表單組件,在同一頁面中可在不一樣地方同時使用,並實現數據同步功能redux
二.解決方案:(前提:已寫好表單組件,實例化該表單組件即表單對象)佈局
1.表單組件可直接做爲內嵌表單,而後吧表單對象傳給彈窗組件,在彈窗組件內渲染出來。優化
結果:雖然功能實現了,但問題是頁面中僅能同時渲染一個表單組件。不能同時顯示,棄this
2.再實例化一個表單組件的對象,傳遞給彈窗組件,在彈窗組件中渲染,並維護這個新表單對象的數據。orm
結果:2.1雖然功能實現了,但數據不能同步。由於實際上是兩個對象,因此對應的數據確定是相互獨立的,因此必須手動同步數據htm
2.2手動同步數據其實只須要在打開和關閉彈窗時,判斷兩表單對象中的數據是否一隻,而後對應更新表單對象數據並從新渲染便可對象
2.3在彈窗表單中,常須要報名成功後關閉彈窗,由於在報名成功後須要修改整個頁面中部分組件的狀態,因此能夠直接在修改狀態時,關閉彈窗
三.總結:
哈哈哈,使用解決方案二,最終試驗成功。仍是redux,vuex這些狀態管理機制好用啊,直接就同步了,咱們這個backbone項目基本上只是用了view層,後續在活動不忙的時候我試試看可否把其他的集成進來,就不用這麼繞了。
四.關鍵代碼:
import Form from './form'; // 表單組件
import FormDialog from './formDialog1'; // 彈窗組件
this.form = new Form({
cityCode,
signUpStatus,
id,
updateSignUpStatus: this._updateSignUpStatus // 報名成功後會修改頁面狀態
});
this.form1 = new Form({ // 嵌入頁面的表單組件
cityCode,
signUpStatus,
id,
toggleShowSignSucess: this._toggleShowSignSucess,
});
this.formDialog = new FormDialog({
form: this.form1, // 將表單組件對象放入彈窗組件中
syncFormData: this._syncFormData // 用戶關閉彈窗時同步嵌入表單組件數據
});
// 修改頁面報名狀態
updateSignUpStatus(signUpStatus) {
Object.assign(this.options, { signUpStatus });
if (signUpStatus) {
// 隱藏表單彈窗
if (this.formDialog.options.show) this.formDialog.toggleShow();
// 更新兩表單改變狀態
this.form.update({ signUpStatus });
this.form1.update({ signUpStatus });
}
}
// 同步表單數據
syncFormData(show) {
if (!show) { // 打開彈窗,同步彈窗表單數據
if (JSON.stringify(this.form.options) !== JSON.stringify(this.form1.options)) {
this.form1.update(this.form.options);
}
} else { // 關閉彈窗,同步嵌入表單數據
if (JSON.stringify(this.form.options) !== JSON.stringify(this.form1.options)) {
this.form.update(this.form1.options);
}
}
}
// 渲染方法
render() {
this.$el.find('.form-contianer').html(this.form.render()); //嵌入表單組件放入頁面
this.$el.find('.formDialog-container').html(this.formDialog.render());//彈窗表單組件放入頁面
}