vue+ts下集----ts配置路由、路由守衛、數據交互-axios、登錄驗證邏輯、狀態管理


### ts配置路由

    ①安裝:npm i vue-router -S
    ②src下新建pages/Home.vue(還有Goods.vue、Detail.vue等頁面):
        <template>
            <div class="home">
                <h2>首頁</h2>
            </div>
        </template>
        <script lang="ts">
        import Vue from 'vue';
        import {Component} from "vue-property-decorator";
        @Component({})
        export default class Home extends Vue{
            
        }
        </script>
    ③src下新建plugins/router.ts:(注意Reg.vue和Detail.vue分別是以import和require的方式實現路由懶加載)
        import Vue from "vue";
        import VueRouter from "vue-router";
        Vue.use(VueRouter);// 安裝插件

        import Home from "../pages/Home.vue";
        import Goods from "../pages/Goods.vue";
        import User from "../pages/User.vue";
        import Login from "../pages/Login.vue";
        import NoPage from "../pages/NoPage.vue";
        let routes=[
            {path:"/home",component:Home},
            {path:"/goods",component:Goods},
            {path:"/user",component:User},
            {path:"/login",component:Login},
            {path:"/reg",component:()=>import("../pages/Reg.vue")},
            {path:"/detail",component:(resolve:any)=>{require(["../pages/Detail.vue"],resolve)}},
            {path:"*",component:NoPage},
            {path:"/",redirect:"/home"},
        ];

        let router=new VueRouter({
            mode:"history",
            routes
        });

        export default router;
    ④main.js中引入router並注冊:
        import router from "./plugins/router"

        new Vue({
            render: h => h(App),
            router
        }).$mount('#app')
    ⑤App.vue中開辟路由空間:
        <router-view></router-view>

 

### 路由守衛

    router.ts中:
        /*
        全局守衛
        */
        router.beforeEach((to,from,next)=>{
            console.log("全局前置守衛")
            next();
        })
        router.afterEach((to,from)=>{
            console.log("全局后置守衛")
        })

        // 路由獨享守衛
        {path:"/user",component:User,beforeEnter: (to:Route, from:Route, next:Function) => {
            console.log("路由獨享前置守衛")
            next();
        }},
        注意:設置路由獨享守衛時,定義的Route類型是ts自動引入的(import VueRouter, { Route } from "vue-router";)

 

    組件內部守衛:(注意這里的Route類型是手動引入的)
        (1)User.vue中:
            import {Route} from "vue-router";
            @Component({
                /*
                    這里寫自定義指令、過濾器、守衛鈎子函數
                */
                beforeRouteEnter (to:Route, from:Route, next:Function) {
                    // 由於寫在裝飾器中,鈎子函數可以自動推測出to、from、next的類型,所以可以加類型也可以不加
                    console.log("組件內前置守衛")
                    next();
                }
            })
        (2)Reg.vue中:
            import {Route} from "vue-router";
            @Component({
                beforeRouteLeave (to:Route, from:Route, next:Function) {
                    console.log("組件內后置守衛")
                    next();
                }
            })

 

### 數據交互-axios

    安裝:npm i axios @types/axios -S
    注意:不是所有的插件都帶有類型聲明文件,只有類型聲明文件才能保證支持ts,沒有類型聲明文件的插件需要安裝類型聲明文件。

 

    (1)axios初步使用:
        ①public下新建data/user.json:
            {
                "data":[
                    {"username":"wxm"}
                ]
            }
        ②Home.vue中:
            import axios from "axios";
            export default class Home extends Vue{
                mounted():void {
                    axios({
                        url:"/data/user.json" // public中的數據可以直接訪問
                    }).then(
                        res=>console.log(res.data)
                    )
                }
            }
    (2)訪問json-server數據:
        需要先將json-server開啟數據服務,再設置url:url:"http://localhost:3000/data"
    (3)訪問tiantian-api數據:
        ①開啟tiantian-api數據服務:npm run start
        ②設置跨域代理(根目錄下新建vue.config.js):
            module.exports={
                devServer:{
                    proxy:{
                        "/v3":{
                            target:"http://localhost:3000",
                            changeOrigin:true
                        }
                    }
                }
            }
        ③代理地址替代原地址:
            url:"/v3/homepage"
    (4)axios攔截器:
        ①plugins下新建axios.ts:
            import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
            import router from './router';
            import { TUser } from '@/types';

            //請求攔截器
            axios.interceptors.request.use((config:AxiosRequestConfig):AxiosRequestConfig=>{
                /*
                    抓取token,攜帶到響應頭
                    顯示loading
                */
                let user:TUser=window.localStorage.getItem("user");
                user=user?JSON.parse(user):"";
                config.headers={token:user?.token}// 攜帶到請求頭
                return config;
            },(error)=>{
                return Promise.reject(error)
            })

            //響應攔截器
            axios.interceptors.response.use((response:AxiosResponse<any>):AxiosResponse<any>=>{
                /*
                    token過期,跳轉login,保留當前地址
                    關閉loading
                */
                // 判斷如果有錯誤(token過期),並且當前路徑不是login,則跳轉到login頁面,並且將當前的全路徑帶過去
                if(response.data.err==2 && !router.currentRoute.fullPath.includes("/login")){
                    router.push({path:"/login",query:{path:router.currentRoute.fullPath}});
                }
                return response;
            },(error)=>{
                return Promise.reject(error)
            })

            // 對外暴露
            export default axios;
        ②Home.vue中使用時用封裝的axios替代原來的axios:
            import axios from "../plugins/axios";
    (5)將axios掛載到window下:
        ①src/types/index.ts中:
            // 定義全局變量,重定義了Window接口
            declare global{
                interface Window{
                    axios(config:AxiosRequestConfig):AxiosPromise<any>
                }
            }
        ②axios攔截器中對外暴露的時候添加:
            window.axios=axios;
        ③main.js中引入:
            import "./plugins/axios"
        ④Home.vue中使用時不用引入任何的axios,直接用window.axios()使用:
            mounted():void {
                window.axios({
                    url:"/v3/homepage"
                }).then(
                    res=>console.log(res.data)
                )
            }
        

### 登錄驗證邏輯

    ①axios.ts的響應攔截器中利用router.currentRoute.fullPath可以拿到當前要去往的路由,保留當前地址:
        // 判斷如果有錯誤(token過期),並且當前路徑不是login,則跳轉到login頁面,並且將當前的全路徑帶過去
        if(response.data.err==2 && !router.currentRoute.fullPath.includes("/login")){
            router.push({path:"/login",query:{path:router.currentRoute.fullPath}});
        }
    ②Login.vue中點擊登錄時進行請求,如果沒有錯誤,則將token存到localStorage中,並且跳轉到響應攔截器中保留的路由:
        <button @click="login">登錄</button>
        export default class Login extends Vue{
            public login():void {
                window.axios({
                    url:"/api/login",
                    method:"post",
                    data:{username:"chenghao",password:"chenghao123"}
                }).then(
                    res=>{
                        if(res.data.err==0){
                            // 種token到localStorage中
                            window.localStorage.setItem("user",JSON.stringify(res.data))
                            // 跳轉到之前的頁面
                            this.$router.replace(this.$route.query.path as string)
                        }
                    }
                )
            }
        }

 

### 狀態管理

    ①安裝:npm i vuex vuex-class -S

 

    未完待續……





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM