什么是Vue.js插件
按照Vue.js 官网的说法。插件通常用来为 Vue 添加全局功能。Vue 插件
Vue.js 插件可以实现什么功能
- 添加全局方法或者 property
- 添加全局资源:指令/过滤器/过渡等
- 通过全局混入来添加一些组件选项
- 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现
- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能
这篇文章说下我自己用插件的方式提供一个包含登录界面的插件,插件内提供 axios 的封装。这样每次新项目就可以按照插件,快速实现登录和 axios 功能了。只是提供一个思路,大家可以在参考下自己做拓展。比如提供一个开箱即用的用户登录,注册,找回密码等功能的插件。插件里也可以注入一个库,实现自己的方法。
功能列表
- 统一登录页
- axios 可配置化封装
实现的关键点
- 暴露一个install 方法
- 在Vue 原型上做一系列的功能或者函数挂载
- Vue.use 时传入定制化参数
贴下官网示例代码
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
// 可以通过 options 获取外部传入的参数 options.someOptions = true
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
使用
import myPlugin from "myplugin"
Vue.use(myPlugin, {
someOption: true
})
贴下我的实现
只要是理解思想,实现思路和原理。这样就能实现自己想要的功能了
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 };
配置参数可以随意配置自己需要的
Vue.use(plugin, {
timeout: 1000, // 超时设置
tokenKey: "token", // token本地存储的键
whiteList: ["login"], // 白名单->暂未实现
homeUrl: "/test", // 登录后默认跳转的首页
api_user: "/dasa", // 获取用户信息的接口地址
baseURL: "", // 请求前缀
namespace: "", // vuex 命名空间配置
headers: {
// 请求头
"Content-Type": "application/json",
},
loginConfig: {
logo: "", // 顶部 logo
title: "系统名称", // 左侧标题
description: "", // 左侧描述
left_img: "", // 左侧图片
system_name: "", // 右侧子系统名称
system_logo: "", // 右侧子系统 logo
api_login: "/api/auth/login", // 登录请求地址
},
router, // 暂时必填
store, // 暂时必填
});
附加
当插件使用时,可以直接在项目里使用这些方法了,不需要每次都重新配置。把自己的包放到 npm. 就可以做版本维护和全局使用了。当然也可以在本地打包成.tgz
文件在本地安装使用 cnpm i /path/to/winyh.tgz
this.$post()
this.$get()
…
今天的文章Vue.js 插件开发分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/20052.html