vue基於類的寫法,和基於對象的寫法並不一致。
使用vue-cli3創建的項目,src
目錄下的文件結構並沒有多大區別,store
、router
、app
、view
、components
、aeests
該有的還是有的。
但是,多了一個東西:vue-property-decorator
,vue-property-decorator
是vue-class-component
的超集。
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'
最主要的區別就是這里,組件的定義,參數的接受,方法的定義,等等。
但是本文主要講的是router的監聽。
路由監聽
用vue2的vue-cli創建項目,在src
下有App.vue
,main.js
,其中如果要做路由權限控制,可以通過在main.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
不生效。
解決方案:
// main.ts import Component from 'vue-class-component' Component.registerHooks([ 'beforeRouteEnter',//進入路由之前 'beforeRouteLeave',//離開路由之前 'beforeRouteUpdate' ])
路由規則文件:
//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> <h2 @click="click(10)">count:{{count}}</h2>
<p>getCount:{{getCount}}</p> </div> </template> <script lang="ts"> import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator' @Component export default class About extends Vue { private count: number = 1; private num: number = 1; private click(num: number) { this.count = num + this.count; this.num++ } // 相當於computed屬性 get getCount() { return this.count + 1 } beforeCreate() { console.log('beforecreate'); } created() { console.log('created') } beforeMount() { console.log('beforemounted'); } mounted() { console.log('mounted'); } beforeRouteEnter(to: any, from: any, next: () => void): void { console.log('beforeRouteEnter111'); next(); } beforeRouteUpdate(to: any, from: any, next: () => void): void { console.log('beforeRouteUpdate111'); next(); } beforeRouteLeave(to: any, from: any, next: () => void): void { console.log('beforeRouteLeave111'); next(); } @Watch('count') // 監聽count private aaa(val: any, oldval: any) { console.log(val, oldval); } @Watch('num') // 監聽num private bbb(a: number, b: number) { console.log(a, b) } } </script> <style lang="less"> .about { background-color: red; h1 { color: #fdfdfd; } } </style>
效果圖:
prop傳值及component組件
// home.vue <template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <HelloWorld :msg='msg' :title='title'/> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src @Component({ components: { HelloWorld, }, }) export default class Home extends Vue { private msg: String = "Welcome to Your Vue.js + TypeScript App" private title: String = 'I am title' } </script>
// helloworld.vue <template> <div class="hello"> <h2>title:{{title}}</h2> <h1>msg:{{ msg }}</h1> </div> </template> <script lang="ts"> import { Component, Prop, Vue } from 'vue-property-decorator'; @Component export default class HelloWorld extends Vue { @Prop() private msg !: string; @Prop() private title !: string; } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped lang="less"> h3 { margin: 40px 0 0; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
效果展示: