el-dialog關(guān)閉再打開后窗口內(nèi)容不刷新問題及解決
頁面中有增加和編輯兩個功能,由于彈窗樣式都是一樣的,于是將它拆分成一個子組件,父組件把狀態(tài)傳給子組件,子組件根據(jù)這個狀態(tài)判斷是做編輯操作還是新增操作.
編輯:

添加:

問題一:但是這樣遇到了一個問題,在編輯時,只有第一次點編輯時,回顯的數(shù)據(jù)才能正確顯示。
隨后再點其他部門的編輯,數(shù)據(jù)顯示不正確了,還是第一次點開的那個部門的數(shù)據(jù).
原因:現(xiàn)在的代碼中,獲取部門詳情這個動作在子組件的created中發(fā)出的,而created鉤子只會執(zhí)行一次:后續(xù)點擊關(guān)閉彈層時,子組件被沒有銷毀,它只是隱藏了。
問題二:點擊編輯之后再點擊添加,添加表單中也會出現(xiàn)部門詳情數(shù)據(jù)
原因:是關(guān)閉彈窗時,子組件被沒有銷毀,它只是隱藏了,也沒有清空里面表單的數(shù)據(jù)
我們先來看問題一數(shù)據(jù)不更新
問題一:回顯數(shù)據(jù)不更新
解決方案一:在父組件中
給父組件中的el-dialog添加destroy-on-close屬性
查閱了 Dialog 對話框 相關(guān)文檔:

