浅谈vue钩子函数自定义指令

一、vue中自定义指令

1. 什么是自定义指令?

除了使用 Vue 提供的内置指令之外,我们可以自定义一些自己的指令,来实现业务操作。

2. 什么时候需要自定义指令?

当你需要不可避免的操作 DOM 的时候,使用自定义指令来解决

3. 如何注册和使用自定义指令?

1. 注册
  • 全局注册,在任何组件中都可以使用全局注册自定义指令
  • 局部注册,只能在当前组件使用该指令

如果需要在多个不同的组件中使用该指令,则把它定义为全局的
非通用的,不需要多次使用的指令我们定义到局部

2. 使用

例:注册一个自定义指令focus

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

注册一个全局自定义指令 v-focus
使用 声明Vue.directive()
参一是指令的名字

  • 指令的名字随便起,但是在使用的时候务必加上 v- 前缀,所以我们在其名字的时候就不要加 v- 前缀
  • 如果是驼峰命名法的名称,则在使用的时候需要把驼峰转为小写使用 - 连接起来(例:myFocus 为 v-my-focus)

参二是钩子函数
下面我们将简单介绍钩子函数

二、钩子函数

1. 简介钩子函数

vue中提供了5个钩子函数

  • bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。(bind 中拿不到父元素)
  • inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。如果你需要操作作用指令的父元素,则最起码写到这个 inserted 中
  • update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
  • componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
  • unbind:只调用一次,指令与元素解绑时调用。

每个钩子函数都可以接收两个参数:

  • el 作用该指令的 DOM 对象
  • binding 一个对象,可以获取指令的值等信息
注意:
  1. bind 和 inserted 的相同之处是一上来都执行一次,以后再也不会执行,异同之处在于,bind 拿不到父元素,inserted 可以拿到父元素
  2. update 和 componentUpdated 只有在指令的绑定的值发生更新的时候才会触发调用
  3. update 和 componentUpdated 的区别是:
    update 中获取的是更新的之前的指令所在的 DOM 内容
    componentUpdated 获取的是更新之后的最新 DOM 内容
    update 拿到的是数据改变视图之前的视图内容
    componentUpdated 拿到的是数据改变视图之后的视图内容
    也就是说如果你需要获取数据改变视图之前的内容,则把代码写到 update 中
    如果需要获取数据改变视图之后的内容,则把代码写到 componentUpdated 里面

例: 模拟v-show实现

<div id="app">
    <!-- <input type="text" v-focus> -->
    <div class="box" v-my-show="seen">{{ seen }}</div>
  </div>
Vue.directive('my-show', {
    bind (el, binding) {
    inserted (el, binding) {
      console.log('my-show inserted')
      if (binding.value) {
        el.style.display = 'block'
      } else {
        el.style.display = 'none'
      }
    },
    update (el, binding) {
      // console.log('my-show update', el, binding)
      console.log('my-show update', el.innerHTML)
      if (binding.value) {
        el.style.display = 'block'
      } else {
        el.style.display = 'none'
      }
    },
    componentUpdated (el, binding) {
      console.log('my-show componentUpdated', el.innerHTML)
    },
    unbind () {
      console.log('my-show unbind')
    }
  })

2. 函数简写

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:

Vue.directive('color-swatch', function (el, binding) {
  el.style.backgroundColor = binding.value
})

我只关心 bind 和 inserted,所以可以这样简写

    Vue.directive('my-show', function (el, binding) {
      // console.log('my-show update', el, binding)
      // console.log('my-show update', el.innerHTML)
      if (binding.value) {
        el.style.display = 'block'
      } else {
        el.style.display = 'none'
      }
    })

模拟v-bind动态绑定属性值

<body>
  <div id="app">
    <h1 v-my-bind:title="message" v-my-bind:foo="message">{{ message }}</h1>
    <input type="text" v-model="message">
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // v-bind 作用
    // 动态绑定属性值
    // Vue.directive('my-bind', {
    //   bind (el, binding) {
    //     console.log(binding.value)
    //     el.setAttribute(binding.arg, binding.value)
    //   },
    //   update (el, binding) {
    //     el.setAttribute(binding.arg, binding.value)
    //   }
    // })

    // 很多时候,我们都会在 bind 和 update 中执行相同的代码
    // 所我们可以使用简写的方式,.直接给一个函数,该函数会被作为 bind 和 update 的时候执行的函数
    Vue.directive('my-bind', function (el, binding) {
      el.setAttribute(binding.arg, binding.value)
    })


    const app = new Vue({
      data: {
        message: 'Hello Vue.js!'
      },
      methods: {}
    }).$mount('#app')
  </script>
</body>

模拟v-bind绑定class

<style>
    .box {
      background-color: pink;
    }

    .box2 {
      color: red;
    }
  </style>
</head>
<body>
  <div id="app">
    <h1 v-my-bind:title="123">{{ message }}</h1>
    <input type="text" v-model="message">
    <input type="checkbox" v-model="toggleBox"> toggleBox
    <input type="checkbox" v-model="toggleBox2"> toggleBox2
    <div v-my-bind:class="{box: toggleBox, box2: toggleBox2}">
      hello vue
    </div>
  </div>
  <script src="node_modules/vue/dist/vue.js"></script>
  <script>
    // v-bind:class = "{}"
    // v-bind:class = "xxx"
    Vue.directive('my-bind', function (el, binding) {
      console.log('所在模板更新了')
      if (binding.arg === 'class') {
        for (let key in binding.value) {
          if (binding.value[key]) {
            // 作用类名
            el.classList.add(key)
          } else {
            el.classList.remove(key)
          }
        }
      } else {
        el.setAttribute(binding.arg, binding.value)
      }
    })
    const app = new Vue({
      data: {
        message: 'Hello Vue.js!',
        toggleBox: true,
        toggleBox2: true
      },
      methods: {}
    }).$mount('#app')
  </script>
</body>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值