業務場景
- 在頁面內容被編輯后,用戶跳轉其他路由,需要提示用戶:當前頁面有改動,確認離開后再進行跳轉,以防編輯數據丟失。
代碼
beforeRouteLeave (to, from, next) {
this.targetName = to.name // 提示框點擊確認后跳轉的 路由
if (this.checkEdit()) { // 是否對頁面進行了編輯
this.dialogVisible = true // 打開離開頁面的提示框
next(false)
} else {
this.dialogVisible = false
next()
}
}
- VUE 提供一個鈎子函數
beforeRouteLeave
, 離開當前路由時會先觸發該函數,當然也有beforeRouteEnter
,進入路由前先觸發該函數。
- to: 目標路由的相關信息 對象
- from:當前路由的相關信息 對象
- next:實行跳轉的 函數。傳入false,不進行跳轉。
檢測頁面是否編輯
我的思路是在頁面初始化時,設置一個對象保存舊有的值。例如在編輯頁面初始化編輯數據時:
data () {
return: {
formData: {},
oldData: {}
}
},
mounted () {
init() {
axios.get(‘/example).then(res => { // 這里就簡寫了
Object.assign(this.oldData, res.data) //這里對已有的編輯數據進行保存
this.formData = res.data // 這里正常回顯
})
}
}
進行存儲后即可保留用戶編輯頁面時的初始狀態。然后離開頁面時進行校驗:
checkEdit () {
for (let key in this.oldValObj) {
if (this.oldValObj[key] != this.formData[key]) {
return true
}
}
return false
}
至此,一般情況下的編輯改動即完成了。
但如果你獲得表單數據,是一個對象內還包含對象的數據,
Object.assign()
就會有錯了,它僅支持淺拷貝。我們此時需要使用的是深復制
方法了,如下:
deepClone (obj) {
let objClone = Array.isArray(obj) ? [] : {};
if(obj && typeof obj === ‘object’){
for(let key in obj){
// 判斷是不是自有屬性,而不是繼承屬性
if(obj.hasOwnProperty(key)){
//判斷ojb子元素是否為對象或數組,如果是,遞歸復制
if(obj[key]&&typeof obj[key] === ‘object’){
objClone[key] = this.deepClone(obj[key]);
}else{
//如果不是,簡單復制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
這種情況下,checkEdit
也需要調整。
/* @param x {Object} 對象1
* @param y {Object} 對象2
* @return {Boolean} true 為相等,false 為不等
*/
checkEdit(x, y) { // 指向同一內存時
if (x === y) {
return true;
} else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length) {
return false;
}
for (var prop in x) {
if (y.hasOwnProperty(prop)) {
if (!deepEqual(x[prop], y[prop])) {
return false;
}
}
else {
return false;
}
}
return true;
} else {
return false;
}
}
總結:
對於一般的表單問題,能確定數據對象中不會包含對象的情形時,數據比較簡單,使用第一種簡易版本會方便調試。數據類型比較復雜的情況,就應該考慮深復制,深對比的思路了。