vue string拆分_vue 路由重定向

前言

最近在做部门系统平台的改版工作。不同于去年经手的 1.0 到 2.0 的 UI 改版工作,这次迭代,是将整个可视化平台抽离模块,将原本耦合很严重的各个模块抽离出来单独形成个项目。

这就需要对整个庞大的项目代码有很好的认识。

很惭愧的是,这一两年时间都没好好看全整个项目的代码,对整体项目的运行都不甚了解。

也很幸运的是,这次改版由我主导独立实现,这就很利于自身技术的提升。

整个系统平台项目的模块分为平台、用户中心、数据中心、权限中心、展示端和编辑器。其中数据中心、权限中心在当时部署的时候就考虑到以后需要拆分的打算,所以都是独立的,比较困难的就是拆分和平台耦合很深的用户中心、展示端和编辑器。

为了方便对整个平台项目代码有更好的认识,我计划的是按照平台代码架构先自己实现一套类似的 vue 项目,特意在便签上列了计划固定在桌面上

43ac7e4a85d0ba9d0e52538e86025f68.png

按进度进行,目前也算是实现了一小阶段,正好记录一下。

引入 ts

之前有文章写过了,点击这里查看

但是有反馈说其中 webpack 的配置按照文中进行,最后运行会有报错。我在附篇文章里重新给出完整的配置文件。

路由

目前我的项目中 src 下目录结构是这样的:

9824f9db9b10a42a92c3c4a53c5817b7.png

所有的页面代码放在 views 中,对应的在 router 中有相应页面路由。

例如登陆页面,router 中新建个 login 的路由文件,代码如下:

import Login from "../views/login/index.vue";
export const loginRouter = {
    path: "/login",
    key: "login",
    name: "login",
    component: Login
};

那路由的 index 中直接引入就可以了,代码如下:

import Vue from "vue";
import Router from "vue-router";
import { loginRouter } from "./login";
import { layoutRouter } from "./layout";
Vue.use(Router);
export const mainRoutes = [loginRouter, layoutRouter];
export default new Router({
    routes: mainRoutes
});

以后每多加个页面,都是在 views 中新建个页面文件夹,再在 router 中新建个页面路由文件,最后要在 index 中引入,加在 mainRoutes 里。

api

这里我以登录页测试,直接引用了部门已有的后端接口。如果有水平自己写 java 接口的话,只需要在 apiConfig 文件中修改个后端接口的 url 就可以了。

新建个 api 文件夹,专门存放所有的后端接口。

首先需要个入口,得清楚调用哪里后端的接口,就像个大门,这块逻辑写在个 apiConfig 的文件里,当然这个文件名随便起,代码如下:

const serverUrl = "https://api:port";
export const apiPrefix: string = `${serverUrl}/`; // 项目请求网址
export const serverNamesPrefix = {
    dataServer: "",
    portal: "",
    fileServer: "",
    jobServer: ""
};

只需要将 serverUrl 替换成你的后端服务地址,没有也没事,并不影响接下来前端的实现,只是影响了最后查看效果时候调用后端接口失败而已。

大门有了,下面就需要搞把钥匙,没有钥匙咋进门用到后端服务拿到数据库里的数据呢。

这里钥匙实现的方式是用的 axios,首先项目里安装一下,

yarn add axios

新建个 base 文件,这里写用 axios 发送 ajax 请求的实现代码:

