步骤
- 创建vue2项目
- 创建utils/directiveArr.js文件
export const checkArr=(key)=>{
let arr=[1,3,5]
if (arr.indexOf(key)>-1) {
return true
}else{
return false
}
}
- 创建directives/showBtn.js文件,引入utils/directiveArr文件
import { checkArr } from "@/utils/directiveArr";
export default {
inserted(el,binding){
let val=binding.value //获取自定义指令传来的值
if(val){/
let has=checkArr(val)//调用checkArr函数判断是否存在数组里面
if (!has) {
el.parentNode&&el.parentNode.removeChild(el)//存在调用el属性到父级删除自己
}
}else{
throw new Error('error')
}
}
}
- 在页面里使用自定义指令,启动项目之后会发现只有一个按钮显示,这是因为在utils/directiveArr.js文件里面的checkArr函数的arr数组里面没有2这个值,所以就没有显示按钮2 当我们改变按钮2传的值为3时就会显示
<template>
<div class="home">
<button v-show-btn='1'>按钮1</button>
<button v-show-btn='2'>按钮2</button>
</div>
</template>
<script>
import showBtn from "@/directives/showBtn";//引入设置的自定义指令
export default {
name: "HomeView",
components: {},
directives: {
showBtn,//注册
},
};
</script>
配合moack数据+vuex+接口实现自定义指令按钮权限的控制
- 安装axios 新建utils/http.js文件进行配置
import axios from "axios";
const https = axios.create({
baseURL: "https://www.fastmock.site/mock/d8cbb6be1a68921dd115e83e225ccaaf/q",//moack数据的域名地址
timeout: 1000,
});
// 添加请求拦截器
https.interceptors.request.use(
function (config) {
// 在发送请求之前做些什么
return config;
},
function (error) {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
https.interceptors.response.use(
function (response) {
// 对响应数据做点什么
let {data}=response
return data;
},
function (error) {
// 对响应错误做点什么
return Promise.reject(error);
}
);
export default https;
- 新建api/http.js文件
import https from "@/utils/http";
// 按钮权限数组
export const getArr = () => {
return https({
method: "get",
url: "/btnText",
});
};
3.store/index.js配置
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
arr:[1,3] //按钮权限数组
},
getters: {
checkArr: (state) => (key) => {//监听变化
let arr = state.arr;
return arr.indexOf(key) != -1 ? true : false;
},
},
mutations: {
setArr(state,val){//修改按钮权限数组
state.arr=val
}
},
actions: {
},
modules: {},
});
- router/index.js里配置
import store from "@/store"; //引入vuex
router.beforeEach((to,from,next)=>{
store.commit("setArr",[4,5])
console.log(store,'store');
next()
})
- 修改directives/showBtn.js文件内容,就会发现页面里没有按钮了,因为我们在router.beforeEach里面修改了值,只有传入的值是4和5的情况下才会显示按钮
import store from "@/store";//引入vuex
export default {
inserted(el,binding){
let val=binding.value
let has=store.getters.checkArr(val)//调用vuex中的getters里面的方法
if(val){
if (!has) {
el.parentNode&&el.parentNode.removeChild(el)
}
}else{
throw new Error('error')
}
}
}
通过vuex异步请求接口动态修改按钮权限的值
- 修改store/index
import Vue from "vue";
import Vuex from "vuex";
import { getArr } from "@/api/index";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
arr:[1,3]
},
getters: {
checkArr: (state) => (key) => {
let arr = state.arr;
return arr.indexOf(key) != -1 ? true : false;
},
},
mutations: {
setArr(state,val){
state.arr=val
}
},
actions: {
setArrAsync(){
return new Promise((reslove)=>{
getArr().then(res=>{
reslove(res)
})
})
}
},
modules: {},
});
- 修改router/index.js中的router.beforeEach 就可以实现用自定义指令动态控制按钮权限了
router.beforeEach(async (to, from, next) => {
let reslove = await store.dispatch("setArrAsync");//调用接口
let { code, arr } = reslove;
if (code == 1) {
store.commit("setArr", arr);//arr[1, 2, 5]
}
next();
});
优化+设置请求超时
问题:每次进入页面都会重新请求
- 安装element-ui,新建login.vue
- 新建utils/promiesUtils文件
//utils/promiesUtils.js
const retry = (fn, data) => {
return new Promise((reslove, reject) => {
Promise.race([fn, timeOut(data)])
.then((res) => {
reslove(res);
})
.catch((err) => {
reject("race 内部超时");
});
});
};
const timeOut = (dalay) => {
return new Promise((reslove, reject) => {
setTimeout(() => {
reject(false);
}, dalay);
});
};
export default {
retry
};
3.在main.js配置全局element-ui,引入并注册全局方法
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import ElementUI from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
import promiesUtils from "@/utils/promiesUtils";
Vue.prototype.$promiesUtils = promiesUtils;
Vue.use(ElementUI);
Vue.config.productionTip = false;
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
- login.vue配置,配置login.vue路由 使用配置的方法设置请求超时
<template>
<div>
<el-button @click="doLogin">登陆</el-button>
</div>
</template>
<script>
import { mapMutations, mapActions } from "vuex";
export default {
methods: {
...mapMutations(["setArr"]),
...mapActions(["setArrAsync"]),
async doLogin() {
try {
let btnArr = await this.$promiesUtils.retry(this.setArrAsync(), 2000);
let { code, arr } = btnArr;
console.log(arr);
code == 1 && this.setArr(arr);
this.$router.push({ path: "/" });
} catch (error) {
console.log(error);
}
},
},
};
</script>
- 修改router/index.js
import Vue from "vue";
import VueRouter from "vue-router";
import HomeView from "../views/HomeView.vue";
import store from "@/store";
import retry from "@/utils/promiesUtils";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "home",
component: HomeView,
},
{
path: "/about",
name: "about",
component: () =>
import(/* webpackChunkName: "about" */ "../views/AboutView.vue"),
},
{
path: "/login",
name: "login",
component: () =>
import(/* webpackChunkName: "Login" */ "../views/Login.vue"),
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach(async (to, from, next) => {
if (store.state.arr.length <= 0 && to.path !== "/login") {
try {
let reslove = await retry(store.dispatch("setArrAsync"), 2000);
// let reslove = await store.dispatch("setArrAsync");
let { code, arr } = reslove;
console.log(reslove);
if (code == 1) {
store.commit("setArr", arr); //arr[1, 2, 5]
}
} catch (error) {
next('/login')
}
}
next();
});
export default router;