iis服务器助手广告广告
返回顶部
首页 > 资讯 > 前端开发 > 其他 >Vue3复用组件怎么使用
  • 950
分享到

Vue3复用组件怎么使用

Vue3 2023-05-20 19:05:30 950人浏览 泡泡鱼
摘要

我们看到,createReusableTemplate 返回了一个 Tuple,即 define 和 reuse 的组件对,然后,通过上面的例子就可以在单文件里面复用多处代码了。还有,实际上还可以通过对象解构的方式返回一个 define 和

我们看到,createReusableTemplate 返回了一个 Tuple,即 define 和 reuse 的组件对,然后,通过上面的例子就可以在单文件里面复用多处代码了。

还有,实际上还可以通过对象解构的方式返回一个 define 和 reuse(很神奇吧,这篇文章就不展开了,有兴趣下次再分享下),用法同上,例子如下

<script setup lang="ts">
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()
const TemplateBar = createReusableTemplate<{ msg: string }>()
const [DefineBiz, ReuseBiz] = createReusableTemplate<{ msg: string }>()
</script>
<template>
  <DefineFoo v-slot="{ msg }">
    <div>Foo: {{ msg }}</div>
  </DefineFoo>
  <ReuseFoo msg="world" />
  <!-- 看这里 -->
  <TemplateBar.define v-slot="{ msg }">
    <div>Bar: {{ msg }}</div>
  </TemplateBar.define>
  <TemplateBar.reuse msg="world" />
  <!-- Slots -->
  <DefineBiz v-slot="{ msg, $slots }">
    <div>Biz: {{ msg }}</div>
    <component :is="$slots.default" />
  </DefineBiz>
  <ReuseBiz msg="reuse 1">
    <div>This is a slot from Reuse</div>
  </ReuseBiz>
  <ReuseBiz msg="reuse 2">
    <div>This is another one</div>
  </ReuseBiz>
</template>

Vue3复用组件怎么使用

真是神奇,那咋实现呢

上面我们介绍了用法,相信应该没人看不懂,上手成本确实为 0,那接下来我们一起看看是如何实现的。

我们知道,vue3 定义组件除了通过 script setup 的方式之外, 还可以通过defineComponent的方式

const Demo = defineComponent({
  props: {
    ...,
  },
  setup(props, { attrs, slots }) {
    return () => {
      ...
    }
  }
})

然后我们观察下是如何定义模板的

<DefineFoo v-slot="{ msg }">
    <div>Foo: {{ msg }}</div>
</DefineFoo>

好像似曾相识?v-slot?,诶,卧槽,这不是插槽吗!还有,模板代码看起来就是放在默认插槽的。

好,我们接下来看下如何实现 Define 的功能。

实现 Define

我们刚才说,模板是定义在默认插槽里面,那我们可以定义个局部变量 render,之后当在 template 里面使用 Define 时会进入 setup,这时候拿到 slot.default,放在 render 上不就好?,代码如下

let render: Slot | undefined
const Define = defineComponent({
  setup(props, { slots, }) {
    return () => {
      
      render = slots.default
    }
  }
})

对的,就是这么简单,对于 Define 来说,核心代码就是这两三行而已

实现 Reuse

上面拿到 render function 了,那我们在使用 Reuse 的地方,将所得到的 v-slot、attrs 等传给 render 不就好?

同样,当我们在 template 使用 Reuse 的时候,就会进入 setup,然后将得到的参数都传给 render,并 return render 的结果即可

  const reuse = defineComponent({
    setup(_, { attrs, slots }) {
      return () => {
        
        if (!render && process.env.node_ENV !== 'production')
          throw new Error(`[Vue-reuse-template] Failed to find the definition of template${name ? ` "${name}"` : ''}`)
        return render?.({ ...attrs, $slots: slots })
      }
    },
  })

上面的 attrs 也就是你在 Reuse 上传的 prop 了

<ReuseFoo msg="msg1" />

而为啥还要传个$slots?

上面实际上有个例子,模板里面还可以通过动态组件<component :is="$slots.default" />的方式来拿到插槽的真正内容

<DefineBiz v-slot="{ msg, $slots }">
    <div>Biz: {{ msg }}</div>
    <component :is="$slots.default" />
</DefineBiz>
<ReuseBiz msg="reuse 1">
    <div>This is a slot from Reuse</div>
  </ReuseBiz>
<ReuseBiz msg="reuse 2">
  <div>This is another one</div>
</ReuseBiz>

Vue3复用组件怎么使用

当然,不只默认插槽啦,其他具名插槽都可以

<DefineBiz v-slot="{ msg, $slots }">
    <component :is="$slots.header" />
    <div>Biz: {{ msg }}</div>
    <component :is="$slots.default" />
  </DefineBiz>
  <ReuseBiz msg="reuse 1">
    <template #header>
      <div>我是 reuse1的header</div>
    </template>
    <div>This is a slot from Reuse</div>
  </ReuseBiz>
  <ReuseBiz msg="reuse 2">
    <template #header>
      <div>我是 reuse1的header</div>
    </template>
    <div>This is another one</div>
  </ReuseBiz>

