We’ve all written something like this: import {message} from ‘antd’; Message. Success (‘ success ‘); Have we considered wrapping such a component ourselves and importing it into JS? I call this a functional component, and after reading this article, I’m sure you can encapsulate your own ‘functional components’ in vuE3 projects.

In my opinion, vuE3 development should have three forms of component encapsulation, respectively

  1. The most common imported component
  2. Global components (similar to global imports of component library ANTD)
  3. Functional components (that is, components that can be used in JS code, like this.$message({}))

Component directory structure

Import component

Component code: / SRC/components/import/BButton vue

<template> <a-button @click="clickBack" type="primary" plain> {{ text }} </a-button> </template> <script setup> import {  useRouter } from "vue-router"; Const props = defineProps({text: {type: String, default: "back"}, backLevel: {type: Number, default: 1,},}); const router = useRouter(); const clickBack = () => { router.go(-props.backLevel); }; </script>Copy the code

Use: / SRC /views/ home.vue to import pages

Import BButton from '@ / components/import/BButton vue' < b - the button text = "the simplest import component" > < / b - button >Copy the code

Global components

Component code: / SRC/components/common/BackButton. Vue

<template> <a-button @click="clickBack" type="primary" plain> {{text}} </a-button> </template> <script setup> import { useRouter } from "vue-router"; Const props = defineProps({text: {type: String, default: "back"}, backLevel: {type: Number, default: 1,},}); const router = useRouter(); const clickBack = () => { router.go(-props.backLevel); }; </script>Copy the code

Global import: / SRC /config/d.ts

// Read all vue components in the common directory using the import.meta.globEager provided by vite, with D+ filename as component name. Const componentList = import.meta. GlobEager ('.. /components/common/**'); let componentArray = new Object() Object.keys(componentList).forEach((key) => { let keyArray = key.split('/') let name =  'D' + keyArray[keyArray.length - 1].split('.')[0] componentArray[name] = componentList[key].default }) export default function (app) { Object.keys(componentArray).forEach((key) => { app.component(key, componentArray[key]) }) }Copy the code

Use this d.ts in main.ts

import d from "@/config/d";
app.use(d)
Copy the code

/ SRC /views/ home.vue is directly used on a page without import

<d-back-button text=" <d-back-button text=" <d-back-button text=" </d-back-button>Copy the code

Functional component

Functional components can be imported in a Vue file or used through global variables, as well as in a JS file

We may encounter a scenario where we need to pop up a global custom component on interface error or success, which cannot be written in a Vue file or use components from a component library, but instead needs to be written in a JS/TS file such as AXIos and used via import. So how do we use and encapsulate a functional component in JS?

Component code: / SRC/components/function/components/tipsDialog vue

<template> < modal-V-Model :visible="pageVisible" title=" Custom global function component "@OK ="_sure" @cancel="pageVisible = false" :okText="okText" > {{content}} </Modal> </template> <script setup> import { ref, watch } from "vue"; Import {Modal} from "ant-design-vue"; import {Modal} from "ant-design-vue"; const props = defineProps({ visible: { type: Boolean, default: false, }, okText: { type: String, default: }, handleOk: {type: Function, // successful callback default: null,}, remove: {type: Default: null,}, Content :{type: String, default: "custom global Function component......" ,}}); const pageVisible = ref(false); pageVisible.value = props.visible; Dom watch(() => pageVisible. Value, (val) => {! val && props.remove(); }); // const _sure = () => {typeof props. HandleOk === "function" && props. HandleOk (" component parameters "); pageVisible.value = false; }; </script>Copy the code

Component code: / SRC/components/function/components/tipsDialog ts

import { createApp } from 'vue'; Import FunTipsDialog from './ tipsdialog. vue' import FunTipsDialog from './ tipsdialog. vue' // Create a mount instance of export default function using vue3 createApp and mount and unmount methods TipsDialog(options) {create a node, And mount components on a const mountNode = document. The createElement method (' div ') document. The body. The appendChild (mountNode) const app = createApp(FunTipsDialog, { ... options, visible: true, Remove () {app. Unmount to (mountNode) / / to destroy the document. After you create the body. The removeChild (mountNode)}}) return app. Mount (mountNode)}Copy the code

Component code: / SRC/components/function/index. The ts

Const componentsList = import.meta. GlobEager ("./components/**"); let List = {}; Export default function (app) {object.keys (componentsList).foreach ((key) => {// Filter ts suffix if (key.split(".")[2] === List[' $${componentsList[key].default.name} '] = componentsList[key].default; // Define the function component into the global variable, In the vue script used by proxy app. Config. GlobalProperties [` $${componentsList [key]. Default. The name} `] = componentsList[key].default; }}); } // Export const funentList = List;Copy the code

Use this index.ts in main.ts

import fc from "@/components/function/index"
app.use(fc)
Copy the code

Use/SRC /views/ home.vue in vue

< a-button@click ="clickOpenFunComponent"> this is a custom global function component, </a-button> import {getCurrentInstance} from "vue"; const { proxy } = getCurrentInstance(); Const clickOpenFunComponent = () => {proxy.$TipsDialog({handleOk: (STR) => {console.log(" Click ok, can do callback here. ") +str); }}); }; / / can also be imported using the import {funComponentList} from "@ / components/function/index"; $TipsDialog({content:" function component triggered in Request. ts ", handleOk: (STR) => {console.log(" click here to make a callback. +str); }});Copy the code

Used in request.ts, which pops up/SRC /config/request.ts when the interface is successfully called or an error is reported

import { funComponentList } from "@/components/function/index"; if (response? .status === 200) {funComponentList.$TipsDialog({content:" Function component on request.ts ", handleOk: (STR) => {console.log(" Click ok, callback can be done here." +str); }}); }Copy the code

Project screenshots:

The project address project currently introduces: I18N Vuex V-Router Less Mock Axios Package Ant-Design (load on demand) Sentry Build subcontract Env TS support three forms of package component support Jsx. A star ~