我們可以給它加上這個屬性
<el-dialog
:title="isEdit?'編輯':'新增'"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="resetForm"
>
<!-- element ui 中dialog的方法destroy-on-close,關(guān)閉時銷毀 Dialog 中的元素 -->
<deptDialog
:id="fatherId"
:origin-list="originList"
:is-edit="isEdit"
destroy-on-close
@success="doSuccess"
@doClose="dialogVisible=false"
/>
</el-dialog>解決方案二:直接在內(nèi)容上加上屬性 v-if="dialogVisible"
v-if="dialogVisible",關(guān)閉和打開彈層,銷毀和創(chuàng)建組件
v-if會由false=>true,會觸發(fā)beforeCreate,created,beforeMount,mounted 鉤子。
由true=>false,會觸發(fā) beforeDestroy,destroyed 鉤子。
所以我們只要給它加上v-if,取值為控制彈窗顯示隱藏的值,我們打開彈窗時它就會重新重建,關(guān)閉彈窗的話就會銷毀,
這樣每次打開彈窗都會執(zhí)行created鉤子里的獲取部門詳情函數(shù),問題就解決了
這樣做雖然簡單,但是它會有性能消耗,其中的ajax請求也會隨著組件的創(chuàng)建和銷毀重復(fù)執(zhí)行
<el-dialog
:title="isEdit?'編輯':'新增'"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="resetForm"
>
<!-- 解決數(shù)據(jù)不更新的問題:v-if="dialogVisible",關(guān)閉和打開彈層,銷毀和創(chuàng)建組件 -->
<deptDialog
v-if="dialogVisible"
:id="fatherId"
:origin-list="originList"
:is-edit="isEdit"
@success="doSuccess"
@doClose="dialogVisible=false"
/>
</el-dialog>解決方案三:在父組件中通過引用找到子組件
在父組件中,每次打開彈層時,找到子組件,要求它去發(fā)請求獲取詳情
添加ref引用:
<el-dialog
:title="isEdit?'編輯':'新增'"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="resetForm"
>
<!-- 添加引用: ref="deptDialog" -->
<deptDialog
:id="fatherId"
ref="deptDialog"
:origin-list="originList"
:is-edit="isEdit"
@success="doSuccess"
@doClose="dialogVisible=false"
/>
</el-dialog>在編輯時:找到子組件,要求它去發(fā)請求獲取詳情
// 編輯
doEdit(id) {
//isEdit設(shè)為true,表示當(dāng)前狀態(tài)為編輯
this.isEdit = true
this.fatherId = id
this.dialogVisible = true
// 解決數(shù)據(jù)不更新的問題: this.$refs.deptDialog.loadDepartDetail()
// 注意:由于DOM更新是異步的,此處要用$nextTick()
this.$nextTick(() => {
this.$refs.deptDialog.loadDepartDetail()
})
//或者放在宏任務(wù)里,如延時器中
// setTimeout(() => {
// this.$refs.deptDialog.loadDepartDetail()
// }, 0)
},子組件:
created() {
//加載部門負(fù)責(zé)人列表數(shù)據(jù)
this.loadEmployeesSimples()
//如果為編輯狀態(tài),獲取部門詳情
if (this.isEdit) this.loadDepartDetail()
},解決方案四:在子組件內(nèi)監(jiān)聽id的變化(不推薦使用)
在子組件內(nèi)部添加一個偵聽器:監(jiān)聽當(dāng)前id的變化
created() {
//加載部門負(fù)責(zé)人列表數(shù)據(jù)
this.loadEmployeesSimples()
//如果為編輯狀態(tài),獲取部門詳情
if (this.isEdit) this.loadDepartDetail()
},
watch: {
id: function(newVal, oldVal) {
//調(diào)用獲取部門詳情函數(shù)
this.loadDepartDetail()
}
},
//上面這種寫法不會立即觸發(fā),還需在created()中調(diào)用一次,用下面這種方法就不需要在created()中調(diào)用了
//watch: {
// id: {
// handler: function(newVal, oldVal) {
// this.loadDepartDetail()
// },
// immediate: true
// }
// },
//immediate表示在watch中首次綁定的時候,是否執(zhí)行handler,值為true則表示在watch中聲明的時候,就立即 //執(zhí)行handler方法,值為false,則和一般使用watch一樣,在數(shù)據(jù)發(fā)生變化的時候才執(zhí)行handler。所以當(dāng)為 //true時 在created周期里就可以不用在寫 已經(jīng)在watch 中寫過的方法了但是這種方法在清空表單數(shù)據(jù)的時候會有一個bug,不推薦使用,后面會詳細(xì)講到.
解決方案五:給子組件添加key值
key就是給每一個vnode的唯一id,可以依靠key更準(zhǔn)確地拿到oldVnode中對應(yīng)的節(jié)點。
避免組件“原地復(fù)用”帶來的副作用,加上key,可以讓組件在數(shù)據(jù)變化時強(qiáng)制更新組件。
<el-dialog
:title="isEdit?'編輯':'新增'"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="resetForm"
>
<!-- 給子組件添加key值 -->
<deptDialog
:id="fatherId"
:key="fatherId"
:origin-list="originList"
:is-edit="isEdit"
@success="doSuccess"
@doClose="dialogVisible=false"
/>
</el-dialog>問題二:添加表單中也會出現(xiàn)部門詳情數(shù)據(jù)
還是上面說到的問題,關(guān)閉彈層時,子組件被沒有銷毀,它只是隱藏了,所以我們需要手動清除表單中的數(shù)據(jù).
(方案一添加destroy-on-close屬性,方案二v-if="dialogVisible",方案五給子組件添加key值,不會出現(xiàn)這個問題)
分析:有如下三個操作都需要我們?nèi)ブ刂帽韱?/strong>
- 取消
- 確定
- 用戶直接點擊關(guān)閉
所以我們可以在Dialog的@close的回調(diào)中寫一次代碼就行了
父組件:
// 給父組件添加 @close="resetForm"
<el-dialog
:title="isEdit?'編輯':'新增'"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@close="resetForm"
>
//給子組件添加 ref="deptDialog"
<deptDialog
v-if="dialogVisible"
ref="deptDialog"
:origin-list="originList"
:is-edit="isEdit"
@success="doSuccess"
@doClose="dialogVisible=false"
/>
</el-dialog>
// 重置子組件表單
resetForm() {
// 調(diào)用子組件中的重置表單方法
this.$refs.deptDialog.resetForm()
}子組件:
// 在父組件中 dialog close時,來調(diào)用
resetForm() {
// resetFields是element-ui中的el-form組件提供一個api,它的作用是:
// 1. 重置表單數(shù)據(jù)
// 2. 清空校驗結(jié)果(頁面上紅色的提示)
this.$refs.deptForm.resetFields()
}清空表單數(shù)據(jù)的bug
問題重現(xiàn)
- 選中a部門,進(jìn)行編輯,故意讓編輯出錯,在表單上出現(xiàn)錯誤
- 點擊取消
- 再次對a部門進(jìn)行編輯,發(fā)現(xiàn)數(shù)據(jù)沒有顯示出來
原因分析
上面的操作中,前后兩次編輯的是同一個部門,所以子組件內(nèi)對id的watch并沒有執(zhí)行,導(dǎo)致內(nèi)容為空
所以不推薦使用方案四,對id進(jìn)行偵聽
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
前端請求超時截斷axios?timeout設(shè)置未生效情況解決記錄
在項目中遇到了后臺接口返回數(shù)據(jù)慢的時候往往需要設(shè)置請求失效時間,在項目中遇到設(shè)置timeout失效問題由此記錄下來,這篇文章主要給大家介紹了前端請求超時截斷axios?timeout設(shè)置未生效情況解決的相關(guān)資料,需要的朋友可以參考下2024-07-07
vue實現(xiàn)excel表格的導(dǎo)入導(dǎo)出的示例
本文主要介紹了vue實現(xiàn)excel表格的導(dǎo)入導(dǎo)出的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
vue中動態(tài)渲染數(shù)據(jù)時使用$refs無效的解決
這篇文章主要介紹了vue中動態(tài)渲染數(shù)據(jù)時使用$refs無效的解決方案,具有很好的參考價值。希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01

