What is vue.js plug-in

According to the website of vue.js. Plug-ins are usually used to add global functionality to a Vue. Vue plug-in

What can the vue.js plug-in do

  • Add global methods or properties
  • Add global resources: directives/filters/transitions, etc
  • Add some component options through global blending
  • Add Vue instance methods by adding them to Vue. Prototype
  • A library that provides its own API and provides one or more of the functions mentioned above

In this article, I provide my own plug-in containing the login interface as a plug-in that provides a wrapper around AXIos. This way, each new project can quickly implement login and AXIOS functions as plug-ins. Just to provide an idea, we can do their own development under the reference. Such as an out-of-the-box plug-in that allows users to log in, register, retrieve passwords, etc. Plug-ins can also inject a library to implement their own methods.

Feature list

  • Unified login page
  • Axios configurable encapsulation

Key points of implementation

  • Expose an install method
  • Do a series of function or function mounts on the Vue prototype
  • The customization parameter is passed when ue. Use

Post a sample code from the official website

MyPlugin.install = function (Vue, options) { // 1. Options.someoptions = true vue.myGlobalMethod = function () {// Logic... {bind (el, binding, vnode, oldVnode) {// bind (el, binding, vnode, oldVnode) {// bind (el, binding, vnode, oldVnode) {// bind (el, binding, vnode, oldVnode) {// }... Mixin ({created: function () {// logic... }... $myMethod = function (methodOptions) {$myMethod = function (methodOptions) {$myMethod = function (methodOptions); }}Copy the code

use

import myPlugin from "myplugin"

Vue.use(myPlugin, {
	someOption: true 
})
Copy the code

Post my implementation

As long as it is to understand the idea, the realization of ideas and principles. Then you can implement the function you want

import axios from "axios";
import qs from "qs";
import { version, winyh, getQueryVariable } from "./util";
import { codeMessage } from "./request";
import user_store from "./store";

import Login from "./components/login";

import Notification from "ant-design-vue/lib/notification";
import "ant-design-vue/lib/notification/style/css";

import Message from "ant-design-vue/lib/message";
import "ant-design-vue/lib/message/style/css";

const components = [Login];

/* 异常处理程序 */
const errorHandler = (error) => {
  const { response } = error;
  if (response && response.status) {
    const errorText = codeMessage[response.status] || response.statusText;
    const { status } = response;
    console.log(`请求错误 ${status}:`, errorText);

    Notification.error({
      message: "系统提示",
      description: `请求错误 ${status}: ${errorText}`,
    });

    if (status === 401) {
      console.log(401);
      if (window.location.pathname !== "/user/login") {
        // 带redirect 到登录页

        // router.replace({
        //     path: "/login",
        //     query: { redirect: router.currentRoute.fullPath },
        //   });

        let redirect = encodeURI(location.href);
        location.href = `/user/login?redirect=${redirect}`;
      }
    }

    if (status === 403) {
      console.log(403);
    }

    if (status === 404) {
      console.log(404);
    }

    if (status === 405) {
      console.log(405);
    }

    if (status === 500) {
      console.log(500);
    }
  } else if (!response) {
    console.log("您的网络发生异常,无法连接服务器");
    Notification.error({
      message: "系统提示",
      description: "您的网络发生异常,无法连接服务器",
    });
  }
  return response;
};

/* 必须暴露 install 方法 */
const install = (Vue, options) => {
  const {
    timeout = 3000,
    tokenKey = "token",
    homeUrl = "/",
    api_user = "/user/info",
    router,
    store,
    baseURL,
    headers,
    namespace = "",
    loginConfig = {},
  } = options;

  /* Login 组件全局变量 */
  Vue.prototype.__loginConfig__ = loginConfig;

  /* Vuex 设置 */

  if (store) {
    store.registerModule("user", user_store);
  }

  router.beforeEach((to, from, next) => {
    /* 必须调用 `next` */
    const token = localStorage.getItem(tokenKey) || "";
    const user = store.state.user.userInfo || "";

    const systemExpireAt = Date.now();
    const localExpireAt = localStorage.getItem("expire_at");

    if (systemExpireAt > localExpireAt) {
      if (to.path === "/user/login") {
        next();
      } else {
        next({ path: "/user/login" });
      }
    }

    if (token) {
      if (!user) {
        Vue.prototype.$getUserInfo();
      }
      next();
    } else {
      if (to.path === "/user/login") {
        next();
      } else {
        localStorage.removeItem(tokenKey);
        next({ path: "/user/login" });
      }
    }
  });

  router.addRoutes([
    {
      path: "/user/login",
      component: Login,
    },
  ]);

  if (install.installed) return;

  components.map((component) => Vue.component(component.name, component));

  const instance = axios.create({
    baseURL: baseURL,
    timeout: timeout,
  });

  /* 请求拦截器 */
  instance.interceptors.request.use(
    (config) => {
      const token = localStorage.getItem(tokenKey) || "";
      if (token) {
        config.headers["Authorization"] = "Bearer " + token;
      }
      if (headers) {
        config.headers = {
          ...config.headers,
          ...headers,
        };
      }

      return config;
    },
    (error) => {
      return Promise.reject(error);
    }
  );

  /* 响应拦截器 */
  instance.interceptors.response.use(
    (response) => {
      return response.data;
    },
    (error) => {
      errorHandler(error);
      return Promise.reject(error);
    }
  );

  /*
   * get请求
   */
  Vue.prototype.$get = (url, params) => {
    return instance(url, { params });
  };

  /*
   * post请求
   */
  Vue.prototype.$post = (url, params, headers) => {
    if (headers) {
      var isUrlencoded =
        headers["content-type"] === "application/x-www-form-urlencoded";
    }
    return instance({
      url,
      method: "post",
      data: isUrlencoded ? qs.stringify(params) : params,
      headers,
    });
  };

  /*
   * put请求
   */
  Vue.prototype.$put = (url, params, headers) => {
    if (headers) {
      var isUrlencoded =
        headers["content-type"] === "application/x-www-form-urlencoded";
    }
    return instance({
      url,
      method: "put",
      data: isUrlencoded ? qs.stringify(params) : params,
      headers,
    });
  };

  /*
   * put请求
   */
  Vue.prototype.$delete = (url, params, headers) => {
    if (headers) {
      var isUrlencoded =
        headers["content-type"] === "application/x-www-form-urlencoded";
    }
    return instance({
      url,
      method: "delete",
      data: isUrlencoded ? qs.stringify(params) : params,
      headers,
    });
  };

  /*
   * Login 方法
   */
  Vue.prototype.$login = (url, params, headers) => {
    return new Promise((resolve, reject) => {
      Vue.prototype
        .$post(url, params, headers)
        .then((res) => {
          if (res.success) {
            let { token, expir, redirect } = res.data;
            let path_to = redirect ? redirect : homeUrl; // 服务器返回redirect
            let local_redirect = getQueryVariable("redirect"); // 本地的redirect
            path_to = local_redirect ? decodeURI(local_redirect) : path_to;
            localStorage.setItem(tokenKey, token);
            localStorage.setItem("expire_at", expir);
            Message.success(res.message);
            router.push(path_to);
            resolve({
              status: true,
            });
          } else {
            Message.warning(res.message);
            resolve({
              status: false,
            });
          }
        })
        .catch((error) => {
          Message.error(error.message);
          reject(error.message);
        });
    });
  };

  /*
   * Logout 方法
   */
  Vue.prototype.$logout = (url, params) => {
    return instance(url, { params });
  };

  /*
   * getUserInfo 方法
   */
  Vue.prototype.$getUserInfo = () => {
    store.dispatch("user/updateUserInfo", { success: 111 });
    instance(api_user)
      .then((res) => {
        if (res.success) {
          let data = res.data;
          store.dispatch(namespace + "updateUserInfo", data);
        } else {
          console.log("获取失败");
          store.dispatch(namespace + "updateUserInfo", { success: 111 });
        }
      })
      .catch((error) => {
        console.log(error);
      });
  };
};

// 判断是否是直接引入文件
if (typeof window !== "undefined" && window.Vue) {
  install(window.Vue);
}

export { version, winyh };

export default { install, version, winyh };

Copy the code

Configuration parameters can be configured as required

Use (plugin, {timeout: 1000, // Timeout set tokenKey: "token", // Token local storage key whiteList: ["login"], // whiteList -> Not yet implemented homeUrl: BaseURL: "", // request prefix namespace: "", // configure headers for the vuex namespace: {// Request header "content-Type ": "application/json",}, loginConfig: {logo: "", // top logo title:" system name ", // left caption description: "", // left description left_img: ", // left picture system_name: ", // right subsystem name system_logo: ", // right subsystem logo API_login:" "/ API /auth/login", // request address}, router, // temporarily required store, // temporarily required});Copy the code

additional

When the plug-in is used, these methods can be used directly in the project without having to be reconfigured each time. Put your own package in NPM. You can do version maintenance and global use. You can also package it as a. TGZ file and install it locally using CNPM I /path/to/winyh.tgz

this.$post()

this.$get()

.