Element對話框組件Dialog在我們的實際項目開發中可以說是一個使用頻率較高的組件,它能為我們展示提示的功能,如:業務模塊提交前展示我們曾經輸入或選擇過的業務信息,或者展示列表信息中某項業務的具體列表數據;也能為我們展示一些表單操作的需求,如:個人信息的添加或編輯等。Dialog組件使用起來也很方便,稍微封裝一下就是一個公共的對話框組件,顯示或隱藏也可以通過它的visible屬性來設置即可。
這是官網上給出的一個Dialog組件的基本用法:
<el-button type="text" @click="dialogVisible = true">點擊打開 Dialog</el-button>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<span>這是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">確 定</el-button>
</span>
</el-dialog>
<script>
export default {
data() {
return {
dialogVisible: false
};
},
methods: {
handleClose(done) {
this.$confirm('確認關閉?')
.then(_ => {
done();
})
.catch(_ => {});
}
}
};
</script>
使用起來若是只單純的用作提示或展示信息,那再好不過,只是有時我們會用它來操作個人信息和業務信息的添加或編輯,這就會出現一些Element官網沒有給出解決辦法的問題亦或這樣那樣使用可能會導致的某種問題,比如我們在Dialog組件中加入了有正則驗證的表單,就可能會出現獲取不到表單DOM以及表單的正則驗證一會兒有效,一會兒又失效的情況,以及在彈出對話框后,其里邊的表單輸入框明明有值,卻提示不能為空的正則驗證,不知道的同學,還以為是Element的坑呢,其實不是。
△ 在彈出編輯的對話框后帶出活動名稱的值,卻出現了“請輸入活動名稱”的正則驗證提示
那么,是什么導致這樣的問題的出現呢?
很簡單,是因為DOM元素還沒有渲染完成導致的,也就是說,當Dialog對話框彈出后,這個對話框及其里邊的DOM元素是有一個渲染的過程的,這個過程可能我們肉眼很難察覺到。大概的意思跟Vue的生命周期函數created和mounted類似,在Vue的生命周期函數created中,我們是拿不到頁面的DOM元素的,因為此時DOM元素並未進行任何渲染,但在mounted函數中就不一樣了,該函數執行時所有的DOM元素掛載和渲染都已完成,此時在該函數中進行任何DOM操作都不會有問題 。
話是這么說,可在調用Dialog對話框的頁面中如何拿到其DOM元素呢,之前說的在對話框中嵌套的表單的正則驗證會失效的問題改如何解決呢?或者明明表單有值,卻正則驗證提示“不能為空”呢?
此時,我們就要隆重有請Vue的殺手鐧'nextTick'出場了。
Vue官方文檔的說法是:在下次DOM更新循環結束之后執行延遲回調。在修改數據之后立即使用這個方法,獲取更新后的DOM。詳細一點的解釋是:
Vue 異步執行DOM更新。只要觀察到數據變化,Vue 將開啟一個隊列,並緩沖在同一事件循環中發生的所有數據改變。如果同一個watcher被多次觸發,只會被推入到隊列中一次。這種在緩沖時去除重復數據對於避免不必要的計算和DOM操作上非常重要。然后,在下一個的事件循環“tick”中,Vue 刷新隊列並執行實際 (已去重的) 工作。Vue 在內部嘗試對異步隊列使用原生的 Promise.then 和MessageChannel,如果執行環境不支持,會采用 setTimeout(fn, 0)代替。
巴拉巴拉說了那么多,其實就是在彈出Dialog對話框時執行nextTick就可以了,然后在nextTick的函數中執行DOM操作或者給表單賦值就不會出現上述的問題了。
還有一點需要注意,阿拉在點擊編輯按鈕彈出對話框並給對話框中的表單賦值后,如果我們在進行了一系列的操作如提交修改后的信息並關閉了對話框或者直接點擊取消按鈕關閉了對話框,那么在關閉時最好再執行一下Element提供的表單的重置方法resetFields(),防止它又出現什么幺蛾子!