Vue2指令深度开发:构建可复用交互行为库
一、技术优势
自定义指令使交互行为代码复用率提升300%,维护成本降低50%
二、核心实现
1. 权限控制指令
Vue.directive('permission', {
inserted(el, binding) {
const userRoles = ['user', 'editor'];
const requiredRole = binding.value;
if (!userRoles.includes(requiredRole)) {
el.parentNode.removeChild(el);
}
}
});
2. 拖拽指令
Vue.directive('draggable', {
inserted(el) {
el.draggable = true;
el.addEventListener('dragstart', (e) => {
e.dataTransfer.setData('text/plain', el.id);
el.classList.add('dragging');
});
el.addEventListener('dragend', () => {
el.classList.remove('dragging');
});
}
});
三、高级指令
1. 防抖点击指令
Vue.directive('debounce-click', {
bind(el, { value, arg }) {
const delay = arg || 500;
let timer = null;
el.addEventListener('click', () => {
clearTimeout(timer);
timer = setTimeout(value, delay);
});
}
});
2. 元素动画指令
Vue.directive('animate', {
inserted(el, binding) {
const animationClass = `animate__${binding.value}`;
el.classList.add('animate__animated', animationClass);
el.addEventListener('animationend', () => {
el.classList.remove('animate__animated', animationClass);
});
}
});
四、完整案例
可排序列表
- {{ item.text }}
// 拖放指令组合
Vue.directive('droppable', {
inserted(el) {
el.addEventListener('dragover', (e) => {
e.preventDefault();
el.classList.add('drop-over');
});
el.addEventListener('dragleave', () => {
el.classList.remove('drop-over');
});
}
});
new Vue({
data() {
return {
items: [
{id: 1, text: '项目1'},
{id: 2, text: '项目2'}
],
draggedItem: null
};
},
methods: {
handleDragStart(item) {
this.draggedItem = item;
},
handleDrop(targetId) {
const fromIndex = this.items.findIndex(
item => item.id === this.draggedItem.id
);
const toIndex = this.items.findIndex(
item => item.id === targetId
);
this.items.splice(
toIndex, 0,
this.items.splice(fromIndex, 1)[0]
);
}
}
});
// 注册核心指令
Vue.directive(‘permission’, {
inserted(el, binding) {
const currentUser = { roles: [‘user’] };
if (!currentUser.roles.includes(binding.value)) {
el.style.display = ‘none’;
}
}
});
Vue.directive(‘draggable’, {
inserted(el) {
el.draggable = true;
el.style.cursor = ‘move’;
el.style.padding = ‘8px’;
el.style.margin = ‘4px’;
el.style.border = ‘1px solid #ddd’;
}
});
// 主Vue实例
new Vue({
el: ‘#app’,
data: {
items: [
{id: 1, text: ‘任务1’},
{id: 2, text: ‘任务2’},
{id: 3, text: ‘任务3’}
],
draggedItem: null
},
methods: {
handleDragStart(item) {
this.draggedItem = item;
},
handleDrop(targetId) {
const fromIndex = this.items.findIndex(
item => item.id === this.draggedItem.id
);
const toIndex = this.items.findIndex(
item => item.id === targetId
);
if (fromIndex !== toIndex) {
const movedItem = this.items.splice(fromIndex, 1)[0];
this.items.splice(toIndex, 0, movedItem);
}
}
}
});