Vue自定义指令

自定义指令

一、自定义指令

1.指令介绍

  • 内置指令:v-html、v-if、v-bind、v-on... 这都是Vue给内置的一些指令,可以直接使用

  • 自定义指令:同时Vue也支持让开发者,自己注册一些指令。这些指令被称为自定义指令

    每个指令都有自己各自独立的功能

2.自定义指令

概念:自己定义的指令,可以封装一些DOM操作,扩展额外的功能

3.自定义指令语法

  • 全局注册

    js 复制代码
    //在main.js中
    Vue.directive('指令名', {
      "inserted" (el) {//inserted 表示被插入时生效,双引号可以略
        // 可以对 el 标签,扩展额外功能
        el.focus()
      }
    })
  • 局部注册

    js 复制代码
    //在Vue组件的配置项中
    directives: {
      "指令名": {
        inserted (el) {
          // 可以对 el 标签,扩展额外功能
          el.focus()
        }
      }
    }
  • 使用指令

    注意:在使用指令的时候,一定要先注册 ,再使用 ,否则会报错

    使用指令语法: v-指令名。如:

    注册 指令时不用 加v-前缀 ,但使用时 一定要加v-前缀

4.指令中的配置项介绍

inserted:被绑定元素插入父节点时调用的钩子函数

el:使用指令的那个DOM元素

5.代码示例

需求:当页面加载时,让元素获取焦点(autofocus在safari浏览器有兼容性)

App.vue

html 复制代码
  <div>
    <h1>自定义指令</h1>
    <input v-focus ref="inp" type="text">
  </div>

main.js

js 复制代码
//全局注册指令
Vue.directive('focus',{
    // inserted会在指令所在的元素,被插入到页面时触发
    inserted(el){
        el.focus()
    }
})

export default

js 复制代码
  //在Vue组件的配置项中局部注册
  directives: {
    "focus": {
      inserted (el) {
        // 可以对 el 标签,扩展额外功能
        el.focus()
      }
    }
  }

6.总结

1.自定义指令的作用是什么?

2.使用自定义指令的步骤是哪两步?

二、自定义指令-指令的值

1.需求

实现一个 color 指令 - 传入不同的颜色, 给标签设置文字颜色

2.语法

1.在绑定指令时,可以通过"等号"的形式为指令 绑定 具体的参数值

html 复制代码
<div v-color="color">我是内容</div>

2.通过 binding.value 可以拿到指令值,指令值修改会 触发 update 函数

js 复制代码
directives: {
  color: {
    inserted (el, binding) {
      el.style.color = binding.value
    },
    update (el, binding) {
      el.style.color = binding.value
    }
  }
}

3.代码示例

App.vue

html 复制代码
<template>
  <div>
    <!--显示红色-->
    <h2 v-color="color1">指令的值1测试</h2>
    <!--显示蓝色-->
    <h2 v-color="color2">指令的值2测试</h2>
    <button @click="updateColor1()">
      改变第一个h1的颜色
    </button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      color1: 'red',
      color2: 'blue'
    }
  },
  directives :{
    color :{
      //元素被添加到页面时的逻辑
      inserted(el,binding){
        console.log("插入")
        el.style.color = binding.value
      },
      //值更新时的逻辑
      update(el,binding){
        console.log("更新")
        el.style.color = binding.value
      },
    }
  },
  methods :{
    updateColor1(){
      this.color1 = 'green';
    }
  }
}
</script>
<style>
</style>

三、自定义指令的钩子函数

Vue 实例从创建、运行到销毁期间,总是伴随着各种各样的事件,这些事件统称为生命周期。生命周期钩子是生命周期事件的别名,钩子函数也就是生命周期函数。

自定义指令也有自己的生命周期函数,即钩子函数。一个自定义指令可以提供以下几个钩子函数:

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

钩子函数可以传入的参数主要包括el、binding、vnode 和 oldVnode,其中:

  • el:指令所绑定的元素,可以用来直接操作DOM。
  • binding :一个对象,包含以下属性。
    • name:指令名,不包括"v-"前缀。
    • value:指令的绑定值,例如v-my-directive="1+1"中,绑定值为 2。
    • oldValue:指令绑定的前一个值,仅在update和componentUpdated钩子中可用,无论值是否改变都可用。
    • expression:字符串形式的指令表达式。例如v-my-directive="1+1"中,表达式为"1+1"
    • arg:传给指令的参数,可选。例如"v-my-directive:foo"中,参数为"foo"
    • modifiers:一个包含修饰符的对象。例如"v-my-directive.foo.bar"中,修饰符对象为{ foo: true, bar: true }。
  • vnode:Vue编译生成的虚拟节点。
  • oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用

另外,除了el 之外,其他参数都是只读的,切勿进行修改。

四、自定义指令-v-loading指令的封装

1.场景

实际开发过程中,发送请求需要时间,在请求的数据未回来时,页面会处于空白状态 => 用户体验不好

2.需求

封装一个 v-loading 指令,实现加载中的效果

3.分析

1.本质 loading效果就是一个蒙层,盖在了盒子上

2.数据请求中,开启loading状态,添加蒙层

3.数据请求完毕,关闭loading状态,移除蒙层

4.实现

1.准备一个 loading类,通过伪元素定位,设置宽高,实现蒙层

2.开启关闭 loading状态(添加移除蒙层),本质只需要添加移除类即可

3.结合自定义指令的语法进行封装复用

css 复制代码
.loading:before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #fff url("./loading.gif") no-repeat center;
}

5.实现代码

html 复制代码
<template>
    <div class="box" v-loading="isLoading">
      <ul>
        <li v-for="item in list" :key="item.id" class="news">
          <div class="left">
            <div class="title">{{ item.title }}</div>
            <div class="info">
              <span>{{ item.source }}</span>
              <span>{{ item.time }}</span>
            </div>
          </div>
          <div class="right">
            <img :src="item.img" alt="">
          </div>
        </li>
      </ul>
    </div>
</template>

<script>
// 安装axios =>  yarn add axios || npm i axios
import axios from 'axios'

// 接口地址:http://?/api/news
// 请求方式:get
export default {
  data() {
    return {
      list: [],
      isLoading: true,
      isLoading2: false
    }
  },
  async created() {
    // 1. 发送请求获取数据
    const res = await axios.get('http://?/api/news')

    setTimeout(() => {
      // 2. 更新到 list 中,用于页面渲染 v-for
      this.list = res.data.data
      this.isLoading = false
    }, 2000)
  },
  directives: {
    loading: {
      inserted(el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      },
      update(el, binding) {
        binding.value ? el.classList.add('loading') : el.classList.remove('loading')
      }
    }
  }
}
</script>

<style>
.loading:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: #fff url('./assets/loading.gif') no-repeat center;
}
.box {
  width: 800px;
  min-height: 500px;
  border: 3px solid orange;
  border-radius: 5px;
  position: relative;
}

.news {
  display: flex;
  height: 120px;
  width: 600px;
  margin: 0 auto;
  padding: 20px 0;
  cursor: pointer;
}

.news .left {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding-right: 10px;
}

.news .left .title {
  font-size: 20px;
}

.news .left .info {
  color: #999999;
}

.news .left .info span {
  margin-right: 20px;
}

.news .right {
  width: 160px;
  height: 120px;
}

.news .right img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>
相关推荐
卸任9 小时前
Vibe coding工具使用心得
前端·ai编程
brien910 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance10 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M10 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写10 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李10 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易11 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding11 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马11 小时前
前沿视界
前端
kyriewen11 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员