用Vue组件动态替换文本字符串

时间:2018-11-29 15:24:34

标签: javascript vue.js vue-dynamic-components

我正在尝试创建一个页面,该页面会将文本字符串(https://pastebin.com/Mp9sKy1A)加载到页面中,然后将--FML-[componentName]的任何实例替换为适当的组件。

例如,--FML-[NoteBlock]将自动替换为NoteBlock组件。

这是我到目前为止所拥有的:

pureContent () {
      const c = this.content.replaced
      const re = new RegExp(`<p>--FML-\\[(\\w+)\\]</p>`, 'g')
      return c.replace(re, ($0, $1) => `<component v-bind:is="${$1.toLowerCase()}"></component>`)
    }

然后将输出放置到以下模板中:

<template>
  <div>
    <site-header></site-header>
    <div class="wrapper">
      <side-bar></side-bar>
      <main class="container" v-html="pureContent()" />
    </div>
  </div>
</template>

实际上是一种作品。但是,component部分并不是作为实际组件插入的,而是作为<component> HTML标记的,这显然不是期望的结果。有没有一种方法可以使其按需工作?

如果有人感兴趣,这里是完整的SFC文件:https://pastebin.com/yb4CJ1Ew

这是我当前得到的输出:

<main data-v-86dcc3c4="" class="container">
  <h1 id="creating-new-contexts">Creating new contexts</h1>
  <h2 id="section-title">Section Title</h2>
  <h3 id="section-subtitle-that-contains-additional-information">
    Section subtitle that contains additional information
  </h3>
  <p>
    Cillum ipsum ad veniam elit non. Sunt ea ut quis qui dolore id voluptate
    magna. Ex non commodo reprehenderit ipsum irure. Ad excepteur nulla ullamco
    et deserunt magna et sint reprehenderit sint esse commodo. Tempor duis anim
    nisi commodo incididunt ut ex et sunt laborum excepteur ea culpa laborum.
  </p>
  <component v-bind:is="noteblock"></component>
  <p>
    Officia esse Lorem ad duis dolore nostrud ex elit aliqua incididunt sint ad
    ex. Eiusmod do in ad aute nulla eiusmod tempor Lorem non. Qui sunt voluptate
    laborum mollit elit adipisicing minim dolore voluptate veniam incididunt
    proident ullamco. Ipsum est cupidatat occaecat pariatur ut aute.
  </p>
  <component v-bind:is="codeexample"></component>
  <component v-bind:is="propstable"></component>
</main>

<component>标签应该是实际的Vue组件

1 个答案:

答案 0 :(得分:2)

You can't do it with v-html

  

更新元素的innerHTML。请注意,内容已插入   作为纯HTML-它们不会被编译为Vue模板。如果你   发现自己尝试使用v-html撰写模板,尝试重新思考   通过使用组件代替解决方案。

您已经在使用动态组件,只需要一个组件即可将它们全部统治(并在文档中将其绑定)。

实际上,如果要定义记事本 et,则可以在内部使用非动态组件。 作为组件而不是数据项,但是您肯定需要使容器成为动态组件,因为这是将文本数据转换为Vue管理的DOM的唯一方法。

new Vue({
  el: '#app',
  data: {
    preContent: "<h1 id=\"creating-new-contexts\">Creating new contexts</h1>\n<h2 id=\"section-title\">Section Title</h2>\n<h3 id=\"section-subtitle-that-contains-additional-information\">Section subtitle that contains additional information</h3>\n<p>Cillum ipsum ad veniam elit non. Sunt ea ut quis qui dolore id voluptate magna. Ex non commodo reprehenderit ipsum irure. Ad excepteur nulla ullamco et deserunt magna et sint reprehenderit sint esse commodo. Tempor duis anim nisi commodo incididunt ut ex et sunt laborum excepteur ea culpa laborum.</p>\n<p>--FML-[NoteBlock]</p>\n<p>Officia esse Lorem ad duis dolore nostrud ex elit aliqua incididunt sint ad ex. Eiusmod do in ad aute nulla eiusmod tempor Lorem non. Qui sunt voluptate laborum mollit elit adipisicing minim dolore voluptate veniam incididunt proident ullamco. Ipsum est cupidatat occaecat pariatur ut aute.</p>\n<p>--FML-[CodeExample]</p>\n<p>--FML-[PropsTable]</p>\n"
  },
  computed: {
    pureContent() {
      const c = this.preContent;
      const re = new RegExp(`<p>--FML-\\[(\\w+)\\]</p>`, 'g');

      return c.replace(re, ($0, $1) => `<component v-bind:is="${$1.toLowerCase()}"></component>`);
    },
    postProcessSpec() {
      return {
        template: `<div>${this.pureContent}</div>`,
        data() {
          return {
            codeexample: {
              template: '<pre>This is the CODEEXAMPLE component</pre>'
            },
            noteblock: {
              template: '<div>This is the NOTEBLOCK component</div>'
            },
            propstable: {
              template: '<table border=1><th>PROPS TABLE!</th></table>'
            }
          }
        },
        components: {}
      };
    }
  }
});
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <component :is="postProcessSpec"></component>
</div>