基础
需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
Vuejs 内置指令如下:
- v-if
- v-else
- v-else-if
- v-show
- v-html
- v-text
- v-on
- v-for
- v-bind
- v-model
- v-pre
- v-cloak
- v-once
常用指令, 如下:
- v-if
- v-else
- v-else-if
- v-show
- v-for
- v-model
- v-bind
- v-on
注册 directive
- 全局注册
// 注册一个全局自定义指令 `v-focus` Vue.directive('focus', { // 当被绑定的元素插入到 DOM 中时…… inserted: function (el) { // 聚焦元素 el.focus() } })
- 局部注册
Vue.component("component", { directives: { focus: { inserted: function (el) { el.focus() } } } })
使用 directive
<input v-focus />
实战 click_out_side
在一些下拉框应用的场景中, 例如: 点击用户头像, 出现 ActionSheet.
点击 ActionSheet, ActionSheet 不消失, 点击页面其他位置时, ActionSheet 消失, 即为 click_out_side
实现原理
为父容器添加 v-click-out-side 指令, 当点击区域为该容器之外任意位置时, 执行指令相关事件.
当指令 bind 时, 增加监听函数, 并执行相关操作
当指令 unbind 时, 移除事件监听, 释放内存
每当指令进行事件监听时, 在 unbind 时务必要移除事件监听并释放内存
否则当前组件被频繁创建销毁时, 会造成内存溢出
// 将其属性置位 null, Javascript 垃圾回收机制 将会自动回收内存 el.__vueClickOutside__ = null // or // 使用 delete Object.key 也能达到该效果 delete el.__vueClickOutside__
- HTML 结构
.test { padding: 50px; border: 1px solid black; margin: 50px; background-color: white; cursor: pointer; }
<div id="app"> <!-- 点击 div.test 容器之外位置, 执行 outside(), 使 clickOutside 自增 1--> <!-- 点击 div.test 容器之内位置, 执行 inside(), 使 clickInside 自增 1--> <div class="test" v-click-out-side="outside" @click="inside"> Test </div> <pre> { clickOutside: {{ clickOutside }}, clickInside: {{ clickIntside }}, } </pre> </div>
new Vue({ el: '#app', data: function () { return { clickOutside: 0, clickInside: 0 } }, methods: { outside: function(e) { this.clickOutside += 1 console.log('clicked outside!') }, inside: function(e) { this.clickInside += 1 console.log('clicked inside!') } }, directives: { 'click-out-side': { bind: function(el, binding) { // 1. 确保指令所接受的参数为一个 Function if (typeof binding.value !== 'function') { console.warn("[Vue-click-outside:]绑定的值必须为一个 Function") } // 2. 定义一个 handler Function const handler = e => { if (!el.contains(e.target) && el !== e.target) { binding.value(e) } } // 3. 将 handler 缓存在 DOM 元素之上 el.__vueClickOutside__ = handler // 4. 监听 document 的 click 事件 document.addEventListener('click', handler) }, unbind: function(el, binding) { // 5. 指令解除绑定时, 释放监听事件内存 document.removeEventListener('click', el.__vueClickOutside__) el.__vueClickOutside__ = null } } } })