v-for里面數據層次太多,或者套的組件層級太多, 數據變了,頁面沒有重新渲染,需手動強制刷新。
解決方法:運用 this.$forceUpdate()強制刷新
迫使 Vue 實例重新渲染。注意它僅僅影響實例本身和插入插槽內容的子組件,而不是所有子組件。
-------------------------------------------------------------------------------------------------------------------------------------
vue強制重新渲染四種方案對比
前言
Vue的雙向綁定屬於自動檔;在特定的情況下,需要手動觸發“刷新”操作,目前有四種方案可以選擇:
- 刷新整個頁面(最low的,可以借助route機制,不推薦)
- 使用v-if標記(比較low的,有時候不生效,不推薦)
- 使用內置的forceUpdate方法(較好的)
- 使用key-changing優化組件(最好的)
一、刷新整個頁面
this.$router.go(0)
二、使用v-if標記
如果是刷新某個子組件,則可以通過v-if指令實現。我們知道,當v-if的值發生變化時,組件都會被重新渲染一遍。因此,利用v-if指令的特性,可以達到強制刷新組件的目的。
<template>
<comp v-if="refresh"></comp>
<button @click="refreshComp()">刷新comp組件</button>
</template>
<script>
import comp from '@/views/comp.vue'
export default {
name: 'parentComp',
data() {
return {
refresh: true
}
},
methods: {
refreshComp() {
// 移除組件
this.refresh = false
// 在組件移除后,重新渲染組件
// this.$nextTick可實現在DOM 狀態更新后,執行傳入的方法。
this.$nextTick(() => {
this.refresh = true
})
}
}
}
</script>
三、forceUpdate
組件內置$forceUpdate方法,如果不能強制刷新,嘗試使用前在配置中啟用。
import Vue from 'vue' Vue.forceUpdate()
<template>
<div>
<button @click="handleUpdateClick()">Refresh當前組件</button>
</div>
</template>
export default {
methods: {
handleUpdateClick() {
// built-in
this.$forceUpdate()
}
}
}
四、key-changing
原理很簡單,vue使用key標記組件身份,當key改變時就是釋放原始組件,重新加載新的組件。
<template>
<div>
<span :key="key"></span>
</div>
</template>
<script>
export default {
data() {
return {
key: 0
}
},
methods: {
handleUpdateClick() {
this.key += 1 // 或者 this.key = new Date();
}
}
}
</script>
五、應用場景
vue具有緩存的頁面的強制刷新
有些列表頁面需要進入詳情返回時有緩存功能,但是每次進入列表頁面又需要刷新列表,這種時候就需要手動刷新頁面
const routerConfig = { path: "/List", query: { time: new Date().getTime(), } }; this.goPath(routerConfig);
List.vue created () { this.initData(); this.preTime = Number(this.$route.query.time); }, activated () { const curTime = Number(this.$route.query.time); if(this.preTime !== curTime) { document.documentElement.scrollTop = 0; this.preTime = curTime; this.listInfo = { pageSize: 10, pageContext: '', hasMore: false, list: [], }; this.initData(); } },
goPath是vue跳轉的一個封裝
main.js /** * 根據前端路由跳轉到webview * @param config * @param type inPage: 利用h5路由跳轉 */ Vue.prototype.goPath = function (routerConfig, type = 'web') { const config = routerConfig; // 統一添加參數 if (this.$route.query.isSelfManage === '1') { config.query.isSelfManage = 1; } console.log(config); if (window.__wxjs_environment === 'miniprogram') { if (window.wx) { const params = this.$router.resolve(config).href; // 添加參數,兼容跳轉問題 const toUrl = `${location.protocol}//${location.host}${location.pathname}${location.search}${params}`; if (type === 'web') { window.wx.miniProgram.navigateTo({ url: `/pages/webview/index?url=${encodeURIComponent(toUrl)}`, }); } else if (type === 'inPage') { this.$router.push(config); if (!config.replace) { this.$router.push(config); } else { this.$router.replace(config); } } else { window.wx.miniProgram.navigateTo(config); } } } else { if (!config.replace) { this.$router.push(config); } else { this.$router.replace(config); } } };
例如:進入頁面輸入框自動聚焦
一般情況下,加上以下代碼就可以聚焦
<template>
<div>
<input
placeholder="大家都在搜"
type="text"
maxlength="500"
v-model="inputInfo.msg"
@blur="resizeView"
v-focus
>
</div>
</template>
<script>
export default {
data() {
return {
inputInfo: { // 輸入框對象
num: 0, // 字數
msg: '' // 內容
},
}
},
watch: {
[`options.msg`] () {
let length = utils.fancyCount2(this.inputInfo.msg);
this.$set(this.inputInfo, 'num', length);
}
},
directives: {
focus: {
// 指令的定義
inserted: function(el) {
el.focus();
}
}
},
methods: {
/**
* input元素失去焦點時觸發
*/
resizeView () {
document.body.scrollIntoView(true);
},
}
}
</script>
但是在有緩存的頁面,一般就只有第一次會聚焦,后面進入都不會聚焦,辦法就是用第四種強制刷新輸入框來聚焦
<template>
<div>
<input
placeholder="大家都在搜"
type="text"
maxlength="500"
v-model="inputInfo.msg"
@blur="resizeView"
v-focus
:key="inputInfo.focus"
>
<button @click="handleUpdateClick()">Refresh當前組件</button>
</div>
</template>
<script>
export default {
data() {
return {
inputInfo: { // 輸入框對象
num: 0, // 字數
msg: '', // 內容
focus: '',
},
}
},
activated () {
this.inputInfo.focus = new Date().getTime();
},
methods: {
handleUpdateClick() {
// built-in
this.inputInfo.focus = new Date().getTime();
}
}
</script>
