Vue?Router解決多路由復(fù)用同一組件頁(yè)面不刷新問(wèn)題(場(chǎng)景分析)
簡(jiǎn)介
說(shuō)明
本文介紹如何解決Vue的多路由復(fù)用同一組件頁(yè)面不刷新問(wèn)題。
多路由復(fù)用同一組件的場(chǎng)景
- 多路由使用同一組件
比如:添加博客(path為:/addBlog)和編輯博客(path為:/editBlog)都對(duì)應(yīng)同一個(gè)組件(EditBlog.vue)
- 動(dòng)態(tài)路由
比如:用戶詳情頁(yè)采用動(dòng)態(tài)路由,其path為:/user/:id,組件都是UserDetail.vue
原因分析
Vue中,相同的組件實(shí)例將被重復(fù)使用。如果兩個(gè)路由都渲染同個(gè)組件,復(fù)用比銷毀再創(chuàng)建更高效。不過(guò),復(fù)用會(huì)導(dǎo)致組件的生命周期函數(shù)不會(huì)被調(diào)用。而我們通常會(huì)將調(diào)后端接口放到created或mounted等生命周期函數(shù)中,生命周期函數(shù)沒(méi)被調(diào)用,也就無(wú)法獲取后端數(shù)據(jù)。
官網(wǎng)網(wǎng)址
https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#響應(yīng)路由參數(shù)的變化
問(wèn)題復(fù)現(xiàn)
本處以博客為例。添加博客(path為:/addBlog)和編輯博客(path為:/editBlog)都對(duì)應(yīng)同一個(gè)組件(EditBlog.vue)
代碼
路由配置(router/index.js)
import Vue from 'vue' import VueRouter from 'vue-router' import BlogEdit from '../components/BlogEdit' Vue.use(VueRouter) const routes = [ { path: '/addBlog', name: 'AddBlog', component: BlogEdit }, { path: '/editBlog', name: 'EditBlog', component: BlogEdit } ] const router = new VueRouter({ routes }) export default router
主頁(yè)面(App.vue)
<template> <div id="app"> <div id="nav"> <!--<router-link to="/">Home</router-link> |--> <!--<router-link to="/about">About</router-link>--> <router-link :to="{name: 'AddBlog'}">創(chuàng)建博客</router-link> | <router-link :to="{name: 'EditBlog'}">修改博客</router-link> </div> <router-view/> </div> </template> <style> <!-- 省略 --> </style>
博客編輯頁(yè)(components/BlogEdit.vue)
<template> <div class="outer"> <div> 這是BlogEdit </div> </div> </template> <script> import LifeCycle from '../mixins/LifeCycle' export default { name: 'BlogEdit', mixins: [LifeCycle] } </script> <style scoped> .outer { margin: 20px; border: 2px solid blue; padding: 20px; } </style>
混入生命周期(mixins/LifeCycle.js)
我把生命周期的鉤子函數(shù)單獨(dú)拿了出來(lái)。
export default { computed: { name () { return this.$options.name } }, created () { console.log('created ==> ' + this.name) }, activated () { console.log('activated ==> ' + this.name) }, deactivated () { console.log('deactivated ==> ' + this.name) }, destroyed () { console.log('destroyed ==> ' + this.name) } }
測(cè)試
訪問(wèn):http://localhost:8080/#/
可見(jiàn),除了第1次進(jìn)入,之后的進(jìn)入和退出沒(méi)有觸發(fā)相關(guān)的生命周期函數(shù),比如:created等。
解決方案
方案1:導(dǎo)航守衛(wèi)
方法:在beforeRouteEnter中請(qǐng)求后端數(shù)據(jù)。
導(dǎo)航衛(wèi)士鉤子(mixins/NavigationGuard.js)
為便于管理,我把導(dǎo)航衛(wèi)士單獨(dú)拿出來(lái),作為mixin給組件使用。
export default { beforeRouteEnter (to, from, next) { // 無(wú)法訪問(wèn)this console.log('beforeRouteEnter ==> 來(lái)自:' + from.path) console.log('beforeRouteEnter ==> 去往:' + to.path) next(true) }, beforeRouteUpdate (to, from, next) { console.log(this.$options.name + ':beforeRouteUpdate ==> 來(lái)自:' + from.path) console.log(this.$options.name + ':beforeRouteUpdate ==> 去往:' + to.path) next(true) }, beforeRouteLeave (to, from, next) { console.log(this.$options.name + ':beforeRouteLeave ==> 來(lái)自:' + from.path) console.log(this.$options.name + ':beforeRouteLeave ==> 去往:' + to.path) next(true) } }
博客編輯組件(components/BlogEdit.vue)
<template> <div class="outer"> <div> 這是BlogEdit </div> </div> </template> <script> import LifeCycle from '../mixins/LifeCycle' import NavigationGuard from '../mixins/NavigationGuard' export default { name: 'BlogEdit', mixins: [LifeCycle, NavigationGuard] } </script> <style scoped> .outer { margin: 20px; border: 2px solid blue; padding: 20px; } </style>
測(cè)試
訪問(wèn):http://localhost:8080/#/
可以發(fā)現(xiàn):離開(kāi)路由時(shí)會(huì)調(diào)用beforeRouteLeave,進(jìn)入路由時(shí)會(huì)調(diào)用beforeRouteEnter。所以可以將調(diào)后端接口的方法放到beforeRouteEnter里邊去。
方案2:watch監(jiān)聽(tīng)$route
方法:使用watch監(jiān)聽(tīng)$route的變化,變化時(shí)根據(jù)情況請(qǐng)求后端數(shù)據(jù)。
修改博客編輯組件(components/BlogEdit.vue)
<template> <div class="outer"> <div> 這是BlogEdit </div> </div> </template> <script> import LifeCycle from '../mixins/LifeCycle' export default { name: 'BlogEdit', mixins: [LifeCycle], watch: { $route (to, from) { console.log('組件:' + this.$options.name) console.log('來(lái)自:' + from.name) console.log('去往:' + to.name) } } } </script> <style scoped> .outer { margin: 20px; border: 2px solid blue; padding: 20px; } </style>
測(cè)試
訪問(wèn):http://localhost:8080/#/
可以發(fā)現(xiàn):路由變化時(shí)會(huì)觸發(fā)對(duì)$route的watch。所以可以將調(diào)后端接口的方法放到里邊去。
方案3:父組件router-view指定key
方法:在父組件的router-view中指定key,這個(gè)key必須是唯一的,比如:"$route.fullPath"。這樣vue就會(huì)認(rèn)為每個(gè)內(nèi)部路由都是不同的,在跳轉(zhuǎn)時(shí)便會(huì)強(qiáng)制刷新組件。
比如:
<router-view :key="$route.fullPath"></router-view>
修改App.vue
<router-view :key="$route.fullPath"></router-view><template> <div id="app"> <div id="nav"> <!--<router-link to="/">Home</router-link> |--> <!--<router-link to="/about">About</router-link>--> <router-link :to="{name: 'AddBlog'}">創(chuàng)建博客</router-link> | <router-link :to="{name: 'EditBlog'}">修改博客</router-link> </div> <!-- 原來(lái)代碼 --> <-- <router-view/> --> <router-view :key="$route.fullPath"></router-view> </div> </template> <style> <!-- 省略 --> </style>
測(cè)試
訪問(wèn):http://localhost:8080/#/
可以發(fā)現(xiàn):可以正常觸發(fā)組件的生命周期(created、destroyed)。
其他網(wǎng)址
Vue keepAlive實(shí)現(xiàn)不同的路由共用一個(gè)組件component的緩存問(wèn)題
到此這篇關(guān)于VueRouter解決多路由復(fù)用同一組件頁(yè)面不刷新問(wèn)題的文章就介紹到這了,更多相關(guān)VueRouter復(fù)用同一組件頁(yè)面不刷新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue組件強(qiáng)制刷新的4種方案
- Vue3中進(jìn)行頁(yè)面局部刷新組件刷新的操作方法
- vue組件值變化但不刷新強(qiáng)制組件刷新的問(wèn)題
- Vue實(shí)現(xiàn)父子組件頁(yè)面刷新的幾種常用方法
- vue打開(kāi)子組件彈窗都刷新功能的實(shí)現(xiàn)
- vue相同路由跳轉(zhuǎn)強(qiáng)制刷新該路由組件操作
- 解決vue更新路由router-view復(fù)用組件內(nèi)容不刷新的問(wèn)題
- vue強(qiáng)制刷新組件的方法示例
- Vue 實(shí)現(xiàn)手動(dòng)刷新組件的方法
- 使用Vue開(kāi)發(fā)動(dòng)態(tài)刷新Echarts組件的教程詳解
- vue強(qiáng)制刷新組件的三種方法
相關(guān)文章
vue集成高德地圖amap-jsapi-loader的實(shí)現(xiàn)
本文主要介紹了vue集成高德地圖amap-jsapi-loader的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06Vue讀取本地靜態(tài)文件json的2種方法以及優(yōu)缺點(diǎn)
這篇文章主要介紹了Vue讀取本地靜態(tài)文件json的2種方法以及優(yōu)缺點(diǎn)說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09解決Vue在封裝了Axios后手動(dòng)刷新頁(yè)面攔截器無(wú)效的問(wèn)題
這篇文章主要介紹了解決VUE在封裝了Axios后手動(dòng)刷新頁(yè)面攔截器無(wú)效的問(wèn)題,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-11-11Vue + Echarts頁(yè)面內(nèi)存占用高的問(wèn)題解決方案
點(diǎn)擊左側(cè)的菜單可以切換不同的看板,有些看板頁(yè)面中的報(bào)表比較多,用戶多次切換后頁(yè)面的內(nèi)存占用可以上升為GB級(jí),嚴(yán)重時(shí)導(dǎo)致頁(yè)面內(nèi)存溢出,使得頁(yè)面崩潰,極大影響了用戶體驗(yàn),本文給大家介紹Vue + Echarts頁(yè)面內(nèi)存占用高的問(wèn)題解決方案,感興趣的朋友一起看看吧2024-02-02vue element-ui el-cascader級(jí)聯(lián)選擇器數(shù)據(jù)回顯的兩種實(shí)現(xiàn)方法
這篇文章主要介紹了vue element-ui el-cascader級(jí)聯(lián)選擇器數(shù)據(jù)回顯的兩種實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2023-07-07解決vue2使用腳手架配置prettier報(bào)錯(cuò)prettier/prettier:context.getPhysical
這篇文章主要介紹了解決vue2使用腳手架配置prettier報(bào)錯(cuò)prettier/prettier:context.getPhysicalFilename is not a function問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03