【Vue3入门】自定义指令与插槽详解

🚀 欢迎来到我的CSDN博客:Optimistic _ chen

一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏 内容特色 适合人群
🔥C语言从入门到精通 系统讲解基础语法、指针、内存管理、项目实战 零基础新手、考研党、复习
🔥Java基础语法 系统解释了基础语法、类与对象、继承 Java初学者
🔥Java核心技术 面向对象、集合框架、多线程、网络编程、新特性解析 有一定语法基础的开发者
🔥Java EE 进阶实战 Servlet、JSP、SpringBoot、MyBatis、项目案例拆解 想快速入门Java Web开发的同学
🔥Java数据结构与算法 图解数据结构、LeetCode刷题解析、大厂面试算法题 面试备战、算法爱好者、计算机专业学生
🔥Redis系列 从数据类型到核心特性解析 项目必备

🚀我的承诺:

✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

文章目录

自定义指令

【Vue入门】Vue指令超全总结:从入门到实战,看这一篇就够了这篇博客详细介绍了Vue常用的内置指令及其使用方法。然而在实际开发中,我们经常会遇到一些特殊需求,这时内置指令可能无法满足。为此,Vue提供了自定义指令功能,让开发者能够直接操作DOM元素,特别适合需要底层DOM操作的场景。

作用:封装一段公共的DOM操作 代码,方便复用。

基础语法:

javascript 复制代码
//全局注册
// main.js
Vue.directive('指令名', {
  // 指令定义
  //元素挂载后(成为DOM的一部分),自动执行
  mounted(el){
     //el:指令所在的DOM元素
  }
})

使用的方法基本和内置指令相同,< p v-指令名> </p>
自定义指令的主要作用是为DOM元素添加响应式行为 。与内置指令类似,自定义指令必须在*元素挂载完成后才能生效,因为其mounted生命周期钩子需要操作已存在于DOM树中的元素。

javascript 复制代码
// Vue 3
Vue.directive('focus', {
  mounted(el) {
    el.focus()  // 页面加载后输入框自动获取焦点
  }
})

// 使用
<input v-focus placeholder="自动获取焦点" />

函数式指令

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

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

javascript 复制代码
//自定义指令:v-color动态绑定colorStr变量
<div v-color="colorStr">Some Text</div>

通过binding.value可以拿到指令值,指令值的修改会触发 updated钩子

javascript 复制代码
//语法
app.directive('color',{
     //挂载后自动触发
     mounted(el,binding){},
     //数据更新,每次都会执行
     updated(el,bingding){}
})

使用自定义指令

javascript 复制代码
app.directive('color', {
  // 元素挂载到DOM时执行
  mounted(el, binding) {
    el.style.color = binding.value  // 设置文字颜色
  },
  // 组件更新时执行
  updated(el, binding) {
    el.style.color = binding.value  // 更新文字颜色
  }
})

//简化:函数式指令,当mounted 和 updated 逻辑相同
app.direvtive('color',(el,binding)={
    //mounted和updated都会调用
    el.style.color=binding.value
})

插槽(重点)

定义:允许开发者对组件的结构⾃定义;本质就是⼀个占位,使⽤组件的时候传⼊指定的标签结构,从⽽做⼀个替换。

把一部分可复用的表情前结构抽离出去成为一个单独的JS文件,使用插槽对原生位置进行占位,让组件可以像 HTML 标签一样灵活地嵌套内容!

默认(匿名)插槽

作用:让组件的部分结构支持自定义(定制结构)

使用:

  1. 组件内需要定制的结构部分,使用slot标签占位(先占位)
  2. 使用组件时,把组件写成双标签,包裹需要展示的标签结构,从而替换掉slot(后传入)

本质上: 默认插槽是组件内某⼀部分结构不确定,需要自定义完成某些内容,每部分的内容各不相同,所以默认插槽可以自定义组件内的结构内容

父组件:多个礼物盒子,每个盒子内部的礼物都不同

javascript 复制代码
<script setup>

</script>

<!-- 父组件:给盒子里放不同的礼物 -->
<template>
  <div>
    <!-- 放一本书 -->
    <Child>
      <p>📖 《Vue入门到精通》</p>
    </Child>
    
    <!-- 放一个玩具 -->
    <Child>
      <p>🧸 毛绒熊</p>
    </Child>
    
    <!-- 什么都不放,盒子就是空的 -->
    <Child></Child>

  </div>
</template>

子组件:表示每个礼物的盒子

javascript 复制代码
<!-- 子组件:Child - 礼物盒子 -->
<template>
  <div class="gift-box">
    <h3>🎁 礼物盒子()</h3>
    <!-- 这个 slot 就是盒子的开口,放什么礼物由你决定 -->
    <slot></slot>
  </div>
</template>

当未向第三个Child标签传入内容时,系统默认会显示空白值。为了避免空白显示,建议预先在slot中定义默认内容。

