vue-cli3+typescript初體驗——router篇

前言

vue基於類的寫法,和基於對象的寫法並不一致。
使用vue-cli3創建的項目,src目錄下的文件結構並沒有多大區別,storerouterappviewcomponentsaeests該有的還是有的。
但是,多了一個東西:vue-property-decoratorvue-property-decoratorvue-class-component的超集。

import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator';

最主要的區別就是這裏,組件的定義,參數的接受,方法的定義,等等。
但是本文主要講的是router的監聽。

路由監聽

用vue2的vue-cli創建項目,在src下有App.vue,main.js,其中如果要做路由權限控制,可以通過在mian.js添加以下代碼來控制:

import router from './router'

router.beforeEach((to, from, next) => {    
    /*如果需要登錄,當前沒有登錄,直接跳轉到登錄頁*/
    if (to.meta.Auth && !store.state.loginStatus) {
        return next({ name: 'Login', query: {path: to.name}})
    }
    next()    
})

這個功能,在新版本的vue3中依然可以使用,因爲使用了typescript,所以應該是main.ts文件。
但是如果要在組件內部使用路由監聽,就遇到問題了,路由鉤子beforeRouteEnter,beforeRouteLeave,beforeRouteUpdate不生效。
官網推薦在mian.ts中註冊解決:

import Component from 'vue-class-component'

Component.registerHooks([
  'beforeRouteEnter',//進入路由之前
  'beforeRouteLeave',//離開路由之前
  'beforeRouteUpdate'
])

但是在vue-cli3中試過,不生效。可能是vue-property-decoratorvue-class-component有區別的原因,或者項目配置問題。
組件中實現路由監聽,只能通過@Watch('$route')來實現。
但是@Watch不是路由守衛,如果離開當前組件,就不能繼續監聽路由變化,所以需要在當前的router-virew容器組件中監聽。

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </div>
    <router-view/>
  </div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
@Component
export default class App extends Vue {
  @Watch('$route',{ immediate: true })
  private changeRouter(route: Route){
      console.log(route)
  }
}
</script>

其中{ immediate: true }是關鍵,必須加這個參數才嫩實現對$route的監聽。

結語

vue-cli3+typescript的規範還不成熟,各種文檔還不夠齊全,尤其是中文文檔。
很多demo都是基於vue2改造的,導致使用vue-cli3的時候出bug。
尤其是vue-routervuex的使用。
但也正是這些問題,讓我們有更大的興趣學習使用這個新的技術規範。

後記

經過社區同學的指點,使用路由鉤子的組件必須由路由加載,做了測試,vue-cli3的路由守衛是可以使用的。
入口文件:

//main.ts
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import { Component } from 'vue-property-decorator';

Vue.config.productionTip = false;
Component.registerHooks([
  'beforeRouteEnter',
  'beforeRouteLeave',
  'beforeRouteUpdate',
]);

new Vue({
  router,
  store,
  render: (h) => h(App),
}).$mount('#app');

路由規則文件:

//router.ts
import Vue from 'vue';
import Router from 'vue-router';
import Home from './views/Home.vue';

Vue.use(Router);

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home,
    },
    {
      path: '/about',
      name: 'about',
      // route level code-splitting
      // this generates a separate chunk (about.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
    },
  ],
});

路由載入組件:

//About.vue
<template>
  <div class="about">
    <h1>This is an about page</h1>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';

@Component
export default class About extends Vue {

  beforeRouteEnter(to: Route, from: Route, next: () => void): void {
    console.log('beforeRouteEnter'); 
    next();
  }
  beforeRouteUpdate(to: Route, from: Route, next: () => void): void {
    console.log('beforeRouteUpdate');//暫時不生效,版本問題
    next();
  }
  beforeRouteLeave(to: Route, from: Route, next: () => void): void {
    console.log('beforeRouteLeave'); 
    next();
  }
}
</script>

如上,可以愉快的使用單獨的路由鉤子啦!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章