二次封装的方法

二次封装

我们开发中经常需要封装一些第三方组件,那么父组件应该怎么传值,怎么调用封装好的组件原有的属性、插槽、方法,一个个调用虽然可行,但十分麻烦,我们一起来看更简便的方法。

二次封装组件,属性怎么传

attrs 主要接收不在 props 里定义,但父组件又传过来的属性,通过 v-bind=“$attrs”,可以将属性全部传给封装起来的组件(如下面例子中的 el-input ),而不需要一个一个传

// 父组件
<template>
  <div>
    <MyInput v-model="text" placeholder="请输入地址"></MyInput>
  </div>
</template>

<script setup>
import MyInput from './components/MyInput.vue';
import { ref } from 'vue';
const text = ref('123');
</script>
// MyInput 组件
<template>
  <div class="item">
    <el-input v-bind="$attrs"></el-input>
  </div>
</template>
<script setup>
import { onMounted, useAttrs } from 'vue';
const props = defineProps({
  // placeholder:{
  //   type:String
  // }
  // attrs包含的是不在props中的属性
  // 如果这里有placeholder,下面输出attrs就不会有这个placeholder
});
const attrs = useAttrs(); // 需要引入 vue 中的 useAttrs ,调用 useAttrs 获取 attrs
onMounted(() => {
  console.log(attrs); // 输出如下图
})
</script>

在这里插入图片描述

监听事件怎么实现

$listeners :包含了父作用域中(不含 .native 修饰器的)v-on 事件监听器,他可以通过 v-on=“listeners” 传入内部组件,监听内部组件的所有事件.

<template>
  <div>
    <MyInput
      v-model="text"
      placeholder="请输入地址"
      ref="focusRef"
      @input="inputNum"
    >
      <template #prepend="{}">
        <el-select v-model="select" placeholder="Select" style="width: 115px">
          <el-option label="A" value="1" />
          <el-option label="B" value="2" />
          <el-option label="C" value="3" />
        </el-select>
      </template>
      <template #append>
        <el-button :icon="Search" />
      </template>
    </MyInput>
  </div>
</template>
<script setup>
import MyInput from "./components/MyInput.vue";
import { onMounted, ref } from "vue";
import { Search } from "@element-plus/icons-vue";
const text = ref("123");
const select = ref("");
const focusRef = ref();
onMounted(() => {
  focusRef.value.focus();
});
const inputNum = (val) => { // 被监听事件触发时调用的方法
  console.log("输出:" + val);
};
</script>

// 子组件
<template>
  <div class="item">
    <el-input v-bind="$attrs" v-on="$listeners" ref="inp">
      <template v-for="(value, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData || {}"></slot>
      </template>
    </el-input>
  </div>
</template>
<script setup>
import { onMounted, useSlots, useAttrs, nextTick, ref } from "vue";

const attrs = useAttrs();
const slots = useSlots();
const inp = ref();
onMounted(() => {
  console.log(attrs);
  console.log(slots);

  console.log(inp.value);
});
defineExpose(
  new Proxy(
    {},
    {
      // 使用 Proxy 代理暴露出去
      get(_target, prop) {
        return inp.value?.[prop];
      },
      has(_target, prop) {
        return prop in inp.value;
      },
    }
  )
);
</script>

插槽怎么使用

二次封装组件时经常需要往原组件的插槽中传递内容,这时要让原始组件知道我们使用了哪些插槽,可以使用 $slots

$slots 是一个表示父组件所传入[插槽]的对象,我们可以在子组件中通过 $slots 获取到父组件传过来所有插槽名,接下来子组件遍历 $slots 动态渲染插槽即可

// 父组件
<template>
  <div>
    <MyInput v-model="text" placeholder="请输入地址">
      <template #prepend="{}">
        <el-select v-model="select" placeholder="Select" style="width: 115px">
          <el-option label="A" value="1" />
          <el-option label="B" value="2" />
          <el-option label="C" value="3" />
        </el-select>
      </template>
      <template #append>
        <el-button :icon="Search" />
      </template>
    </MyInput>
  </div>
</template>
<script setup>
import MyInput from './components/MyInput.vue';
import { ref } from 'vue';
import { Search } from '@element-plus/icons-vue'
const text = ref('123');
const select = ref('')
</script>

// 也可以往插槽传值 slotData
<template>
  <div class="item">
    <el-input v-bind="$attrs">
      <template v-for="(value,name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData || {}"></slot>
      </template>
    </el-input>
  </div>
</template>
<script setup>
import { onMounted, useSlots, useAttrs } from 'vue';

