百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 博客教程 > 正文

Vue3 封装第三方组件(一)做一个合格的传声筒

connygpt 2024-09-12 13:52 16 浏览

各种UI库的功能都是非常强大的,尤其对于我这种不会 css 的人来说,就更是帮了大忙了。

只是嘛,如果再封装一下的话,那么用起来就会更方便了。

那么如何封装呢?

封装三要素 —— 属性、插槽、事件、方法

可以封装,但是原生UI库提供的强大功能不能给封装没了吧,吃了回扣可是不好滴。
那么如何做到不遗漏呢?先做一个合格的传声筒。

传递属性

先看看 el-input 提供的属性:

太长了,这里只截了一半。
这么多的属性,如果一个一个都弄到 props 里面,然后再一个一个绑定上去,这就太麻烦了。

我们可以分成两部分,重要的属性做到 props 里面,其他的可以放到 $attrs 里面。

定义一个简单的组件

模板

<template>
  <div>
    <el-input
      v-model="value" // 不能直接帮的属性
      v-bind="$attrs"  // 绑定其他属性。
    >
    </el-input> 
  </div>
</template>

代码

export default {
  name: 'test-text',
  inheritAttrs: false,
  props: {
    modelValue: [String, Number]
  },
  setup(props, ctx) {
    const value = debounceRef(props, ctx.emit)

    return {
      value
    }
  }
}

父组件的调用代码:
模板

<inputtext
    v-model="value"
    v-bind="attrs"
  >
  </inputtext>

代码

const value = ref('222')

const attrs = reactive({
  maxlength: 10,
  'show-word-limit': true,
  clearable: true
})

这里 modelValue 就是 props ,maxlength、show-word-limit、clearable 就变成了 $attrs 。

然后要看 el-input 是否是根元素,如果是跟元素的话,那么会自动绑定上,不需要我们手动写 v-bind="$attrs"

如果像上面的例子不是根元素的话,需要手动写 v-bind="$attrs"

inheritAttrs

这个是指定组件是否自动绑定 $attrs 。
默认是 true,会自动把 $attrs 绑定到根元素上面,不管根元素是啥。
这里设置为 false,那么$attrs 就不会自动绑定到 div 上面了。

插槽

这个稍微复杂一点,插槽本来就有一点绕,官网的介绍又比较含混。

