✨ 14-自定义指令_函数式
This commit is contained in:
parent
ba61fc3655
commit
dbf4e201ce
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<script src="js/vue@2.7.16.js"></script>
|
||||||
|
<title>自定义指令_函数式</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app">
|
||||||
|
<h2>当前值:<span v-text="num"></span></h2>
|
||||||
|
<h2>放大十倍值:<span v-big="num"></span></h2>
|
||||||
|
<button @click="num++">点击</button>
|
||||||
|
|
||||||
|
<input type="text" v-fbind="num" />
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const vm = new Vue({
|
||||||
|
el: "#app",
|
||||||
|
data: { num: 10 },
|
||||||
|
directives: {
|
||||||
|
// 指令所在模板被重新解析时
|
||||||
|
big(el, binding) {
|
||||||
|
el.innerText = binding.value * 10;
|
||||||
|
},
|
||||||
|
fbind: {
|
||||||
|
bind(el, binding) {
|
||||||
|
console.log("bind");
|
||||||
|
el.value = binding.value;
|
||||||
|
},
|
||||||
|
inserted(el, binding) {
|
||||||
|
console.log("inserted");
|
||||||
|
el.focus();
|
||||||
|
},
|
||||||
|
update(el, binding) {
|
||||||
|
console.log("update");
|
||||||
|
el.value = binding.value;
|
||||||
|
el.focus();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</html>
|
|
@ -0,0 +1,135 @@
|
||||||
|
# Vue2 自定义指令全面指南
|
||||||
|
|
||||||
|
指令中的作用域时window!!!
|
||||||
|
|
||||||
|
## 一、指令类型对比
|
||||||
|
|
||||||
|
| 类型 | 语法 | 触发时机 | 适用场景 |
|
||||||
|
| ------ | ------------------------------------- | ------------- | ----------- |
|
||||||
|
| 函数式 | `directives: { big(el, binding) {} }` | bind + update | 简单DOM操作 |
|
||||||
|
| 对象式 | `directives: { fbind: { hooks } }` | 完整生命周期 | 复杂交互 |
|
||||||
|
|
||||||
|
## 二、对象式指令详解
|
||||||
|
|
||||||
|
### 1. 完整生命周期钩子
|
||||||
|
```javascript
|
||||||
|
fbind: {
|
||||||
|
// 指令第一次绑定到元素时调用(初始化设置)
|
||||||
|
bind(el, binding) {
|
||||||
|
el.value = binding.value;
|
||||||
|
},
|
||||||
|
// 被绑定元素插入父节点时调用
|
||||||
|
inserted(el, binding) {
|
||||||
|
el.focus(); // 自动获取焦点
|
||||||
|
},
|
||||||
|
// 所在组件更新时调用
|
||||||
|
update(el, binding) {
|
||||||
|
el.value = binding.value;
|
||||||
|
el.focus(); // 值更新后重新聚焦
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 执行流程示例
|
||||||
|
1. 初始化时:`bind` → `inserted`
|
||||||
|
2. 数据更新时:`update`
|
||||||
|
3. 模板重新解析时:`update`
|
||||||
|
|
||||||
|
## 三、最佳实践建议
|
||||||
|
|
||||||
|
### 1. 输入框增强指令
|
||||||
|
```javascript
|
||||||
|
Vue.directive('input-enhanced', {
|
||||||
|
inserted(el) {
|
||||||
|
el.select(); // 自动选中文本
|
||||||
|
},
|
||||||
|
update(el) {
|
||||||
|
// 防抖处理避免频繁触发
|
||||||
|
clearTimeout(el._timer);
|
||||||
|
el._timer = setTimeout(() => {
|
||||||
|
el.select();
|
||||||
|
}, 300);
|
||||||
|
},
|
||||||
|
unbind(el) {
|
||||||
|
// 清理工作
|
||||||
|
clearTimeout(el._timer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 性能优化技巧
|
||||||
|
```javascript
|
||||||
|
update(el, binding) {
|
||||||
|
if (binding.value !== binding.oldValue) {
|
||||||
|
// 只有值变化时才执行操作
|
||||||
|
el.value = binding.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 四、高级应用场景
|
||||||
|
|
||||||
|
### 1. 权限控制指令
|
||||||
|
```javascript
|
||||||
|
Vue.directive('permission', {
|
||||||
|
inserted(el, binding) {
|
||||||
|
if (!checkPermission(binding.value)) {
|
||||||
|
el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
使用方式:
|
||||||
|
```html
|
||||||
|
<button v-permission="'admin'">管理按钮</button>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 拖拽指令实现
|
||||||
|
```javascript
|
||||||
|
Vue.directive('drag', {
|
||||||
|
inserted(el) {
|
||||||
|
el.style.cursor = 'move';
|
||||||
|
el.onmousedown = function(e) {
|
||||||
|
// 拖拽逻辑实现
|
||||||
|
}
|
||||||
|
},
|
||||||
|
unbind(el) {
|
||||||
|
el.onmousedown = null; // 清理事件
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 五、常见问题解决方案
|
||||||
|
|
||||||
|
1. **指令不生效问题排查**
|
||||||
|
- 检查指令名称是否使用kebab-case(短横线)
|
||||||
|
- 确认绑定值是否为响应式数据
|
||||||
|
- 验证是否在正确的生命周期钩子操作DOM
|
||||||
|
|
||||||
|
2. **动态指令参数**
|
||||||
|
```html
|
||||||
|
<div v-demo:[dynamicArg]="value"></div>
|
||||||
|
```
|
||||||
|
```javascript
|
||||||
|
binding.arg // 获取动态参数
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **多修饰符处理**
|
||||||
|
```javascript
|
||||||
|
if (binding.modifiers.large) {
|
||||||
|
el.style.fontSize = '20px';
|
||||||
|
}
|
||||||
|
if (binding.modifiers.red) {
|
||||||
|
el.style.color = 'red';
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 六、与Vue3的对比
|
||||||
|
|
||||||
|
| 特性 | Vue2 | Vue3 |
|
||||||
|
| --------- | ---------------------- | ------------------- |
|
||||||
|
| 钩子名称 | `bind` → `beforeMount` | |
|
||||||
|
| | `inserted` → `mounted` | |
|
||||||
|
| | 新增`beforeUpdate` | |
|
||||||
|
| 参数传递 | 通过`binding`对象 | 更直观的上下文参数 |
|
||||||
|
| 组合式API | 无 | 支持setup中使用指令 |
|
Loading…
Reference in New Issue