一、問題解析
今天在使用 Vue命名視圖發(fā)現(xiàn)了兩個問題,首先看下代碼
路由部分代碼
{
path: Prefix('/device/:id'),
name: 'Device',
components: {tabbar: Device},
meta: {
title: '',
},
props: true,
},
{
path: Prefix('/stop/:deviceId/:goodsId'),
name: 'Stop',
component: Stop,
meta: {
title: '',
},
props: true,
},
這段代碼包含兩個路由,Device和Stop
- 首先當(dāng)進(jìn)入
Device時無法到props中的id,這時需要修改成如下方式
props: {
tabbar: true,
},
官方解釋是 對于包含命名視圖的路由,你必須分別為每個命名視圖添加 props 選項
- 第二個問題是當(dāng)從路由
Device的組件跳轉(zhuǎn)到Stop路由的組件的時候,不能正確跳轉(zhuǎn)
當(dāng)把1的問題解決好以后,2的問題也解決好了,至于原理,應(yīng)該是vue-router內(nèi)部的實現(xiàn)機(jī)制,具體的原理還不清楚。
二、命名視圖的簡單用法
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
const router = new VueRouter({
routes: [
{
path: '/',
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
這樣就可以正常使用了,如果有布局的需求,就要自己進(jìn)行布局。
三、我什么會引入命名視圖
<template v-if="showTabBar">
<div class="p-app-body">
<router-view name="tabbar"></router-view>
</div>
<div class="p-app-tabbar">
<tab-bar v-model="routerName"></tab-bar>
</div>
</template>
<template v-if="hideTabBar">
<router-view></router-view>
</template>
上面這段代碼是我現(xiàn)在可以正常運行的代碼
我部分頁面是有tabBar的,這時候就需要用到全屏,沒有用到tabBar的頁面正常顯示就好。
有問題的代碼
<template v-if="showTabBar">
<div class="p-app-body">
<router-view></router-view>
</div>
<div class="p-app-tabbar">
<tab-bar v-model="routerName"></tab-bar>
</div>
</template>
<template v-else>
<router-view></router-view>
</template>
問題主要是當(dāng)我路由切換的時候可能導(dǎo)致我的組件加載兩次,何為兩次呢。
有一個Me路由(需要顯示tabBar)和一個Order路由(不需要顯示tabBar)時,當(dāng)有Me跳轉(zhuǎn)至Order時,showTabBar會由true變?yōu)?code>false,因為異步的原因,值改變的時候vue路由還沒有切換,因為都是路由的默認(rèn)組件,所以Me路由對應(yīng)的組件還會要再加載一次,再馬上切換到Order路由,正常情況下是沒有感官上的感受的,如果Me組件在created階段刪除掉了Order組件需要用的的Cookie、localStorage、sessionStorage等,將導(dǎo)致頁面不能正確顯示,所以才會引入最上面說到的問題,同時還會引起下面這個問題。
說一下為什么要用兩個v-if而不是使用v-if和v-else。
假設(shè)我們使用v-if和v-else,當(dāng)首次加載的時候頁面已經(jīng)加載完畢,但是路由還沒有完全加載,頁面就會使用v-else進(jìn)行加載(或者因為異步的原因路由已經(jīng)加載完畢,但是我showTabBar是false),當(dāng)路由加載完成以后發(fā)現(xiàn)showTabBar是true,這時就需要使用v-if加載,導(dǎo)致路由對應(yīng)的組件加載兩次,解決的方法就是增加一個v-if,而且每個都要有去空判斷。
showTabBar() {
return this.routerName && listTabBar.indexOf(this.routerName) >= 0
},
hideTabBar() {
return this.routerName && listTabBar.indexOf(this.routerName) < 0
},
增加這一段之后因為有了去空解決了首次重復(fù)加載問題,那是否可以解決我最開始的問題(切換路由組件加載兩次)呢。
當(dāng)然是否定的。還是回到了出現(xiàn)這個問題的原因,因為異步導(dǎo)致v-if切換和路由切換不是同步的,所有是不可以的。
總結(jié)
如果Vue根節(jié)點是要根據(jù)v-if顯示不同的內(nèi)容并且每個內(nèi)容快都包含路由視圖時就需要考慮兩個方面
1、是否能容忍組件加載兩次,不能的話就要使用命名視圖。
2、是否能容忍首次重復(fù)加載,不能的話就要給每個單獨寫v-if并去掉空。
異議
其實解決這個問題也可以根據(jù)路由進(jìn)行區(qū)分,再加一個上級路由,需要用到tabBar的就統(tǒng)一有一個上級路由,把tabBar和全屏都寫在這個上級路由里面。