【Vue2】05 - 自定义指令和插槽

自定义和插槽

一:自定义指令

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

1:回顾内置指令

内置指令 - 就是之前学习过的指令,是vue自身提供的,可以参见我的这个笔记

在这里插入图片描述

2:自定义指令的两种写法

自定义指令方式一:全局指令注册main.js中 -> Vue.directive('指令名称', {指令对象})

// ============ main.js ================
// 全局注册自定义指令-Vue.directive("指令名", {指定对象})
Vue.directive("focus", {
  // el就是v-focus绑定的元素
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus();
  }
});
<!-- 一旦这个输入框插入进来页面中(DOM完成渲染),此时自动聚焦到该输入框 -->
<input v-focus type="text" v-model="name">

自定义指令方式二:局部注册,写在当前组件的export default中,只能在当前的组件中使用

export default {
  // 局部注册指令
  directives: {
    // 指令名:指令的配置项
    focus: {
      // 参数:el -> 绑定v-focus指令的元素
      inserted(el) {
        el.focus(); // 获取焦点
      }
    }
  }
}

3:总结一下

在这里插入图片描述

4:常用自定义指令实战

v-color -> 传入不同的颜色,给标签设置文字颜色

在这里插入图片描述

v-loading -> 实现加载中效果

在这里插入图片描述

<template>
  <!-- 1:准备一个loading类,通过为元素定位,设置宽高100%,实现蒙层 -->
  <div class="box" v-loading="isLoading">
    <ul>
      <!-- v-for循环展示 -->
      <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">
          <!-- 通过 v-bind的简写绑定属性,简写成为: -->
          <img :src="item.img" alt="">
        </div>
      </li>
    </ul>
  </div>
</template>

<script>

import axios from 'axios'

export default {
  name: "MyLoading",
  data() {
    return {
      list: [],
      isLoading: true // 是否显示加载中,初始值是显示加载中
    }
  },

  // created方法,在vue实例创建完毕之后执行,一般用于请求数据
  // async 关键字 表示异步请求
  // await关键字表示等待异步请求结束,再执行下面的代码
  async created() {
    const res = await axios.get("http://hmajax.itheima.net/api/news");
    // 为了模拟延迟,这里设置休眠2s
    setTimeout(() => {
      this.list = res.data.data;
      this.isLoading = false; // 渲染出数据来了,isLoading置为false, 此时会触发自定义指令的update钩子函数
    }, 2000)
  },

  // 自定义指令,用于实现加载中效果 -> inserted(初始化) update(更新时候的处理)
  directives: {
    loading: {
      inserted(el, binding) {
        // binding.value -> 就是绑定的值(isLoading)
        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 scoped>
/* 加载中样式 - 蒙层 */
/* 1:准备一个loading类,通过为元素定位,设置宽高100%,实现蒙层 */
.loading:before {
  content: "";
  position: absolute; /* 设置绝对定位 */
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: #fff url("../assets/loading.gif") no-repeat center;
}
.box {
  width: 800px; /* 宽度 */
  min-height: 500px; /* 最小高度,没有内容的时候的高度 */
  border: 3px solid orange; /* 边框设置 - 3像素 实线 橘色 */
  border-radius: 5px; /* 圆角 */
  position: relative; /* 设置相对定位,方便后续的绝对定位 */
}
.news {
  display: flex; /* 设置弹性布局 */
  height: 120px;
  width: 600px;
  margin: 0 auto; /* 设置居中 */
  padding: 20px 0; /* 内边距 */
  cursor: pointer; /* 设置鼠标样式 */
}
.news .left {
  flex: 1; /* 设置弹性布局为1份 */
  display: flex;
  flex-direction: column; /* 设置弹性布局为垂直布局 */
  justify-content: space-between; /* 设置弹性布局为垂直居中 */
  padding-right: 10px; /* 设置右边距 */
}
... /* 其他样式 */
</style>

在这里插入图片描述

二:插槽

1:默认插槽

在这里插入图片描述

在这里插入图片描述

<template>
  <div class="dialog">
    <div class="dialog-header">
      <h3>友情提示</h3>
      <span class="close">×</span>
    </div>

    <div class="dialog-body">
      <!-- 在可定制的部分使用slot插槽占位 -->
      <slot></slot>
    </div>

    <div class="dialog-footer">
      <button class="btn-primary">确定</button>
      <button class="btn-default">取消</button>
    </div>
  </div>
</template>

<script>
export default {
  name: 'MyDialog',
  data() {
    return {

    }
  },
}
</script>

<style lang="scss" scoped>

</style>
<template>
  <div class="App">
    <!-- 在使用组件的时候,写入自定义的内容,将会填充slot -->
    <MyDialog>我是可定制的内容,我将填充组件中的slot部分</MyDialog>
    <MyDialog>我也是可定制的内容,我将填充组件中的slot部分</MyDialog>
  </div>
</template>

<script>
// 1.引入组件
import MyDialog from "@/components/MyDialog.vue";
export default {
  name: 'App',
  components: {
    MyDialog
  }
}
</script>

<style lang="less" scoped>
/* 设置样式 */
.App {
  width: 600px;
  height: 700px;
  background-color: #87ceeb;
  margin: 0 auto; /* 居中 */
  padding: 20px; /* 边距 */
}
</style>

2:后备内容(默认值)

在这里插入图片描述

3:具名插槽

在slot中通过name区分名称,然后再使用端通过template + v-slot:名字分发对应的标签

在这里插入图片描述

4:作用域插槽(插槽传值)

在这里插入图片描述

  1. 给slot标签,通过添加属性的方式进行传值
<slot :id="item.id" msg="我是一个消息"></slot>
  1. 所有添加的属性,都会被收集到一个对象中
{
    id: 3
    msg: "我是一个消息"
}

3:在使用端,template中通过#插槽名字="obj"接收,默认的插槽名字是default

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值