首页 > 解决方案 > 在 vuejs 中实现简单的 markdown 指令,反应性问题

问题描述

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

    import _Vue from 'vue';
    
    const emphasize = (str: string) => {
      const matched = /(\*|_)(.*?)(\*|_)/gm;
      return str.replace(matched, '<em>$2</em>');
    };
    
    const strong = (str: string) => {
      const matched = /(\*\*|__)(.*?)(\*\*|__)/gm;
      return str.replace(matched, '<strong>$2</strong>');
    };
    
    const strikeThrough = (str: string) => {
      const matched = /~~(.*?)~~/gm;
      return str.replace(matched, '<s>$2</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没有更新,所以它呈现旧的。实现这种行为的最佳实践是什么?

标签: typescriptvue.jsvuejs2vue-i18n

解决方案


我不确定为什么解析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()有一个替代品$2,但只有一个捕获组,所以应该是$1.

演示


推荐阅读