Vue3复用组件怎么使用

具体怎么玩出花,你来定~

类型支持,提升开发体验

我们定义了模板,但模板接收什么参数,传入什么参数,你得告诉我对不对,如果没有类型的提示,那么开发体验会极其糟糕,不过,不用担心,大佬这些都考虑好了。

createReusableTemplate 支持泛型参数,也就是说你要复用的模板需要什么参数,只需要通过传入对应类型即可,比如你有个 msg,是 string 类型,那么用法如下

const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }>()

然后你就会发现,DefineFoo, ReuseFoo 都会对应的类型提示了

添加类型支持

我们上面说是用 defineComponent 得到 Define 和 Reuse,而 defineComponent 返回的类型就是 DefineComponent 呀

type DefineComponent<PropsOrPropOptions = {}, RawBindings = {}, ...>

假设模板参数类型为 Bindings 的话,那么对于 Reuse 来说,其既支持传参,也支持添加插槽内容,所以类型如下

type ReuseTemplateComponent<
  Bindings extends object,
  Slots extends Record<string, Slot | undefined>,
  
> = DefineComponent<Bindings> & {
 
  new(): { $slots: Slots }
}

而对于 Define 类型来说,我们知道其 v-slot 也有对应的类型,且能通过$slots 拿到插槽内容,所以类型如下

type DefineTemplateComponent<
 Bindings extends object,
 Slots extends Record<string, Slot | undefined>,
 Props = {},
> = DefineComponent<Props> & {
  new(): { $slots: { default(_: Bindings & { $slots: Slots }): any } }
}

小结一下

ok,相信我开头说的看懂只需要 1 分钟不到应该不是吹的,确实实现很简单,但功能又很好用,解决了无法在单文件复用代码的问题。

我们来小结一下:

  • 通过 Define 来将你所需要复用的代码包起来,通过 v-slot 拿到传过来的参数,同时支持渲染其他插槽内容

  • 通过 Reuse 来复用代码,通过传参渲染出不同的内容

  • 为了提升开发体验,加入泛型参数,所以 Define 和 Reuse 都有对应的参数类型提示

  • 要记住使用条件,Define 在上,Reuse 在下,且不允许只使用 Reuse,因为拿不到 render function,所以会报错

加个彩蛋吧

实际上多次调用 createReusableTemplate 得到相应的 DefineXXX、ReuseXXX 具有更好的语义化Vue3复用组件怎么使用

Vue3复用组件怎么使用

也就是说,我不想多次调用 createReusableTemplate 了,直接让 define 和 reuse 支持 name 参数(作为唯一的 template key),只要两者都有相同的 name,那就意味着它们是同一对

如何魔改

实际上也很简单,既然要支持 prop name来作为唯一的 template key,那 define 和 reuse 都添加 prop name 不就好?

  const define = defineComponent({
    props {
      name: String
    }
  })
  const reuse = defineComponent({
    props {
      name: String
    }
  })

然后之前不是有个 render 局部变量吗?因为现在要让一个 Define 支持通过 name 来区分不同的模板,那么我们判断到传入了 name,就映射对应的的 render 不就好?

这里我们通过 Map 的方式存储不同 name 对应的 render,然后 define setup 的时候存入对应 name 的 render,reuse setup 的时候通过 name 拿到对应的 render,当然如果没传入 name,默认值是 default,也就是跟没有魔改之前是一样的

const renderMap = new Map<string, Slot | undefined>()
const define = defineComponent({
    props: {
      
      name: String,
    },
    setup(props, { slots }) {
      return () => {
        const templateName: string = props.name || 'default'
        if (!renderMap.has(templateName)) {
          // render = slots.default
          renderMap.set(templateName, slots.default)
        }
      }
    },
  })
  const reuse = defineComponent({
    inheritAttrs: false,
    props: {
      name: String,
    },
    setup(props, { attrs, slots }) {
      return () => {
        const templateName: string = props.name || 'default'
        const render = renderMap.get(templateName)
        if (!render && process.env.NODE_ENV !== 'production')
          throw new Error(`[vue-reuse-template] Failed to find the definition of template${templateName}`)
        return render?.({ ...attrs, $slots: slots })
      }
    },
  })

以上就是Vue3复用组件怎么使用的详细内容,更多请关注编程网其它相关文章!

--结束END--

本文标题: Vue3复用组件怎么使用

