之前做了一个查看文件源代码的组件,想着使用组件不方便,所以做成了js调用的方式
使用
showSourceCode('/src/directives/module/resize.ts')
功能实现
<template>
<el-dialog
:modelValue="show"
align-center
append-to-body
destroy-on-close
:before-close="close"
modal-class="source-code-dialog"
v-bind="dialogProps">
<template #header>
<div>
代码地址:<span class="font-bold ml-5">{{ codePath }}</span>
</div>
</template>
<section class="code-area overflow-auto no-scroll">
<Code :html="getSourceCode" :language="dialogProps.language" />
</section>
<template #footer>
<div class="dialog-footer">
<el-button @click="close" type="danger">关闭</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import Code from '@/components/code/index.vue'
import { IDialogProps } from '.'
const codePath = ref('')
const show = ref(false)
const dialogProps = ref<IDialogProps & { language: 'js' | 'ts' | 'json' | string }>({
width: 900,
language: 'ts',
})
const getSourceCode = computed(() => {
const allFiles = import.meta.glob(['@/directives/**', '@/components/**'], {
eager: true,
as: 'raw',
})
// console.log(`allFiles ==>`, allFiles)
return allFiles[codePath.value] || '```代码地址不存在```'
})
const close = () => {
show.value = false
}
const open = (_codePath: string, _dialogProps?: IDialogProps) => {
codePath.value = _codePath
if (_dialogProps) {
dialogProps.value = {
...dialogProps.value,
..._dialogProps,
}
}
show.value = true
return true
}
defineExpose({
close,
open,
})
</script>
<style lang="scss">
.source-code-dialog {
font-style: italic;
.el-overlay-dialog {
.el-dialog {
@apply rounded-xl;
.el-dialog__body {
padding: 0 15px;
font-size: 15px;
.code-area {
max-height: calc(100vh - 150px);
overflow: auto;
}
}
}
}
}
</style>
import { createVNode, render, createApp } from 'vue'
import Index from './index.vue'
import { ElDialog } from 'element-plus'
export type IDialogProps = InstanceType<typeof ElDialog>['$props']
/**
* 查看源代码
* @param codePath
*
*/
export const showSourceCode = async (codePath: string, dialogProps: IDialogProps = {}) => {
const excuteFn = () => {
const vNode = createVNode(Index)
render(vNode, document.body)
const { open, close } = vNode.component?.exposed as InstanceType<typeof Index>
open(codePath, dialogProps)
}
try {
excuteFn()
} catch (error) {
console.log(`error ==>`, error)
excuteFn()
}
}
组件正常显示
出现问题 (DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.)
error ==> DOMException: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.
at insert (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:9134:12)
at Object.process (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:7873:7)
at patch (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:6448:16)
at ReactiveEffect.componentUpdateFn [as fn] (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:7106:11)
at ReactiveEffect.run (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:423:19)
at instance.update (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:7212:52)
at setupRenderEffect (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:7220:5)
at mountComponent (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:7010:5)
at processComponent (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:6963:9)
at patch (http://192.168.5.240:9527/node_modules/.vite/deps/chunk-M4WZCJL6.js?v=ec5b445d:6436:11)
这个问题我搜了半天不知道问题出在哪里 因为这样js调用的方式我在两年前就写过一模一样的示例,但是没报错
查询问题的原因的出在插入dom的问题,不知道vue更新了什么导致使用这一api报错
解决方法 添加
<div id="dialog-container"></div>
<body>
<div id="app"></div>
<div id="dialog-container"></div>
<div id="loading-mask">
<div class="loading-wrapper">
<span class="loading-dot loading-dot-spin">
<i></i>
<i></i>
<i></i>
<i></i>
</span>
</div>
</div>
<script type="module" src="./src/main.ts"></script>
</body>
/**
* 查看源代码
* @param codePath
*
*/
export const showSourceCode = async (codePath: string, dialogProps: IDialogProps = {}) => {
const excuteFn = () => {
const vNode = createVNode(Index)
render(vNode, document.getElementById('dialog-container'))
const { open, close } = vNode.component?.exposed as InstanceType<typeof Index>
open(codePath, dialogProps)
}
try {
excuteFn()
} catch (error) {
console.log(`error ==>`, error)
excuteFn()
}
}
问题解决了
猜测是因为 **teleport** 导致的