技术文档中心
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
  • Vue2 基础

    • Vue 学习指南
    • Vue2 快速入门
    • Vue2 模板语法
    • Vue2 组件基础
    • Vue2 计算属性与侦听器
    • Vue2 生命周期
  • Vue2 进阶

    • Vue2 组件通信
    • Vue2 插槽详解
    • Vue2 混入与自定义指令
    • Vue2 过渡与动画
    • Vuex 状态管理
  • Vue2 高级

    • Vue2 性能优化
    • Vue2 服务端渲染(SSR)
    • Vue2 源码解析
  • Vue3 基础

    • Vue3 快速入门
    • Vue3 Composition API
    • Vue3 响应式系统
    • Vue3 组件基础
    • Vue3 生命周期
  • Vue3 进阶

    • Vue3 组合式函数
    • Vue3 组件通信
    • Vue3 Teleport 与 Suspense
    • Pinia 状态管理
    • Vue Router 4
  • Vue3 高级

    • Vue3 TypeScript
    • Vue3 性能优化
    • Vue3 测试
    • Vue3 SSR
    • Vue3 源码解析
  • 实战项目

    • Vue2 实战项目
    • Vue3 实战项目
    • Vue2 迁移 Vue3

Vue2 混入与自定义指令

混入(Mixins)

基本用法

// 定义混入对象
const myMixin = {
  created() {
    this.hello()
  },
  methods: {
    hello() {
      console.log('hello from mixin!')
    }
  }
}

// 使用混入
const Component = Vue.extend({
  mixins: [myMixin]
})

选项合并

const mixin = {
  data() {
    return {
      message: 'hello',
      foo: 'abc'
    }
  }
}

new Vue({
  mixins: [mixin],
  data() {
    return {
      message: 'goodbye',
      bar: 'def'
    }
  },
  created() {
    console.log(this.$data)
    // => { message: "goodbye", foo: "abc", bar: "def" }
  }
})

全局混入

Vue.mixin({
  created() {
    const myOption = this.$options.myOption
    if (myOption) {
      console.log(myOption)
    }
  }
})

自定义指令

注册指令

// 全局注册
Vue.directive('focus', {
  inserted(el) {
    el.focus()
  }
})

// 局部注册
directives: {
  focus: {
    inserted(el) {
      el.focus()
    }
  }
}

钩子函数

Vue.directive('demo', {
  bind(el, binding, vnode) {
    // 只调用一次,指令第一次绑定到元素时调用
  },
  inserted(el, binding, vnode) {
    // 被绑定元素插入父节点时调用
  },
  update(el, binding, vnode, oldVnode) {
    // 所在组件的 VNode 更新时调用
  },
  componentUpdated(el, binding, vnode, oldVnode) {
    // 指令所在组件的 VNode 及其子 VNode 全部更新后调用
  },
  unbind(el, binding, vnode) {
    // 只调用一次,指令与元素解绑时调用
  }
})

钩子函数参数

Vue.directive('demo', {
  bind(el, binding, vnode) {
    console.log(binding.value)    // 指令的绑定值
    console.log(binding.oldValue) // 指令绑定的前一个值
    console.log(binding.arg)      // 传给指令的参数
    console.log(binding.modifiers)// 修饰符对象
  }
})

实际应用

权限指令

Vue.directive('permission', {
  inserted(el, binding) {
    const { value } = binding
    const permissions = store.getters.permissions
    
    if (value && !permissions.includes(value)) {
      el.parentNode && el.parentNode.removeChild(el)
    }
  }
})

// 使用
<button v-permission="'admin'">删除</button>

防抖指令

Vue.directive('debounce', {
  inserted(el, binding) {
    let timer
    el.addEventListener('click', () => {
      if (timer) {
        clearTimeout(timer)
      }
      timer = setTimeout(() => {
        binding.value()
      }, 1000)
    })
  }
})

// 使用
<button v-debounce="handleClick">提交</button>

图片懒加载

Vue.directive('lazy', {
  inserted(el, binding) {
    const observer = new IntersectionObserver(([entry]) => {
      if (entry.isIntersecting) {
        el.src = binding.value
        observer.unobserve(el)
      }
    })
    observer.observe(el)
  }
})

// 使用
<img v-lazy="imageUrl" />
最近更新: 2026/1/27 15:51
Contributors: hailong
Prev
Vue2 插槽详解
Next
Vue2 过渡与动画