本文链接: https://www.lsjlt.com/news/214763.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Vue3复用组件怎么使用
    我们看到,createReusableTemplate 返回了一个 Tuple,即 define 和 reuse 的组件对,然后,通过上面的例子就可以在单文件里面复用多处代码了。还有,实际上还可以通过对象解构的方式返回一个 define 和...
    99+
    2023-05-20
    Vue3
  • vue3 table组件怎么使用
    基础表格首先开发table组件之前,先想好要用什么样式的api,因为笔者在生产工作中用的都是element,所以前面几个组件风格和element类似,但是这次不打算用element的风格了,打算换一种,直接展示:我们期望用户这样使用:<...
    99+
    2023-05-14
    Vue3 table
  • vue3动态组件怎么使用
    这篇文章主要介绍“vue3动态组件怎么使用”,在日常操作中,相信很多人在vue3动态组件怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”vue3动态组件怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-07-06
  • Vue3之Teleport组件怎么使用
    Teleport 组件解决的问题版本:3.2.31如果要实现一个 “蒙层” 的功能,并且该 “蒙层” 可以遮挡页面上的所有元素,通常情况下我们会选择直接在 标签下渲染 “蒙层” 内容。如果在Vue.js 2 中实现这个功能,只能通过原生 D...
    99+
    2023-05-14
    Vue3 teleport
  • Vue3异步组件Suspense怎么使用
    今天小编给大家分享一下Vue3异步组件Suspense怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。Suspense...
    99+
    2023-07-06
  • Vue3怎么使用Vite打包组件库
    本文小编为大家详细介绍“Vue3怎么使用Vite打包组件库”,内容详细,步骤清晰,细节处理妥当,希望这篇“Vue3怎么使用Vite打包组件库”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。打包配置vite 专门提供...
    99+
    2023-07-05
  • vue3伸缩菜单组件怎么使用
    本篇内容介绍了“vue3伸缩菜单组件怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!效果图在components下面创建一个conta...
    99+
    2023-07-05
  • vue3异步组件怎么用
    这篇文章给大家分享的是有关vue3异步组件怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。 在vue3中,异步组件可以减少打包的结果,会将异步组件...
    99+
    2024-04-02
  • Vue3中的异步组件defineAsyncComponentAPI怎么使用
    传递工厂函数作为参数defineAsyncComponent方法接收一个工厂函数是它的基本用法,这个工厂函数必须返回一个Promise,Promise的resolve应该返回一个组件。我们这里以Vue Cli创建的项目为例,这里我稍微做了一...
    99+
    2023-05-21
    Vue3
  • vue3 table组件如何使用
    今天小编给大家分享一下vue3 table组件如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。基础表格首先开发tabl...
    99+
    2023-07-06
  • Vue3 Element Plus el-form表单组件怎么使用
    在 Element Plus 中,el-form 是一个表单组件,用于创建表单以便用户填写和提交数据。它提供了许多内置的验证规则和验证方法,使表单验证更加容易。使用 el-form 组件,您可以将表单控件组织在一起,并对表单进行验证,以确保...
    99+
    2023-05-14
    Vue3 element plus el-form
  • vue3动态组件使用详解
    目录vue2vue3markRow:标记一个对象,使其不能成为一个响应式对象。toRaw:将响应式对象(由 reactive定义的响应式)转换为普通对象。shallowRef:只处理...
    99+
    2023-02-27
    vue3中动态组件 vue3动态加载组件 vue3动态添加组件
  • Vue3 table表格组件的使用
    目录一、Ant Design Vue1、官网地址2、怎么使用3、将电子书表格进行展示二、总结一、Ant Design Vue 在大量数据需要展示时,我们一般都会以报表的形式展现,按照...
    99+
    2024-04-02
  • Vue3之Teleport组件如何使用
    这篇文章主要介绍了Vue3之Teleport组件如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue3之Teleport组件如何使用文章都会有所收获,下面我们一起来看看吧。Teleport 组件解决的问...
    99+
    2023-07-06
  • vue3动态加载组件及动态引入组件怎么使用
    本篇内容介绍了“vue3动态加载组件及动态引入组件怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1.问题在做一个用vite构建的vu...
    99+
    2023-07-05
  • vue3动态组件如何使用
    这篇“vue3动态组件如何使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue3动态组件如何使用”文章吧。问题:为什么v...
    99+
    2023-07-05
  • vue3无限滚动组件怎么用
    这篇“vue3无限滚动组件怎么用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“vue3无限滚动组件怎么用”文章吧。什么是无限...
    99+
    2023-06-29
  • Vue3全局组件通信之provide/inject怎么使用
    本篇内容介绍了“Vue3全局组件通信之provide/inject怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1、前言顾名思义,爷...
    99+
    2023-07-06
  • Vue3异步组件suspense使用详解
    目录结合elementui 使用 vue在解析我们的组件时, 是通过打包成一个 js 文件,当我们的一个组件 引入过多子组件是,页面的首屏加载时间 由最后一个组件决定 优化的一种方式...
    99+
    2022-12-28
    Vue3 异步组件 suspense Vue3 组件 suspense
  • Vue3异步组件Suspense如何使用
    这篇文章主要介绍了Vue3异步组件Suspense如何使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Vue3异步组件Suspense如何使用文章都会有所收获,下面我们一起来看看吧。Suspense组件官网中...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作