天天看點

記一次踩雷經曆:Vue引入vant /van-tabs元件後不顯示/van-tabs和子路由的封裝後Failed to resolve directive: keep-scroll-position

記一次踩雷經曆:Vue引入vant /van-tabs元件後不顯示/van-tabs和子路由的封裝後Failed to resolve directive: keep-scroll-position

核心錯誤應該是

[Vue warn]: Property or method "$t" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property

和下面的提示

Error in render: "TypeError: _vm.$t is not a function"

以及最後的

TypeError: "_vm.$t is not a function"

問題出現在我是按需引入的插件,在main.js中引入的時候出錯了,可以看到tabbar下面有個小波浪号,首字母要大寫

記一次踩雷經曆:Vue引入vant /van-tabs元件後不顯示/van-tabs和子路由的封裝後Failed to resolve directive: keep-scroll-position

如果此時還是出錯,則删掉

npm uninstall i babel-plugin-import -D

按需引入的,以及相關的js配置檔案中一起删掉,選擇全部一起引入,否則會找不到Vant。

但是當vant可以全局引入的時候會報同樣的錯誤。是以應該不是引入方式的問題,網上普遍說是引入vux插件的問題,但是我又沒有引入這個插件。并且我在引入button的時候是沒有問題的,是以問題應該出現在我引入的tabBar。

<!--下方的TabBar-->
    <van-tabbar v-model="tabBarSelect">
      <van-tabbar-item v-for="(item, i) in tabItemList" :key="i" :to="item.to" replace>
        <div class="tab-txt">{{$t(item.name)}}</div>
        <img :src="getTabIconSrc(item, props.active)" slot="icon" slot-scope="props" class="icon-img"/>
      </van-tabbar-item>
    </van-tabbar>
           

然後這裡的tabitemlist是這樣的,我確定了圖檔和路徑的正确,img主要是想要一個點選之後的高亮:

tabItemList: [
          {
            active: 'main_tab_3.png',
            normal: 'main_tab_2.png',
            name: 'tab_home',
            to: "home"
          },
          {
            active: 'main_tab_5.png',
            normal: 'main_tab_4.png',
            name: 'tab_products',
            to: "products"
          },
          {
            active: 'main_tab_7.png',
            normal: 'main_tab_6.png',
            name: 'tab_discovery',
            to: "discover"
          },
          {
            active: 'main_tab_1.png',
            normal: 'main_tab_8.png',
            name: 'tab_mine',
            to: "mine"
          },
        ],
           

首先我測試了一下别的方式引入tabbar是不會出錯的,進一步說明不是引入的問題。

<van-tabbar v-model="tabBarSelect" >
       <van-tabbar-item icon="gem-o" url="/Home">精選</van-tabbar-item>
       <van-tabbar-item icon="shop-o">分類</van-tabbar-item>
       <van-tabbar-item icon="shopping-cart-o">購物車</van-tabbar-item>
       <van-tabbar-item icon="manager-o">我的</van-tabbar-item>
   </van-tabbar>
           

接下來實作路由跳轉。注意我這裡的路由設定是這樣的,設定了一個公共的副路由mainpage,mainpage裡面引入tabbar元件,并且進行第二次的路由跳轉。

//routes.js
const routes = [{
    path: '/',
    name:"main",
    // component: App,
    component: (resolve) => require(['../page/mainpage/index'], resolve),
    //父路由是APP.vue,子路由在副路由中出現
    children: [
        {
            path: '/index',
            name:'home',
            meta: {
                title: '首頁',
                keepAlive: true
            },
            component: (resolve) => require(['../page/home/index'], resolve)
        },
        {
            path: '/item',
            name:'item',
            meta: {
                title: '分類',
                keepAlive: true
            },
            component: (resolve) => require(['../page/item'], resolve)
        },
        {
            path: '/cart',
            name:'cart',
            meta: {
                title: '購物車',
                keepAlive: true
            },
            component: (resolve) => require(['../page/cart'], resolve)
        },
        {
            path: '/mine',
            name:'mine',
            meta: {
                title: '我的',
                keepAlive: true
            },
            component: (resolve) => require(['../page/mine'], resolve)
        },
        {
            path: '*',
            redirect: '/index'
        }
    ], meta: {keepAlive: true}
}]
           

改進後可以實作路由跳轉的mainpage的tab元件部分,隻需要加一個onchange來監聽tabbar發生變化:

