Vue - 模板语法拓展

本文详细介绍了如何在Vue2.x和3.x中创建自定义指令,包括生命周期函数的使用,以及在实际项目中如权限控制和页面路由中的应用实例。
摘要由CSDN通过智能技术生成

模板语法 - 拓展

自定义指令

在 Vue 中,你可以使用Vue.directive()方法来创建自定义指令。以下是一个基本的步骤说明如何创建自定义指令:

Vue2.x定义自定义指令

全局定义:

Vue.directive('my-directive', {
  bind(el, binding, vnode) {
    // 当指令绑定到元素上时触发
    // el 是指令绑定的元素
    // binding 是一个对象,包含以下属性:
    //   - name: 指令名,不包括 v- 前缀。
    //   - value: 指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
    //   - oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
    //   - expression: 字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
    //   - arg: 传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
    //   - modifiers: 一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
    // vnode 是 Vue 编译生成的虚拟节点
  },
  inserted(el, binding, vnode) {
    // 当被绑定的元素插入到 DOM 中时触发
  },
  update(el, binding, vnode, oldVnode) {
    // 当指令的绑定值更新时触发
    // oldVnode 是上一个虚拟节点
  },
  componentUpdated(el, binding, vnode, oldVnode) {
    // 当组件的 VNode 及其子 VNode 更新时触发
  },
  unbind(el, binding, vnode) {
    // 当指令与元素解绑时触发
  }
})

局部定义(在组件选项中):

directives: {
  'my-directive': {
    // ... 与全局定义相同 ...
  }
}
Vue3.x定义自定义指令
app.directive('my-directive', {  
  beforeMount(el, binding, vnode, prevVnode) {  
    // 当指令绑定到元素上之前触发  
    // el 是指令绑定的元素  
    // binding 是一个对象,包含与 Vue 2.x 类似的属性  
    // vnode 是 Vue 编译生成的虚拟节点  
    // prevVnode 是前一个虚拟节点,如果是初始渲染则为 null  
  },  
  mounted(el, binding, vnode, prevVnode) {  
    // 当被绑定的元素插入到 DOM 中后触发  
  },  
  beforeUpdate(el, binding, vnode, prevVnode) {  
    // 当指令的绑定值可能发生变化时触发  
    // 此时元素和组件尚未更新  
  },  
  updated(el, binding, vnode, prevVnode) {  
    // 当指令的绑定值更新,并且元素和组件已经更新后触发  
  },  
  beforeUnmount(el, binding, vnode, prevVnode) {  
    // 当指令与元素解绑之前触发  
  },  
  unmounted(el, binding, vnode, prevVnode) {  
    // 当指令与元素解绑后触发  
  }  
});

在 Vue 3.x 中,自定义指令的生命周期钩子函数与 Vue 2.x 有所不同,主要有以下几点变化:

  • bindinserted 在 Vue 3.x 中合并成了 mounted
  • update 在 Vue 3.x 中变成了 beforeUpdateupdated
  • componentUpdated 在 Vue 3.x 中不再存在,因为 updated 钩子现在是在 DOM 更新之后调用的。
  • unbind 在 Vue 3.x 中变成了 unmounted

实战模拟

按钮级权限控制
import {createApp} from 'vue'
import App from './App.vue'
import store from './store'
import router from './router';

// 创建vue实例(声明为Vue而不是app等其他的原因是如果不命名为Vue,我的WebStorm的版本在组件中使用自定义指令会报警告,可能是因为这个版本还没有完全兼容好Vue3.x的写法,使用Vue命名是为了让它识别成Vue2.x的写法就不报警告了。强迫症患者)
const Vue = createApp(App);

// 检查用户权限
function checkUserPermission(userPermissions, requiredPermission) {
    return userPermissions.includes(requiredPermission);
}

// 封装显示/隐藏元素的逻辑
function toggleElementDisplay(el, show) {
    el.style.display = show ? '' : 'none';
}

// 在Vue应用实例上定义全局自定义指令
Vue.directive('permission', {
    mounted(el, binding) {
        const hasPermission = checkUserPermission(store.state.user.userPermissions, binding.value);
        toggleElementDisplay(el, hasPermission);
    },

    updated(el, binding) {
        const hasPermission = checkUserPermission(store.state.userPermissions, binding.value);
        toggleElementDisplay(el, hasPermission);
    }
});

Vue.use(store).use(router);

// 挂载实例
Vue.mount('#app');

这样一个全局的权限控制指令就完成了。

既然说到了权限控制,那就不得不说一下页面级别的权限控制。

页面路由 - 页面级权限控制
import {createRouter, createWebHistory} from 'vue-router';
import {useStore} from "vuex";

const routes = [
	{
		path: '/',
		name: 'Index',
		meta: {
			title: '首页',
			keepAlive: true,
			permissionName: 'default',
			requireAuth: true // 标记这个路由需要权限
		},
		component: () => import('@/pages/Home.vue')
	},
	{
		path: '/ces',
		name: 'ces',
		meta: {
			title: 'ces',
			keepAlive: true,
			permissionName: 'admin',
			requireAuth: true // 标记这个路由需要权限
		},
		component: () => import('@/pages/ces.vue')
	}
];

const router = createRouter({
	history: createWebHistory(),
	routes
});

// 检查用户是否有权限访问某个路由
function hasPermission(to) {
	const store = useStore();
	const user = store.state.user;
	// 检查用户是否已登录,以及是否有访问该路由的权限
	// 这通常涉及到检查用户的角色或其他权限信息
	return store.state.isLoggedIn && (to.meta.requireAuth ? user.hasPermission(to) : true);
}

// 全局前置守卫
router.beforeEach((to, from, next) => {
	const store = useStore(); // 获取 Vuex store 实例
	const user = store.state.user; // 获取用户状态
	const isLoggedIn = store.getters.isLoggedIn; // 获取登录状态
	const hasPermission = store.getters.hasPermission; // 获取权限检查函数

	if (to.meta.requireAuth) {
		if (isLoggedIn && hasPermission(to.meta.permissionName)) {
			// 用户已登录且拥有权限,进入路由
			next();
		} else {
			alert('权限不符,请确认权限')
			// 用户未登录或没有权限,重定向到登录页面或其他处理逻辑
			next('/');
		}
	} else {
		// 不需要权限的路由,直接通过
		next();
	}
});

export default router;

使用 Vue Router 的全局前置守卫 beforeEach,在每个路由跳转前执行权限检查。如果用户没有权限访问目标路由,就使用 next 函数重定向到登录页面或其他处理逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值