import axios, { AxiosRequestConfig, AxiosResponse } from "axios";
import { merge } from "lodash";
import { apiPrefix } from "./apiConfig";
import { urlUtils } from "../utils/url";
const apiOpenList: string[] = [
    // 登录
    "auth/password"
];
// http request 拦截器
axios.interceptors.request.use(
    (config: AxiosRequestConfig) => {
        const { url, headers } = config;
        if (!headers["jwt-token"]) {
            const index = apiOpenList.findIndex(apiUrl => {
                if (url.indexOf(apiUrl) > -1) {
                    return true;
                } else {
                    return false;
                }
            });
            if (index === -1) {
                urlUtils.noAuthRedirect();
            }
        }
        return config;
    },
    error => {
        return Promise.reject(error);
    }
);
// http Response响应拦截器
axios.interceptors.response.use(
    response => {
        if (response.data) {
            switch (response.data.status) {
                case 10014: // 返回401,清除token信息并跳转到登录页面
                case 10013: // auth.authz.jwt.signature.error
                case 10001: // auth.authz.jwt.signature.error
                    api.clearJwtToken();
                    urlUtils.noAuthRedirect();
                    break;
            }
        }
        return response;
    },
    (error: any) => {
        if (error.response) {
            return Promise.reject(error.response.data);
        } else {
            return Promise.reject({
                status: 0,
                message: error.message
            });
        }
    }
);
class API<T> {
    // 请求的参数
    public ajaxMap = {};
    // jwt-token操作
    public setJwtToken(token: string) {
        window.sessionStorage.setItem("jwt-token", token);
    }
    public getJwtToken() {
        window.sessionStorage.getItem("jwt-token") || "";
    }
    public clearJwtToken() {
        window.sessionStorage.removeItem("jwt-token");
    }
    // 请求方式
    public get(url: string, params?: any): Promise {return this.baseRequest(url, { method: "GET", params: params || {} });
    }
    public post(url: string, params?: any): Promise {return this.baseRequest(url, { method: "POST", data: params || {} });
    }
    private baseRequest(url: string, options?: AxiosRequestConfig): Promise {const defaultConfig: AxiosRequestConfig = {method: "GET",timeout: 300000,url: `${apiPrefix}${url}`,headers: {"Content-Type": "application/json"
            },withCredentials: true
        };const config = merge(defaultConfig, options || {});return new Promise(resolve => {
            axios(config)
                .then((res: AxiosResponse) => {
                    resolve(res.data);
                })
                .catch(error => {const result: AxiosResponse = {data: {success: false,status: error.status || 500,data: "",message: `${error.message}`,msg: `${error.message}`
                        },status: 0,statusText: "",headers: "",config: {}
                    };
                    resolve(result.data);
                });
        });
    }
}export const api = new API();

在 base 中还加了个拦截器的实现,不需要的话可以直接删除那两段代码。

这里拦截器的代码里主要是判断了登录的情况,根据约定好的后端接口名,首次登录时判断,进行路由重定向,将首页的路由修改成登录页的。

哇,终于点题了。

路由重定向

直接复制如上代码到 base 里一定是会报错的,毕竟还有文件没引用。

就是这个 urlUtils。

src 先新建个 utils 文件夹,再在里面新建个 url 文件,代码如下:

const { origin, href } = window.location;
let baseUrl = origin;
class UrlUtils {
    // 重定向
    public redirect(url: string) {
        window.location.replace(url);
    }
    public goCallbackUrl(url: string) {
        this.redirect(`${url}`);
    }
    public noAuthRedirect() {
        this.redirect(
            `${baseUrl}/#/login?redirect=${encodeURIComponent(href)}`
        );
    }
    public logout() {
        this.redirect(`${baseUrl}/#/login`);
    }
}
export const urlUtils = new UrlUtils();

base 应该还有报错,最后 new API 的时候它的类型报错了。

因为没有声明呀。

在 src 下的 types 下的 global.d.ts 中,添加如下代码:

/**
 * 内部接口返回格式
 * success:接口调用状态 成功或者失败
 * status: 接口返回状态值 0成功  10006 没有获取到数据
 * data: 返回的数据 默认为任何值,根据具体接口设置不同的值类型
 * mes:返回的错误信息。
 */
declare interface ApiResponse {success: boolean;
    status: number;
    data: T;
    msg?: string;
    [k: string]: any;
}

这样,base.ts 就没问题了。

顺便根据后端提供的接口文档,在 api 中新建个登录接口文件,就是那个 auth/password 的接口名:

import { api } from "./base";
export class Auth {
    // 登录
    public static login(params: any): Promise {return api.post("auth/password", params);
    }
}

当然了,关于的后端的都需要根据个人实际情况来操作,你又用不到我这儿的后端环境。

关于为啥用路由重定向,又如何用了重定向,这里简单说一下。

在路由文件中,layout 的路由 path 是"/",login 的路由 path 是 "/login",那就是应该在浏览器输入http://localhost:8080/#/login才可以访问,不然默认的话就是 layout 的页面。

然而首次登录的时候,就需要默认展示登录页,用户登录之后才可以进入 layout。

就像如下这个样子:(我在 login 页写了"登陆页面",layout 页写了"主页面")

7298eb9c5b643939448b111d01b6ba56.gif

按理说,输入 localhost:8080 之后,路由渲染的应该是 layout 页面,页面应该出现"主页面的字样",但实际上是自动跳转到了 login。

前文中说到了 api 的 base 中,重定向的实现是在拦截器里,其实就是那句是否首次登录判断里调用了 urlUtils.noAuthRedirect(),在输入 localhost:8080 之后,调用 layout 页面中需要有 api 的调用,才能触发 base 中代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值