1.前置知识

  • h函数
  • 动态组件component

h函数

  1. h函数通常在Vue的render函数内部使用,用于创建组件的虚拟DOM节点。它接受三个参数
  2. 第一个参数可以是标签名(div)或者是一个组件对象
  3. 第二个参数是可选对象,用于定义属性、事件监听等
  4. 第三个参数分两种情况。当第一个参数是标签时该值子节点(可以是一个字符串、数组),当第一个参数是组件时该值是该组件对应的插槽。
<script setup lang="ts">
import {ElDialog} from 'element-plus'
</script>
<template>
// 第一个参数是一个标签
  <component :is="h('div', {onClick: () => {console.log('按钮被点击了')}}, [h('button', {}, '按钮')])"></component>
// 第一个参数是一个组件
  <component :is="h(ElDialog, {...$attrs,onClick: () => {console.log('按钮被点击了')}}, $slots)"></component>

<template>

<style></style>

component

  1. 基于is属性来动态渲染组件
  2. <script setup lang="ts">
    import Test from '@/component/Test/index.vue'
    import Test2 from '@/component/Test2/index.vue'
    const comName=shallowRef<any>(Test)
    // 可进行动态切换
    setTimeout(()={
      comName.value=Test2
    },2000)
    </script>
    <template>
        <component :is="comName"></component>
    <template>
    
    <style></style>

完整代码

以封装el-dialog为例:

<script lang='ts' setup>
import { ElDialog, ElButton } from 'element-plus'
import { h } from 'vue'
import type { ComponentInstance } from 'vue'

const dialogVisible = defineModel({ type: Boolean, default: false })
const emits = defineEmits(['confirm', 'close'])
const confirm = () => {
  emits('confirm')
}

const instance = getCurrentInstance()

const close = () => {
  emits('close')
}
// 组件挂在的时候会执行此方法,暴露方法给父组件
function dialogRef(exposed: any) {
  // defineProps原理就是将暴露的属性挂载到当前组件实例的exposed属性上
  instance!.exposed = exposed
}

// 给父组件使用时添加类型提示,支持在vscode、cursor中使用
defineExpose({} as ComponentInstance<typeof ElDialog>)

</script>
<template>
  <component :is="h(ElDialog,
    {
      ...$attrs,
      modelValue: dialogVisible,
      ref: dialogRef,
      top: '5%',
      onClose: close,
    },
    {
      ...$slots,
      default: () => $slots.default?.(),
      footer: () => $slots.footer?.() || h('div', { class: 'dialog-footer' }, [
        h(ElButton, { onClick: () => dialogVisible = false }, () => '关闭'),
        h(ElButton, { type: 'primary', onClick: confirm}, () => '确定')
      ])
    })"></component>
</template>
<style></style>

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