<van-tabbar v-model="tabBarSelect"  @change="onChange">
            <van-tabbar-item icon="gem-o" url="/home">精選</van-tabbar-item>
            <van-tabbar-item icon="shop-o">分類</van-tabbar-item>
            <van-tabbar-item icon="shopping-cart-o">購物車</van-tabbar-item>
            <van-tabbar-item icon="manager-o">我的</van-tabbar-item>
        </van-tabbar>
           

發生變化後觸發了方法:

methods: {
         onChange(index) {
             const routerArray = [
                 "/home",
                 "/item",
                 "/cart",
                 "/mine"
             ];
             this.$router.push(routerArray[index])
         },
     },
           

但是現在還有一個問題就是,每次店家home頁面時會重新整理緩存。并且還是有個警告:

Failed to resolve directive: keep-scroll-position

,我想了想可能是我對子路由的運用有問題,就取消了子路由,

改成了直接把元件放在app.vue中。

<template>
  <div id="app">
    <!--緩存的頁面-->
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"/>
    </keep-alive>
    <!--不緩存的頁面-->
    <router-view v-if="!$route.meta.keepAlive"/>
    <tabbar v-if="$route.meta.showTab" />
  </div>
</template>

<script>
import Tabbar from './components/Tabbar'
export default {
  name: 'App',
  components: {
    Tabbar
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

           

檔案結構是:

記一次踩雷經曆:Vue引入vant /van-tabs元件後不顯示/van-tabs和子路由的封裝後Failed to resolve directive: keep-scroll-position

路由設定是:

import Vue from 'vue'
import VueRouter from 'vue-router'
// import App from '../App.vue'

const routes = [
        {
            path: '/index',
            name:'home',
            meta: {
                title: '首頁',
                keepAlive: true,
                showTab: true
            },
            component: (resolve) => require(['../page/home/index'], resolve)
        },
        {
            path: '/item',
            name:'item',
            meta: {
                title: '分類',
                keepAlive: true,
                showTab: true
            },
            component: (resolve) => require(['../page/item'], resolve)
        },
        {
            path: '/cart',
            name:'cart',
            meta: {
                title: '購物車',
                keepAlive: true,
                showTab: true
            },
            component: (resolve) => require(['../page/cart'], resolve)
        },
        {
            path: '/mine',
            name:'mine',
            meta: {
                title: '我的',
                keepAlive: true,
                showTab: true
            },
            component: (resolve) => require(['../page/mine'], resolve)
        },
        {
            path: '*',
            redirect: '/index'
        }

]

           

然後tabbar的元件的設定是,要特别的注意這裡的tabbar沒有設定屬性route,是以需要自己設定監聽動作onChange,否則隻需要直接在van-tabbar-item中設定to就能實作路由跳轉,但是此時不會自動改變顔色:

<template>
    <div class="tabbar">
        <van-tabbar v-model="tabBarSelect"  @change="onChange" :active-color="color" :fixed="false">
            <van-tabbar-item icon="gem-o" url="/home">精選</van-tabbar-item>
            <van-tabbar-item icon="shop-o">分類</van-tabbar-item>
            <van-tabbar-item icon="shopping-cart-o">購物車</van-tabbar-item>
            <van-tabbar-item icon="manager-o">我的</van-tabbar-item>
        </van-tabbar>
    </div>
</template>

<script>
    export default {
        name: "index",
        watch: {

        },
        computed: {
            color(){
                return "#1c99e2c0";
            }

        },
        data() {
            return {
                tabBarSelect: 0,
            };
        },
        methods: {
            onChange(index) {
                const routerArray = [
                    "/index",
                    "/item",
                    "/cart",
                    "/mine"
                ];
                this.$router.push(routerArray[index])
            },
        },
        mounted() {

        }
    }
</script>

<style scoped>
    .tabbar {
        width: 100vw;
        position: fixed;
        bottom: 0;
        left: 0;
        border-top: 2px solid #f5f5f5;
    }
</style>

           

tabbar的另外一個寫法,,此時需要額外的設定高亮:

<div class="tabbar">
      <van-tabbar v-model="active" :active-color="variables.theme" :fixed="false" route>
        <van-tabbar-item to="/" icon="wap-home">首頁</van-tabbar-item>
        <van-tabbar-item to="/category" icon="bars">分類</van-tabbar-item>
        <van-tabbar-item to="/cart" icon="shopping-cart">購物車</van-tabbar-item>
        <van-tabbar-item to="/user" icon="manager">我的</van-tabbar-item>
      </van-tabbar>
    </div>