在vuejs中实现简单的markdown指令,反应性问题

Implementing simple markdown directive in vuejs, reactivity problem

我尝试实现一个非常简单的 Markdown 格式化程序指令(只是粗体、强调和删除线),以更加独立于 vue-18n 格式。当前指令如下所示:

    import _Vue from 'vue';
    
    const emphasize = (str: string) => {
      const matched = /(\*|_)(.*?)(\*|_)/gm;
      return str.replace(matched, '<em></em>');
    };
    
    const strong = (str: string) => {
      const matched = /(\*\*|__)(.*?)(\*\*|__)/gm;
      return str.replace(matched, '<strong></strong>');
    };
    
    const strikeThrough = (str: string) => {
      const matched = /~~(.*?)~~/gm;
      return str.replace(matched, '<s></s>');
    };
    
    const fromMd = (str: string) => strikeThrough(emphasize(strong(str)));
    
    export default {
      install: (Vue: typeof _Vue): void => {
        /* eslint-disable no-param-reassign */
        Vue.directive('tmd', {
          bind(el: HTMLElement) {
            el.innerHTML = fromMd(el.innerHTML);
          },
          inserted(el: HTMLElement) {
            el.innerHTML = fromMd(el.innerHTML);
          },
          update(el: HTMLElement) {
            el.innerHTML = fromMd(el.innerHTML);
          },
        });
      },
    };

我是这样使用的:

<p v-tmd >{{ $t('path-to-translation', ) }}</p>

到目前为止一切正常,但问题是,当我更改语言时,指令似乎没有更新。它接收到 updated 事件,但 el.innerHTML 未更新,因此它呈现旧事件。实现此行为的最佳做法是什么?

我不确定为什么解析 el.innerHTML 不起作用,但您可以改为解析 vnode 文本:

export default {
  install: Vue => {
    const childrenTextToMd = (el, binding, vnode) => {
      if (vnode.children) {
        el.innerHTML = vnode.children
          .map(child => fromMd(child.text))
          .join('')
      }
    }

    Vue.directive('tmd', {
      inserted: childrenTextToMd,
      update: childrenTextToMd
    })
  }
}

旁注: strikeThrough() 可以替代 </code>,但只有一个捕获组,所以它应该是 <code>.

demo