javascript 复制代码
<!-- 子组件:GiftBox.vue - 礼物盒子 -->
<template>
  <div class="gift-box">
    <h3>🎁 礼物盒子()</h3>
    <!-- 这个 slot 就是盒子的开口,放什么礼物由你决定 -->
    <slot>这个礼物是空的</slot>
  </div>
</template>

具名插槽

作用:⼀个组件内有多处结构,需要外部传⼊标签,进⾏⾃定义

使用:

  1. 多个slot,使用name属性区分
    <slot name=" 名字 "> 默认内容 </slot>
  2. template+#插槽名,来分发相应的标签结构
    <template #名字> 要展⽰的内容</template>
javascript 复制代码
<template>
  <div>
    <h1>具名插槽</h1>
    <Child>
      <!-- 放左边口袋 -->
    <template #left>
      📱 手机
    </template>
    
    <!-- 放右边口袋 -->
    <template #right>
      🔑 钥匙
    </template>

    <!-- 放中间口袋(默认插槽) -->
    💳 公交卡
    </Child>
  </div>
</template>

<script setup>
import Child from './Child.vue';
</script>
javascript 复制代码
<template>
  <div class="child-container">
    <!-- 左边口袋 -->
    <div class="left-pocket">
      <slot name="left"></slot>
    </div>
    
    <!-- 右边口袋 -->
    <div class="right-pocket">
      <slot name="right"></slot>
    </div>
    
    <!-- 默认口袋(如果没指定放哪,就放这) -->
    <div class="center-pocket">
      <slot></slot>
    </div>
  </div>
</template>

作用域插槽

作用:带数据的插槽, 可以让组件功能更强⼤、更灵活、复⽤性更⾼。⽤slot占位的同时,还可以给slot 绑定数据,将来使⽤组件时,不仅可以传内容,还能使⽤slot带来的数据

使用:

  1. 在 template 中,通过#插槽名="变量"接收,如果没有给slot取名,默认是default
  2. 给相应的slot标签添加自定义属性

父组件:自己点菜(使用数据)

javascript 复制代码
<template>
  <div>
    <!-- 客人1:爱吃鱼 -->
    <Child>
      <template #default="{ fish, meat, vegetable }">
        <p>我要吃:{{ fish }}刺身,{{ meat }}烤着吃,{{ vegetable }}炒着吃</p>
      </template>
    </Child>
    
    <!-- 客人2:素食主义者 -->
    <Child>
      <template #default="{ vegetable }">
        <p>我只要:清炒{{ vegetable }}</p>
      </template>
    </Child>
    
    <!-- 客人3:随便,就用默认做法 -->
    <Child/>
  </div>
</template>

<script setup>
import Child from './Child.vue';
</script>

子组件:提供材料(数据)

javascript 复制代码
<!-- 子组件:Restaurant.vue -->
<template>
  <div class="restaurant">
    <h3>🍽️ 今日推荐</h3>
    
    <!-- ✅ 正确:把数据通过 slot 传递出去 -->
    <slot :fish="fish" :meat="meat" :vegetable="vegetable">
      <!-- 默认内容 -->
      <p>炒{{ fish }}、{{ meat }}、{{ vegetable }}</p>
    </slot>
  </div>
</template>

<script setup>
import { ref } from 'vue'

// 厨房准备的食材
const fish = ref('三文鱼')
const meat = ref('牛肉')
const vegetable = ref('西兰花')
</script>

作用域插槽的关键是子组件要通过 slot 的 attribute 传递数据父组件要通过 #default 接收数据。

完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~

想获取更多干货? 欢迎关注我的专栏 → optimistic_chen

📌 收藏本文,下次需要时不迷路!

我们下期再见!💫 持续更新中......


悄悄说:点击主页有更多精彩内容哦~ 😊

相关推荐
濮水大叔10 小时前
在大型 Vue 项目中,如何有效管理复杂的状态?“散装版” vs “套装版”
前端·vue.js·typescript
dddwjzx11 小时前
嵌入式Linux C应用编程入门——信号
linux·嵌入式
范什么特西11 小时前
网络代理问题
java·linux·服务器
laowang35712 小时前
依赖故障时,日志体系需要埋哪些关键节点才能快速定位是安装失败、解析失败还是运行时缺失?
前端·javascript·vue.js·webpack·node.js
姚不倒12 小时前
F5 SSL Profile 证书卸载深入篇
运维·网络协议·负载均衡·ssl·f5
utf8mb4安全女神12 小时前
【Redis数据库】哨兵集群/redis集群/安装配置/主从复制/数据持久化操作/数据结构/安全限制/PHP redis/
linux·服务器·数据结构·数据库·redis·缓存
智商偏低12 小时前
Windows Nginx 完整安装 + 启动教程
运维·nginx
Zk.Sun12 小时前
Linux设置触屏双击距离容差
linux·运维·数据库
Let's Chat Coding12 小时前
对称密钥认证:主机和设备共享同一把密钥
运维·服务器·网络
bukeyiwanshui13 小时前
20260622 安装配置ubuntu
linux·运维·ubuntu