const attrs = useAttrs();
const slots = useSlots() // 引入 useSlots
onMounted(() => {
  console.log(attrs);
  console.log(slots); // 输出如下图
})
</script>

在这里插入图片描述

父组件的 ref 怎么调用目标组件内部方法

我们要想通过父组件的 ref 调用到子组件内部方法(如 el-input 的 focus 方法)可以怎么做?其实可以通过 ref 链式调用,比如 focusRef.value.inp.value.focus(),但代码的可读性差

更好的方法是将所有方法暴露出去供父组件调用,可以利用 Proxy 对象来创建一个代理,并通过 defineExpose 将这个代理暴露给父组件。这个代理的目的是拦截对特定属性的访问,并将这些访问重定向到 inp.value(即 el-input 的引用)上,这样,父组件就可以通过组件的 ref 访问到 el-input 实例的属性

// 父组件
<template>
  <div>
    <MyInput v-model="text" placeholder="请输入地址" ref="focusRef">
      <template #prepend="{}">
        <el-select v-model="select" placeholder="Select" style="width: 115px">
          <el-option label="A" value="1" />
          <el-option label="B" value="2" />
          <el-option label="C" value="3" />
        </el-select>
      </template>
      <template #append>
        <el-button :icon="Search" />
      </template>
    </MyInput>
  </div>
</template>
<script setup>
import MyInput from "./components/MyInput.vue";
import { onMounted, ref } from "vue";
import { Search } from "@element-plus/icons-vue";
const text = ref("123");
const select = ref("");
const focusRef = ref();
onMounted(() => {
  focusRef.value.focus();
});
</script>

// 子组件
<template>
  <div class="item">
    <el-input v-bind="$attrs" ref="inp">
      <template v-for="(value, name) in $slots" #[name]="slotData">
        <slot :name="name" v-bind="slotData || {}"></slot>
      </template>
    </el-input>
  </div>
</template>
<script setup>
import { onMounted, useSlots, useAttrs, nextTick, ref } from "vue";

const attrs = useAttrs();
const slots = useSlots();
const inp = ref();
onMounted(() => {
  console.log(attrs);
  console.log(slots);

  console.log(inp.value); // 这里输出如下图
});
defineExpose( // 使用 Proxy 代理暴露出去
  new Proxy(
    {},
    {
      get(_target, prop) {
        return inp.value?.[prop];
      },
      has(_target, prop) {
        return prop in inp.value;
      },
    }
  )
);
</script>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

整体效果如图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/961543.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机组成原理(2)王道学习笔记

数据的表示和运算 提问&#xff1a;1.数据如何在计算机中表示&#xff1f; 2.运算器如何实现数据的算术、逻辑运算&#xff1f; 十进制计数法 古印度人发明了阿拉伯数字&#xff1a;0&#xff0c;1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6&#…

npm启动前端项目时报错(vue) error:0308010C:digital envelope routines::unsupported

vue 启动项目时&#xff0c;npm run serve 报下面的错&#xff1a; error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:67:19) at Object.createHash (node:crypto:133:10) at FSReqCallback.readFileAfterClose [as on…

「 机器人 」仿生扑翼飞行器中的“被动旋转机制”概述

前言 在仿生扑翼飞行器的机翼设计中,模仿昆虫翼的被动旋转机制是一项关键技术。其核心思想在于:机翼旋转角度(攻角)并非完全通过主动伺服来控制,而是利用空气动力和惯性力的作用,自然地实现被动调节。以下对这种设计的背景、原理与优势进行详细说明。 1. 背景:昆虫的被动…

防御保护第一次实验:安全策略配置

一、实验拓扑 二、实验要求 三、需求分析 1.创建两个vlan 2.在ENSP中配置基于时间的ACL实现对于办公区PC访问OA Server的时间限制&#xff08;工作日早8到晚6&#xff09;。 3.通过配置基于MAC地址的ACL来实现对于生产区PC访问Web Server的限制&#xff08;除PC3外不能访问&am…

[权限提升] Windows 提权 — 系统内核溢出漏洞提权

关注这个框架的其他相关笔记&#xff1a;[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01&#xff1a;系统内核溢出漏洞提权介绍 注意&#xff1a;提权很容易让电脑蓝屏&#xff0c;所以如果是测试的话&#xff0c;提权前最好做好系统备份。 溢出漏洞就像是往杯子里装水 —— 如…

Dest1ny漏洞库:用友 U8 Cloud ReleaseRepMngAction SQL 注入漏洞(CNVD-2024-33023)

