【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

<think>首先,用户的问题是关于在Vue2自定义vant的van-picker组件的选项内容样式。参考了提供的引用,我需要基于这些信息构建一个结构清晰的回答。 关键引用: - 引用[1]:讨论了基于vant的van-picker实现自定义四层区域组件封装,涉及业务需求效果展示。 - 引用[2]:描述了picker组件的结构,包括picker_column的样式模板,比如flex:1, overflow:hidden, 以及使用translateY来滚动内容。 - 引用[3]:提到了Vue2自定义vant-select封装,给出了数据格式如columns1数组,包含labelvalue。 用户的问题:“我想查找在Vue2中对van-picker组件进行自定义选项内容样式的方法”。所以,我需要解释如何自定义选项的内容(如数据源)样式(如外观)。 系统指令- 所有行内数学表达式用$...$。 - 独立公式用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 保证回答真实可靠。 回答结构: 1. **介绍**:简要说明van-picker组件自定义需求。 2. **自定义选项内容**:解释如何定义数据源,如使用数组对象(labelvalue),基于引用[3]。 3. **自定义样式**:解释如何修改CSS样式,基于引用[2],比如修改列样式、滚动效果等。 4. **代码示例**:提供一个简单的Vue2组件示例,展示如何自定义内容样式。 5. **生成相关问题**:在末尾添加相关的问题列表。 确保引用: - 在解释数据格式时,引用引用[3]。 - 在解释样式时,引用引用[2]。 由于引用[1]是关于多层区域封装的,但用户的问题焦点在自定义选项内容样式,所以我应该优先参考引用[2][3]。 步骤: - **步骤1:导入设置数据**:使用columns属性传递数据。 - **步骤2自定义选项内容**:通过插槽或属性定义显示的文本。 - **步骤3:自定义样式**:覆盖vant的默认样式或使用自定义类。 代码示例: - 创建一个Vue组件,使用van-picker。 - 展示数据定义:如const columns = [{ label: '苹果', value: '01' }, ...]。 - 展示样式覆盖:在<style scoped>中修改相关类。 生成相关问题: - 基于主题,生成2-3个相关问题,如: 1. 如何实现van-picker的多列联动? 2.Vue2中如何优化van-picker的性能? 3. van-picker的自定义插槽用法有哪些? 最终回答以中文写成。 </think> ### Vue2中van-picker组件自定义选项内容样式的方法 在Vue2项目中,使用vant-ui的`<van-picker>`组件时,自定义选项内容样式是常见需求。下面我将逐步解释实现方法,基于vant的文档最佳实践。关键是通过**数据绑定**自定义选项内容,并通过**CSS覆盖**或**插槽**修改样式。以下是详细步骤: #### 1. **自定义选项内容** 选项内容通常通过`columns`属性传入一个数据数组,定义选项的显示文本(`label`)值(`value`)。每个选项是对象格式,支持动态数据绑定。 - **数据格式示例**: 使用数组定义选项,如引用[3]所示: ```javascript export default { data() { return { // 自定义选项数据:label为显示文本,value为选中值 columns: [ { label: '苹果', value: '01' }, { label: '香蕉', value: '02' }, { label: '橙子', value: '03' } ] } } } ``` - **在组件中使用**: 将`columns`绑定到`<van-picker>`的`columns`属性: ```vue <template> <van-picker :columns="columns" @change="onChange" /> </template> ``` 此方法允许动态更新选项内容,例如从API加载数据[^3]。 #### 2. **自定义选项样式** 样式自定义涉及修改选项的布局、字体、颜色等。vant的picker组件由多个`picker-column`组成(引用[2]),每个列有固定类名,可通过CSS覆盖或作用域样式(scoped CSS)实现: - **关键CSS类**: - `.van-picker-column`:控制单列容器(flex布局)。 - `.van-picker-column__item`:控制单个选项项(居中显示)。 - `.van-picker-column__wrapper`:控制滚动容器(使用translateY实现滚动)。 - **样式覆盖示例**: 在Vue组件的`<style>`块中,覆盖默认样式: ```vue <style scoped> /* 修改选项容器:调整宽度背景 */ .van-picker-column { flex: 1; background-color: #f5f7fa; /* 自定义背景色 */ } /* 修改单个选项:字体、边距悬停效果 */ .van-picker-column__item { font-size: 16px; /* 增大字体 */ padding: 12px 0; /* 增加垂直边距 */ color: #333; /* 文本颜色 */ } .van-picker-column__item:hover { background-color: #e1f0ff; /* 悬停效果 */ } /* 修改滚动容器:平滑滚动动画 */ .van-picker-column__wrapper { transition-timing-function: cubic-bezier(0.23, 1, 0.68, 1); /* 平滑动画曲线 */ } </style> ``` 此方法基于picker的内部结构(引用[2]),确保样式生效[^2]。 #### 3. **完整组件示例** 以下是一个Vue2组件示例,结合数据绑定样式自定义: ```vue <template> <div> <van-picker :columns="columns" :item-height="44" <!-- 自定义选项高度 --> @change="handlePickerChange" /> </div> </template> <script> export default { data() { return { columns: [ { label: '苹果', value: '01' }, { label: '香蕉', value: '02' }, { label: '橙子', value: '03' } ] } }, methods: { handlePickerChange(picker, value, index) { console.log('选中值:', value); } } } </script> <style scoped> .van-picker { border-radius: 8px; /* 圆角边框 */ } .van-picker-column__item { font-size: 16px; font-weight: bold; /* 加粗文本 */ } </style> ``` #### 注意事项 - **数据动态更新**:如果选项数据来自API,使用`this.columns = newData`触发响应式更新。 - **样式作用域**:添加`scoped`属性避免全局样式污染。 - **性能优化**:对于多列picker(如4层区域选择),确保数据量不过大,否则影响滚动流畅度(引用[1])。 - **兼容性**:在Vue2中,vant 2.x版本兼容良好;升级到Vue3时需使用vant 3.x。 ### 相关问题 1. 如何在van-picker中实现多列联动(如省市区选择)? 2.Vue2项目中,如何优化van-picker的滚动性能? 3. van-picker支持哪些自定义插槽(slots)来增强灵活性?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值