vue3 component 动态组件
vue3 component 动态组件
vue3的setup默认没有挂载组件了,因为自动挂载了,所以如果要做动态组件,就挂载到全局,在main.ts里面挂载,或其他地方也行。
<component
:is="item.chartConfig.chartKey"
:id="item.id"
:chartConfig="item"
:themeSetting="themeSetting"
:themeColor="themeColor"
:style="{
...getSizeStyle(item.attr),
...getFilterStyle(item.styles),
...getTransformStyle(item.styles)
}"
v-on="useLifeHandler(item)"
></component>
vue3 动态编译 没有加载components这一步了,所以这里只能挂载全局的组件,然后再调用。
main.ts
// 挂载到 window
window['$vue'] = app
// 注册全局自定义组件
setupCustomComponents(app)
...
// 挂载到页面
app.mount('#app', true)
src/plugins/customComponents.ts
import type { App } from 'vue'
import { GoSkeleton } from '@/components/GoSkeleton'
import { GoLoading } from '@/components/GoLoading'
import { SketchRule } from 'vue3-sketch-ruler'
/**
* 全局注册自定义组件
* @param app
*/
export function setupCustomComponents(app: App) {
// 骨架屏
app.component('GoSkeleton', GoSkeleton)
// 加载
app.component('GoLoading', GoLoading)
// 标尺
app.component('SketchRule', SketchRule)
}
src/utils/components.ts
import { defineAsyncComponent, AsyncComponentLoader } from 'vue'
import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading'
/**
* * 动态注册组件
*/
export const componentInstall = <T> (key:string, node: T) => {
if(!window['$vue'].component(key) && node) {
window['$vue'].component(key, node)
}
}
/**
* * 异步加载组件
* @param loader
* @returns
*/
export const loadAsyncComponent = (loader: AsyncComponentLoader<any>) =>
defineAsyncComponent({
loader,
loadingComponent: AsyncLoading,
delay: 20,
})
export const loadSkeletonAsyncComponent = (loader: AsyncComponentLoader<any>) =>
defineAsyncComponent({
loader,
loadingComponent: AsyncSkeletonLoading,
delay: 20,
})
拖拽处理
// 拖拽处理
const dragStartHandle = (e: DragEvent, item: ConfigType) => {
if (item.disabled) return
// 动态注册图表组件
componentInstall(item.chartKey, fetchChartComponent(item))
componentInstall(item.conKey, fetchConfigComponent(item))
// 将配置项绑定到拖拽属性上
e!.dataTransfer!.setData(DragKeyEnum.DRAG_KEY, JSONStringify(omit(item, ['image'])))
// 修改状态
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CREATE, true)
}
获取组件函数
/**
* * 获取组件
* @param {string} chartName 名称
* @param {FetchComFlagType} flag 标识 0为展示组件, 1为配置组件
*/
const fetchComponent = (chartName: string, flag: FetchComFlagType) => {
const module = flag === FetchComFlagType.VIEW ? indexModules : configModules
for (const key in module) {
const urlSplit = key.split('/')
if (urlSplit[urlSplit.length - 2] === chartName) {
return module[key]
}
}
}
/**
* * 获取展示组件
* @param {ConfigType} dropData 配置项
*/
export const fetchChartComponent = (dropData: ConfigType) => {
const { key } = dropData
return fetchComponent(key, FetchComFlagType.VIEW)?.default
}
/**
* * 获取配置组件
* @param {ConfigType} dropData 配置项
*/
export const fetchConfigComponent = (dropData: ConfigType) => {
const { key } = dropData
return fetchComponent(key, FetchComFlagType.CONFIG)?.default
}s
动态组件的变量
const configModules: Record<string, { default: string }> = import.meta.glob('./components/**/config.vue', {
eager: true
})
const indexModules: Record<string, { default: string }> = import.meta.glob('./components/**/index.vue', {
eager: true
})
const imagesModules: Record<string, { default: string }> = import.meta.glob('../assets/images/chart/**', {
eager: true
})
---------------------------------------------
生活的意义就是你自己知道你要做什么,明确目标。没有目标,后面都是瞎扯!
https://pengchenggang.gitee.io/navigator/
SMART原则:
目标必须是具体的(Specific)
目标必须是可以衡量的(Measurable)
目标必须是可以达到的(Attainable)
目标必须和其他目标具有相关性(Relevant)
目标必须具有明确的截止期限(Time-based)
生活的意义就是你自己知道你要做什么,明确目标。没有目标,后面都是瞎扯!
https://pengchenggang.gitee.io/navigator/
SMART原则:
目标必须是具体的(Specific)
目标必须是可以衡量的(Measurable)
目标必须是可以达到的(Attainable)
目标必须和其他目标具有相关性(Relevant)
目标必须具有明确的截止期限(Time-based)