如何创建一个动态 vue 组件,该组件具有一个计算模板,该模板包含另一个具有对象属性的组件而不将其作为字符串传递

how to create a dynamic vue component that has a computed template containing another component with Object properties without passing it as string

我有这样一个组件:

Relation.vue

<template>
    <div :is="dynamicRelation"></div>
</template>

<script>
  import Entry from '@/components/Entry';
  import weirdService from '@/services/weird.service';
  export default { 
      name: 'Relation',
      data() {
         return {
             entry1: { type: 'entity', value: 'foo', entity: {id: 4}},
             entry2: { type: 'entity', value: 'bar', entity: {id: 5}},
             innerText: '@1 wut @2',
         } 
      },
      computed: {
          dynamicRelation() {
              return {
                  template: `<div>${this.innerText
                        .replace('@1', weirdService.entryToHtml(this.entry1))
                        .replace('@2', weirdService.entryToHtml(this.entry2))}</div>`,
                  name: 'DynamicRelation',
                  components: { Entry }
              };
          }
      }
  }
</script>

wierd.service.js

export default {
   entryToHtml(entry) {
       [some logic]
       return `<entry entry='${JSON.stringify(entry)}'></entry>`;
       // unfortunately I cannot return JSX here: <entry entry={entry}></entry>; 
       // I get 'TypeError: h is not a function'
       // unless there is a way to convert JSX to a pure html string on the fly
    }
}

Entry.vue

<template>
    <div>{{objEntry.name}}</div>
</template>

<script>
  export default { 
      name: 'Entry',
      props: {
          entry: String // I need this to be Object
      },
      computed: {
          objEntry() {
              return JSON.parse(this.entry);
          }
       }
   }
</script>

innerText 属性 决定了组件的呈现方式,它可以通过在任何位置放置 @ 插槽来随时更改。 在此示例中,结果为:

<div>
   <div>foo</div> 
   wut 
   <div>bar</div>
</div>

这是有效的,因为 Entry 组件具有类型为 String 的 属性 entry,但我必须 JSON.stringify() [中的条目对象=19=] 端,然后在 Entry 组件中,我必须 JSON.parse() 字符串才能取回真实对象。 我怎样才能完成上述工作,以便将对象直接传递给动态模板,从而始终避免序列化和反序列化。

顺便说一句,要使它运行,需要在 vue.config.js:

中启用 runtimeCompiler
module.exports = { 
    runtimeCompiler: true
}

我知道我可以将 JSX 用于 return 带有对象的组件,但这似乎只在 render() 函数中允许,而不是像我这样的自定义函数。

谢谢!!

我仍然可以通过使用 JSON.stringify 来做我想做的事,但将条目作为对象传递 :entry

wierd.service.js

export default {
   entryToHtml(entry) {
       return `<entry :entry='${JSON.stringify(entry)}'></entry>`;
    }
}

Entry.vue

<template>
    <div>{{entry.name}}</div>
</template>

<script>
  export default { 
      name: 'Entry',
      props: {
          entry: Object
      }
   }
</script>