Pārlūkot izejas kodu

fix(markdown): resolving markdown exceptions

修复markdown组件的异常以及不能正确设置value的问题
无木 3 gadi atpakaļ
vecāks
revīzija
d95815b503

+ 1 - 0
CHANGELOG.zh_CN.md

@@ -21,6 +21,7 @@
   - 修复顶栏菜单在显示包含需要隐藏的菜单项目时出错的问题
   - 修复悬停触发模式下左侧混合菜单会在没有子菜单且被激活时直接跳转路由
 - **Breadcrumb** 修复带有重定向的菜单点击无法跳转的问题
+- **Markdown** 修复初始化异常以及不能正确地动态设置 value 的问题
 - **其它**
   - 修复菜单默认折叠的配置不起作用的问题
   - 修复`safari`浏览器报错导致网站打不开

+ 41 - 26
src/components/Markdown/src/Markdown.vue

@@ -5,18 +5,19 @@
   import {
     defineComponent,
     ref,
-    onMounted,
     unref,
-    onUnmounted,
     nextTick,
     computed,
     watch,
+    onBeforeUnmount,
+    onDeactivated,
   } from 'vue';
   import Vditor from 'vditor';
   import 'vditor/dist/index.css';
   import { useLocale } from '/@/locales/useLocale';
   import { useModalContext } from '../../Modal';
   import { useRootSetting } from '/@/hooks/setting/useRootSetting';
+  import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
 
   type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
 
@@ -26,7 +27,7 @@
       height: { type: Number, default: 360 },
       value: { type: String, default: '' },
     },
-    emits: ['change', 'get'],
+    emits: ['change', 'get', 'update:value'],
     setup(props, { attrs, emit }) {
       const wrapRef = ref<ElRef>(null);
       const vditorRef = ref<Nullable<Vditor>>(null);
@@ -36,17 +37,16 @@
 
       const { getLocale } = useLocale();
       const { getDarkMode } = useRootSetting();
+      const valueRef = ref('');
 
       watch(
         [() => getDarkMode.value, () => initedRef.value],
-        ([val]) => {
-          const vditor = unref(vditorRef);
-
-          if (!vditor) {
+        ([val, inited]) => {
+          if (!inited) {
             return;
           }
-          const theme = val === 'dark' ? 'dark' : undefined;
-          vditor.setTheme(theme as 'dark');
+          const theme = val === 'dark' ? 'dark' : 'classic';
+          instance.getVditor()?.setTheme(theme);
         },
         {
           immediate: true,
@@ -54,6 +54,16 @@
         }
       );
 
+      watch(
+        () => props.value,
+        (v) => {
+          if (v !== valueRef.value) {
+            instance.getVditor()?.setValue(v);
+            valueRef.value = v;
+          }
+        }
+      );
+
       const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
         let lang: Lang;
         switch (unref(getLocale)) {
@@ -72,54 +82,59 @@
         return lang;
       });
       function init() {
-        const wrapEl = unref(wrapRef);
+        const wrapEl = unref(wrapRef) as HTMLElement;
         if (!wrapEl) return;
         const bindValue = { ...attrs, ...props };
         vditorRef.value = new Vditor(wrapEl, {
-          theme: 'classic',
+          theme: getDarkMode.value === 'dark' ? 'dark' : 'classic',
           lang: unref(getCurrentLang),
           mode: 'sv',
           preview: {
             actions: [],
           },
           input: (v) => {
-            // emit('update:value', v);
+            valueRef.value = v;
+            emit('update:value', v);
             emit('change', v);
           },
+          after: () => {
+            nextTick(() => {
+              modalFn?.redoModalHeight?.();
+              initedRef.value = true;
+            });
+          },
           blur: () => {
-            unref(vditorRef)?.setValue(props.value);
+            //unref(vditorRef)?.setValue(props.value);
           },
           ...bindValue,
           cache: {
             enable: false,
           },
         });
-        initedRef.value = true;
       }
 
       const instance = {
         getVditor: (): Vditor => vditorRef.value!,
       };
 
-      onMounted(() => {
-        nextTick(() => {
-          init();
-          setTimeout(() => {
-            modalFn?.redoModalHeight?.();
-          }, 200);
-        });
-
-        emit('get', instance);
-      });
-
-      onUnmounted(() => {
+      function destroy() {
         const vditorInstance = unref(vditorRef);
         if (!vditorInstance) return;
         try {
           vditorInstance?.destroy?.();
         } catch (error) {}
+        vditorRef.value = null;
+      }
+
+      onMountedOrActivated(() => {
+        nextTick(() => {
+          init();
+        });
+        emit('get', instance);
       });
 
+      onBeforeUnmount(destroy);
+      onDeactivated(destroy);
       return {
         wrapRef,
         ...instance,

+ 12 - 1
src/views/demo/editor/markdown/index.vue

@@ -1,7 +1,13 @@
 <template>
   <PageWrapper title="MarkDown组件示例">
     <a-button @click="toggleTheme" class="mb-2" type="primary"> 黑暗主题 </a-button>
-    <MarkDown :value="value" @change="handleChange" ref="markDownRef" />
+    <a-button @click="clearValue" class="mb-2" type="default"> 清空内容 </a-button>
+    <MarkDown
+      v-model:value="value"
+      @change="handleChange"
+      ref="markDownRef"
+      placeholder="这是占位文本"
+    />
   </PageWrapper>
 </template>
 <script lang="ts">
@@ -30,11 +36,16 @@
         valueRef.value = v;
       }
 
+      function clearValue() {
+        valueRef.value = '';
+      }
+
       return {
         value: valueRef,
         toggleTheme,
         markDownRef,
         handleChange,
+        clearValue,
       };
     },
   });