Vue 自定义指令

220 阅读2分钟

05571a2c58870f9301399b7b823de69c.jpeg

概念: 指令(Directives)是 Vue 提供的带有 v- 前缀 的 特殊 标签属性

  • 内容渲染指令(v-html、v-text)

  • 条件渲染指令(v-show、v-if、v-else、v-else-if)

  • 事件绑定指令(v-on)

  • 属性绑定指令 (v-bind)

  • 双向绑定指令(v-model)

  • 列表渲染指令(v-for)

### 自定义指令:

1. 自定义指令

同时Vue也支持让开发者,自己注册一些指令。这些指令被称为自定义指令 每个指令都有自己各自独立的功能

2.注册指令

使用 Vue.directive 方法或 directive 函数来注册指令。这些方法接受两个参数:指令名称和指令配置对象。

    inserted:被绑定元素插入父节点时调用的钩子函数
    el:使用指令的那个DOM元素
//在main.js中
Vue.directive('指令名', {
  "inserted" (el) {
    // 可以对 el 标签,扩展额外功能
    el.focus()
  }
})
//在Vue组件的配置项中
directives: {
  "指令名": {
    inserted () {
      // 可以对 el 标签,扩展额外功能
      el.focus()
    }
  }
}

使用指令:- 使用指令 在使用指令的时候,一定要先注册再使用,否则会报错 使用指令语法: v-指令名。如: **** ```

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

3. 钩子函数:

指令配置对象中的钩子函数定义了指令的生命周期。常用的钩子函数包括 bindmountedupdatecomponentUpdatedunbind。这些钩子函数在指令的不同生命周期阶段被调用,允许开发者在相应的时机执行自定义的逻辑。

4.**钩子函数参数

指令的钩子函数可以接受一些参数,用于传递信息给指令的行为逻辑。常用的参数包括 el(指令所绑定的元素)、binding(一个对象,包含指令的绑定值、参数、修饰符等信息)、vnode(Vue 编译生成的虚拟节点)和 oldVnode(上一个虚拟节点)等。

常见自定义指令应用场景

封装 v-loading ,实现加载中的效果

分析

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

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

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

代码实现
<template>
  <div>
     <!-- 数据来了之后 -->
    <div class="box" v-loading="isShow">
      <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>
    <!-- 数据没来之前 loading -->
    <div class="box1" v-loading="isShow"></div>
  </div>
</template>

<script>
// 安装axios =>  yarn add axios
import axios from "axios";

// 请求方式:get
export default {
  data() {
    return {
      list: [],
      isShow: true,
    };
  },
  async created() {
    // 1. 发送请求获取数据
    const res = await axios.get("http://xxxx/api/news");

    setTimeout(() => {
      // 2. 更新到 list 中,用于页面渲染 v-for
      this.list = res.data.data;
      // 3. 改变isShow的值
      this.isShow = false;
    }, 3000);
  },
  // loading 加载状态
  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("./loading.gif") no-repeat center;
}

.box1 {
  width: 300px;
  height: 300px;
  border: 10px solid pink;
  position: relative;
  margin-top: 30px;
}

.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>