我们可以找到 $slots 这个东东,但是官网的介绍(https://www.vue3js.cn/docs/zh/api/instance-properties.html#slots )却是 使用 h,这个就……

不过想要传递插槽,还是需要这个。

我们先看看 el-input 的插槽的使用。

  <el-input
    placeholder="请输入内容"
    v-model="input3"
    class="input-with-select"
  >
    <template #prepend>
      <el-select v-model="select" placeholder="请选择">
        <el-option label="餐厅名" value="1"></el-option>
        <el-option label="订单号" value="2"></el-option>
        <el-option label="用户电话" value="3"></el-option>
      </el-select>
    </template>
    <template #append>
      <el-button icon="el-icon-search"></el-button>
    </template>
  </el-input>

那么想要传递插槽的话,是不是可以这样?

   <!--传递插槽-->
    <template  v-slot:prepend> // 给递给el-input 的插槽
      <slot name="prepend"></slot> // 接收父组件传递进来的插槽
    </template> 

测试可以。

那么总不会一个一个写吧,这也太麻烦了。如果能够for就好了。

等等, for?那么我们是不是可以这样。

  <!--传递插槽-->
  <template 
    v-for="(item, key, index) in $slots"
      :key="index"
      v-slot:[key]
  >
      <slot :name="key"></slot>
  </template>  

测试可以。

完整代码

    <el-input
      ref="refInput"
      v-model="value"
      v-bind="$attrs"
    >
      <!--传递插槽-->
      <template 
        v-for="(item, key, index) in $slots"
        :key="index"
        v-slot:[key]
      >
        <slot :name="key"></slot>
      </template> 
    </el-input> 

传递事件

这个就简单了,啥都不用做,自动就传递出去了。el-input 是否是跟元素都可以。
测试一下:

 <inputtext
    ref="refInput"
    v-model="value"
    v-bind="props"
    @clear="clear"
    @my-change="myChange"
  >
  • clear 是 el-input 提供的事件,外部可以直接得到这个事件,组件内部不用做操作。
  • my-change 是自定义的事件。

方法

一直都忽略了,还有方法这个事,因为基本没用过。

使用方法嘛,就需要使用 ref,这个词 ref 非彼 ref,说不清了,还是写代码吧。

直接使用的方法

直接使用UI库组件的方法,比如 el-input 的 提供的 select:

<el-input
  ref="refInput" // 注意这里的 ref 
  v-model="value"
  v-bind="$attrs" >
</el-input> 

ref 的写法,不要加冒号。

const refInput = ref(null) // 先放一个null
onMounted(() => { // 然后在 onMounted 里面才能得到值。
  console.log('refinput', refInput) // 看看啥样。
  refInput.value.select() // 调用方法,文本框的内容会被选中
})

先定义一个 ref,然后交给模板里的 ref,好像有点绕,这里必须使用 ref,reactive是不行滴。

在渲染后才能生效,也就是说必须在 onMounted 里面才能得到值,我们看看打印结果:(太长只能截取一部分)

很长吧。

父组件里面怎么用方法

<inputtext
    ref="refInput"
    v-model="value">
</el-input> 
// 测试方法
const refInput = ref(null)

onMounted(() => {
  console.log('refinput', refInput)
  // refInput.value.$refs.refInput.select()
  refInput.value.refInput.select()
})

父组件里面的用法是一样的,只是需要再套一层,才能拿到自定义组件内部的UI库组件。

看看结构:

太长了,还在下面。

这个就比较近了。

话说为啥弄得这么多属性和方法事件呀?

父组件调用子组件内部的方法

上面那种方式,还可以让父组件调用子组件内部定义的方法,比如内部定义一个

   const setInput = () => {
      value.value = new Date()
    }

父组件可以这样调用

refInput.value.setInput()

总结

其实事件和方法,并没有封装,而是直接就可以使用的。
这是 element-plus 测试的结果,其他UI库没有测试。

插槽需要写一个 v-for 就可以实现传递,而且是通用的代码。
属性 就需要规划一下了,看设计要求,哪些放在 props里面,哪些放在attrs 里面。

相关推荐

自学Python,写一个挨打的游戏代码来初识While循环

自学Python的第11天。旋转~跳跃~,我~闭着眼!学完循环,沐浴着while的光芒,闲来无事和同事一起扯皮,我说:“编程语言好神奇,一个小小的循环,竟然在生活中也可以找到原理和例子”,同事也...

常用的 Python 工具与资源,你知道几个?

最近几年你会发现,越来越多的人开始学习Python,工欲善其事必先利其器,今天纬软小编就跟大家分享一些常用的Python工具与资源,记得收藏哦!不然下次就找不到我了。1、PycharmPychar...

一张思维导图概括Python的基本语法, 一周的学习成果都在里面了

一周总结不知不觉已经自学Python一周的时间了,这一周,从认识Python到安装Python,再到基本语法和基本数据类型,对于小白的我来说无比艰辛的,充满坎坷。最主要的是每天学习时间有限。只...

三日速成python?打工人,小心钱包,别当韭菜

随着人工智能的热度越来越高,许多非计算机专业的同学们也都纷纷投入到学习编程的道路上来。而Python,作为一种相对比较容易上手的语言,也越来越受欢迎。网络上各类网课层出不穷,各式广告令人眼花缭乱。某些...

Python自动化软件测试怎么学?路线和方法都在这里了

Python自动化测试是指使用Python编程语言和相关工具,对软件系统进行自动化测试的过程。学习Python自动化测试需要掌握以下技术:Python编程语言:学习Python自动化测试需要先掌握Py...

Python从放弃到入门:公众号历史文章爬取为例谈快速学习技能

这篇文章不谈江流所专研的营销与运营,而聊一聊技能学习之路,聊一聊Python这门最简单的编程语言该如何学习,我完成的第一个Python项目,将任意公众号的所有历史文章导出成PDF电子书。或许我这个Py...

【黑客必会】python学习计划

阅读Python文档从Python官方网站上下载并阅读Python最新版本的文档(中文版),这是学习Python的最好方式。对于每个新概念和想法,请尝试运行一些代码片段,并检查生成的输出。这将帮助您更...

公布了!2025CDA考试安排

CDA数据分析师报考流程数据分析师是指在不同行业中专门从事行业数据搜集、整理、分析依据数据作出行业研究评估的专业人员CDA证书分为1-3级,中英文双证就业面广,含金量高!!?报考条件:满18...

一文搞懂全排列、组合、子集问题(经典回溯递归)

原创公众号:【bigsai】头条号:程序员bigsai前言Hello,大家好,我是bigsai,longtimenosee!在刷题和面试过程中,我们经常遇到一些排列组合类的问题,而全排列、组合...

「西法带你学算法」一次搞定前缀和

我花了几天时间,从力扣中精选了五道相同思想的题目,来帮助大家解套,如果觉得文章对你有用,记得点赞分享,让我看到你的认可,有动力继续做下去。467.环绕字符串中唯一的子字符串[1](中等)795.区...

平均数的5种方法,你用过几种方法?

平均数,看似很简单的东西,其实里面包含着很多学问。今天,分享5种经常会用到的平均数方法。1.算术平均法用到最多的莫过于算术平均法,考试平均分、平均工资等等,都是用到这个。=AVERAGE(B2:B11...

【干货收藏】如何最简单、通俗地理解决策树分类算法?

决策树(Decisiontree)是基于已知各种情况(特征取值)的基础上,通过构建树型决策结构来进行分析的一种方式,是常用的有监督的分类算法。决策树算法是机器学习中的一种经典算法,它通过一系列的规则...

面试必备:回溯算法详解

我们刷leetcode的时候,经常会遇到回溯算法类型题目。回溯算法是五大基本算法之一,一般大厂也喜欢问。今天跟大家一起来学习回溯算法的套路,文章如果有不正确的地方,欢迎大家指出哈,感谢感谢~什么是回溯...

「机器学习」决策树——ID3、C4.5、CART(非常详细)

决策树是一个非常常见并且优秀的机器学习算法,它易于理解、可解释性强,其可作为分类算法,也可用于回归模型。本文将分三篇介绍决策树,第一篇介绍基本树(包括ID3、C4.5、CART),第二篇介绍Ran...

大话AI算法: 决策树

所谓的决策树算法,通俗的说就是建立一个树形的结构,通过这个结构去一层一层的筛选判断问题是否好坏的算法。比如判断一个西瓜是否好瓜,有20条西瓜的样本提供给你,让你根据这20条(通过机器学习)建立起...