feat: 优化md渲染组件性能表现
This commit is contained in:
1 parent
c1be93739d
commit
d20dc84d9d
4 files changed
+44
-31
No files matched your search
@@ -4,17 +4,19 @@
|
|||||||
<div class="md-render-wrapper markdown-body">
|
<div class="md-render-wrapper markdown-body">
|
||||||
<VNodeMD v-if="VNodeMD && props.data"></VNodeMD>
|
<VNodeMD v-if="VNodeMD && props.data"></VNodeMD>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<el-skeleton :rows="12" />
|
<el-skeleton v-if="!props.disableSkeleton" :rows="12" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import codemirrorMiddleware from '~/hooks/h2v/codemirrorMiddleware';
|
||||||
import useMarkdownit from '~/hooks/useMarkdownit';
|
import useMarkdownit from '~/hooks/useMarkdownit';
|
||||||
import Html2VNode from '~/utils/html2VNode';
|
import Html2VNode from '~/utils/html2VNode';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
data: string
|
data: string
|
||||||
|
disableSkeleton?: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const VNodeMD = shallowRef<any>()
|
const VNodeMD = shallowRef<any>()
|
||||||
@@ -26,31 +28,7 @@ watch(() => props.data, async () => {
|
|||||||
const markdownIt = await useMarkdownit()
|
const markdownIt = await useMarkdownit()
|
||||||
const renderedData = markdownIt.render(props.data)
|
const renderedData = markdownIt.render(props.data)
|
||||||
const h2v = new Html2VNode()
|
const h2v = new Html2VNode()
|
||||||
h2v.use(
|
h2v.use(codemirrorMiddleware)
|
||||||
{
|
|
||||||
filter(tagName) {
|
|
||||||
return tagName === 'code'
|
|
||||||
},
|
|
||||||
async render({
|
|
||||||
item,
|
|
||||||
tagAttrs,
|
|
||||||
}) {
|
|
||||||
const codeMirror = (await import('./codeMirror.vue')).default
|
|
||||||
const codeType = tagAttrs?.class?.slice(1, -1)?.split('-')?.[1] ?? ''
|
|
||||||
// @ts-ignore
|
|
||||||
const inline = (item.children[0].children.trim() as string).includes('\n') ? false : true
|
|
||||||
return h(
|
|
||||||
codeMirror,
|
|
||||||
{
|
|
||||||
// @ts-ignore
|
|
||||||
data: item.children[0].children.trim(),
|
|
||||||
type: codeType,
|
|
||||||
inline,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const res = await h2v.render(renderedData)
|
const res = await h2v.render(renderedData)
|
||||||
VNodeMD.value = {
|
VNodeMD.value = {
|
||||||
setup: () => {
|
setup: () => {
|
||||||
@@ -61,10 +39,6 @@ watch(() => props.data, async () => {
|
|||||||
immediate: true
|
immediate: true
|
||||||
})
|
})
|
||||||
|
|
||||||
// watch(() => renderedData.value, () => {
|
|
||||||
// _key.value = Math.random()
|
|
||||||
// })
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<el-input v-if="isEditing" type="textarea" v-model:model-value="content" placeholder="content"
|
<el-input v-if="isEditing" type="textarea" v-model:model-value="content" placeholder="content"
|
||||||
:autosize="{ minRows: 15 }" :disabled="disabled" />
|
:autosize="{ minRows: 15 }" :disabled="disabled" />
|
||||||
<div class=" border-1 border-gray-300 rounded-sm p-2" v-else>
|
<div class=" border-1 border-gray-300 rounded-sm p-2" v-else>
|
||||||
<markdown-render :data="content ?? ''" />
|
<markdown-render :data="content ?? ''" :disable-skeleton="true" />
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
const codemirrorMiddleware: middlewareType = {
|
||||||
|
filter(tagName: string) {
|
||||||
|
return tagName === 'code'
|
||||||
|
},
|
||||||
|
async render({
|
||||||
|
item,
|
||||||
|
tagAttrs,
|
||||||
|
}) {
|
||||||
|
const codeMirror = await cachedPromise('component:codeMirror', async () => {
|
||||||
|
const codeMirror = (await import('~/components/codeMirror.vue')).default
|
||||||
|
return codeMirror
|
||||||
|
})
|
||||||
|
const codeType = tagAttrs?.class?.slice(1, -1)?.split('-')?.[1] ?? ''
|
||||||
|
// @ts-ignore
|
||||||
|
const inline = (item.children[0].children.trim() as string).includes('\n') ? false : true
|
||||||
|
return h(
|
||||||
|
codeMirror,
|
||||||
|
{
|
||||||
|
// @ts-ignore
|
||||||
|
data: item.children[0].children.trim(),
|
||||||
|
type: codeType,
|
||||||
|
inline,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default codemirrorMiddleware
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import useDefaultStore from "~/hooks/pinia/useDefaultStore"
|
||||||
|
|
||||||
|
export default async function cachedPromise<T>(key: string, promise: () =>Promise<T>): Promise<T> {
|
||||||
|
const cache = useDefaultStore().getCache(key)
|
||||||
|
if (cache) {
|
||||||
|
return cache
|
||||||
|
}
|
||||||
|
const res = await promise()
|
||||||
|
useDefaultStore().setCache(key, res)
|
||||||
|
return res
|
||||||
|
}
|
||||||
Reference in new issue
Block a user