大家好&#xff0c;今天是Dest1ny漏洞库的专题&#xff01;&#xff01; 会时不时发送新的漏洞资讯&#xff01;&#xff01; 大家多多关注&#xff0c;多多点赞&#xff01;&#xff01;&#xff01; 0x01 产品简介 用友U8 Cloud是用友推出的新一代云ERP&#xff0c;主要聚…

在线课堂小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

【Linux权限】—— 于虚拟殿堂,轻拨密钥启华章

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…

Qt Designer and Python: Build Your GUI

1.install pyside6 2.pyside6-designer.exe 发送到桌面快捷方式 在Python安装的所在 Scripts 文件夹下找到此文件。如C:\Program Files\Python312\Scripts 3. 打开pyside6-designer 设计UI 4.保存为simple.ui 文件&#xff0c;再转成py文件 用代码执行 pyside6-uic.exe simpl…

【Rust自学】15.7. 循环引用导致内存泄漏

说句题外话&#xff0c;这篇文章真心很难&#xff0c;有看不懂可以在评论区问&#xff0c;我会尽快作答的。 喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω…

[免费]基于Python的Django博客系统【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的基于Python的Django博客系统&#xff0c;分享下哈。 项目视频演示 【免费】基于Python的Django博客系统 Python毕业设计_哔哩哔哩_bilibili 项目介绍 随着互联网技术的飞速发展&#xff0c;信息的传播与…

乐优商城项目总结

文章目录 项目简介微服务集群1.enreka注册中心2. zuul网关3. 公共工具类4. 商品微服务5. 文件上传微服务6. 搜索微服务7. 页面静态化微服务8. 用户微服务9. 短信微服务10. 认证微服务11. 购物车微服务12. 订单微服务项目最大的收获项目遇到的问题 项目简介 乐优商城是一个全品…

基于django的智能停车场车辆管理深度学习车牌识别系统

完整源码项目包获取→点击文章末尾名片&#xff01;

【开源免费】基于Vue和SpringBoot的在线文档管理系统(附论文)

本文项目编号 T 038 &#xff0c;文末自助获取源码 \color{red}{T038&#xff0c;文末自助获取源码} T038&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

双层Git管理项目,github托管显示正常

双层Git管理项目&#xff0c;github托管显示正常 背景 在写React项目时&#xff0c;使用Next.js,该项目默认由git托管。但是我有在项目代码外层记笔记的习惯&#xff0c;我就在外层使用了git托管。 目录如下 code 层内也有.git 文件&#xff0c;对其托管。 我没太在意&…

54.数字翻译成字符串的可能性|Marscode AI刷题

1.题目 问题描述 小M获得了一个任务&#xff0c;需要将数字翻译成字符串。翻译规则是&#xff1a;0对应"a"&#xff0c;1对应"b"&#xff0c;依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的…

基于Langchain-Chatchat + ChatGLM 本地部署知识库

一、相关环境 参考链接: Github:https://github.com/chatchat-space/Langchain-Chatchat Langchain-chatchat版本&#xff1a;v0.3.1 安装环境&#xff1a;Ubuntu&#xff1a;22.04&#xff0c;CUDA&#xff1a;12.1 二、搭建过程 2.1 环境配置 2.1.1 创建chatchat虚拟环…

Hive:日志,hql运行方式,Array,行列转换

日志 可以在终端通过 find / | grep hive-log4j2 命令查找Hive的日志配置文件 这些文件用于配置Hive的日志系统。它们不属于系统日志也不属于Job日志&#xff0c;而是用于配置Hive如何记录系统日志和Job日志, 可以通过hive-log4j2 查找日志的位置 HQL的3种运行方式 第1种就是l…

护眼好帮手:Windows显示器调节工具

在长时间使用电脑的过程中&#xff0c;显示器的亮度和色温对眼睛的舒适度有着重要影响。传统的显示器调节方式不仅操作繁琐&#xff0c;而且在低亮度下容易导致色彩失真。因此&#xff0c;今天我想为大家介绍一款适用于Windows系统的护眼工具&#xff0c;它可以帮助你轻松调节显…

简要介绍C语言和c++的共有变量,以及c++特有的变量

在C语言和C中&#xff0c;变量是用来存储数据的内存位置&#xff0c;它们的使用方式和特性在两种语言中既有相似之处&#xff0c;也有不同之处。以下分别介绍C语言和C的共有变量以及C特有的变量。 C语言和C的共有变量 C语言和C都支持以下类型的变量&#xff0c;它们在语法和基…