如何封装更简单易用的命令式组件?

什么是组件?

在vue中,组件是可复用的Vue实例,用于封装和组合可重用的UI元素。组件可以包含模板、数据、方法和样式等,它们可以独立地管理自己的状态和行为,并可以在应用程序中多次使用。

一般组件的封装及使用

组件封装了自己的模板、数据和方法,可以隐藏实现细节,提供清晰的接口供其他组件使用。这样可以降低组件之间的耦合度,提高代码的可读性。

来看下一般的组件封装,以下用消息提示组件为例:

  1. 其中script部分,接收参数,向外暴露出方法。
ts 复制代码
<script setup lang="ts">
import type { PropType } from 'vue'

const emit = defineEmits(['cancel', 'confirm'])
interface IConfig {
  title: string
  message: string
  onConfirm?: Function
  onCancel?: Function
}
defineProps({
  config: {
    type: Object as PropType<IConfig>,
    default: () => {
      return {
        title: '',
        message: ''
      }
    }
  }
})
</script>
  1. html和css部分,使用参数并显示,以及样式的书写。
html 复制代码
<template>
  <view class="flex items-center justify-center absolute top-0 left-0 w-full h-full z-99999 bg-[#000000cc]">
    <view class="w-4/5 h-[400rpx] bg-white rounded-lg p-3">
      <view class="h-[260rpx] text-center">
        <view class="font-semibold">{{ config.title }}</view>
        <view>{{ config.message }}</view>
      </view>
      <view class="flex justify-between h-[100rpx]">
        <button class="w-1/2 mr-1" @click="emit('cancel')">取消</button>
        <button class="w-1/2 bg-[#2979ff] text-white" @click="emit('confirm')">确认</button>
      </view>
    </view>
  </view>
</template>

如何使用呢?

  1. 引入组件并使用。
ts 复制代码
import MessageBox from '@/components/MessageBox/index.vue'
html 复制代码
<template>
  <view class="flex items-center w-full h-[100vh]">
    <view class="w-4/5 my-2 mx-auto">
      <u-button @click="handleOpenMsg1" type="primary">一般组件</u-button>
    </view>
    <view class="w-4/5 my-2 mx-auto">
      <u-button @click="handleOpenMsg2" type="primary">命令式组件</u-button>
    </view>

    <MessageBox v-if="isShow" :config="config" @cancel="isShow = false" @confirm="handleConfirm" />
  </view>
</template>
  1. 定义变量及方法控制
ts 复制代码
// 显示及配置
const isShow = ref<boolean>(false)
const config = ref({
  title: '一般组件',
  message: '这是内容'
})

// 点击显示
const handleOpenMsg1 = () => {
  isShow.value = true
}

// 点击确认
const handleConfirm = () => {
  console.log('确认');
  isShow.value = false
}

总结:

通过以上我们可以看到,组件的封装并不麻烦,只需定义好模版接收参数等等就行了,但是一般在项目中组件通用性的居多,可能在一处使用还行,如果多处使用到同一种组件的使用,会不会发现组件在使用时较为复杂,需要引入组件,定义一大堆的变量和方法,给后续的使用维护增加了较大的负担。

如何改变?

像我们经常使用的elementUI这种框架一样,在使用消息提示框的时候直接这样写就很省事:

js 复制代码
import { ElMessage } from 'element-plus'

ElMessage({
    type: 'info',
    message: '消息内容',
})

如何封装这样简单易用的组件呢?

还是以上面的消息提示为例,组件部分可以不用改变,在组件同级目录建一个ts文件:

需引入 createApp 将组件挂载到body中,在确认按钮或取消按钮执行后调用组件的移除。

取消事件可以不必传,默认点击关闭弹窗。当然这只是以消息组件作为示例,其他的组件封装也要考虑全面,使用起来方便即可。

ts 复制代码
import MessageBox from './index.vue' // 引入组件
import { createApp } from 'vue'

interface IConfig {
  title: string
  message: string
  onConfirm?: Function
  onCancel?: Function
}

// 抛出使用方法
export default function showMsg(config: IConfig) {
  const app = createApp(MessageBox, {
    config, // 组件参数配置
    onConfirm() { // 确认按钮事件
      config.onConfirm && config.onConfirm(() => {
        app.unmount()
        div.remove()
      })
    },
    onCancel() { // 取消按钮事件
      if (config.onCancel) {
        config.onCancel(() => {
          app.unmount()
          div.remove()
        })
      } else {
        app.unmount()
        div.remove()
      }
    }
  })
  const div = document.createElement('div')
  document.body.appendChild(div)
  app.mount(div)
}

如何使用

引入抛出的方法:

ts 复制代码
import showMsg from '@/components/MessageBox';

点击按钮时调用即可:

ts 复制代码
const handleOpenMsg2 = () => {
  showMsg({
    title: '命令式组件',
    message: '测试内容',
    onConfirm: (close: any) => {
      console.log(11111);
      close()
    },
    onCancel: (close: any) => {
      console.log(22222);
      close()
    }
  })
}

以上就是命令式组件的封装了。当然这也不是更简洁的封装,这里将组件的vue文件和ts文件分开了;更为一体化的封装则是将vue模版组件的内容通过JSX写入到ts文件中,和react中的写法类似,这里就不过多赘述了,感兴趣的前端小伙伴们可以去尝试一下哦!

相关推荐
只喜欢赚钱的棉花没有糖12 分钟前
http的缓存问题
前端·javascript·http
小小小小宇27 分钟前
请求竞态问题统一封装
前端
loriloy28 分钟前
前端资源帖
前端
源码超级联盟30 分钟前
display的block和inline-block有什么区别
前端
GISer_Jing36 分钟前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js
让梦想疯狂38 分钟前
开源、免费、美观的 Vue 后台管理系统模板
前端·javascript·vue.js
海云前端1 小时前
前端写简历有个很大的误区,就是夸张自己做过的东西。
前端
葡萄糖o_o1 小时前
ResizeObserver的错误
前端·javascript·html
AntBlack1 小时前
Python : AI 太牛了 ,撸了两个 Markdown 阅读器 ,谈谈使用感受
前端·人工智能·后端
MK-mm2 小时前
CSS盒子 flex弹性布局
前端·css·html