【问题标题】:Dynamically replaced text string with Vue component用 Vue 组件动态替换文本字符串
【发布时间】:2019-05-01 17:01:52
【问题描述】:

我正在尝试创建一个页面,该页面会将文本字符串 (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 部分并没有作为一个实际组件被引入,而是一个&lt;component&gt; 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>

&lt;component&gt; 标签应该是实际的 Vue 组件

【问题讨论】:

  • this 似乎是您可以使用的一种方法?
  • 不幸的是,我认为这行不通,因为它仍然需要我将&lt;component ... 放在我的主模板中,我只是不知道这些组件将出现在正文中的什么位置。我真的别无选择,只能想办法从文本文件中按原样呈现它们。
  • 您将制作一个组件,其中包含要进行替换的所有文本。

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


【解决方案1】:

You can't do it with v-html:

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

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

事实上,如果你想定义你的笔记块,等,你可以在内部使用非动态组件。 al. 作为组件而不是数据项,但您肯定需要将容器作为动态组件,因为这是将文本数据转换为 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>

【讨论】:

  • 我很想接受这个作为 LOTR 参考的答案 :) 谢谢,罗伊,这是有道理的。我会看看我能不能让它像这样工作。
  • 成功了!谢谢。我做了一点修改,以便我可以通过导入使用现有的 .vue 组件:pastebin.com/FrWHPmLu 你知道我如何将道具传递给这些组件吗?
  • 根据需要什么样的道具,您可以使用v-bind="propsObj" 来避免必须具体说明道具名称。除此之外,我认为没有任何技巧:将它们传递给 postProcessSpec 并将绑定包含在模板中。
  • 谢谢!我没想到先将它们传递给 postProcessSpec!现在一切正常。
  • 您好,感谢您在我来到这里的另一篇文章中的回答,一个问题是这是否真的支持 SSR 以及如何将自定义道具传递给组件,例如 &lt;swiper :options="...."&gt;&lt;/swiper&gt;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2015-11-04
  • 1970-01-01
相关资源
最近更新 更多