带有自定义组件的Vue 3h()

vbopmzt1  于 2023-05-01  发布在  Vue.js
关注(0)|答案(2)|浏览(157)

我已经读了大约100个关于这个的帖子,仍然不能完全理解。
我尝试从后端API解析字符串模板并使用自定义组件呈现它。
我在vite.config.js中别名了esm build:

resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
      vue: 'vue/dist/vue.esm-bundler.js',
    },
  },

下面是我的组件:

<script>
import { defineAsyncComponent, h } from 'vue';

export default {
  components: {
    PageCalculator: defineAsyncComponent(() => import('@/components/PageCalculator.vue')), /* eslint-disable-line */
  },
  props: {
    content: {
      type: String,
      default: '',
    },
  },
  render() {
    const render = {
      template: `<div class="content">${this.content}</div>`,
    };
    return h(render);
  },
};
</script>

这给出了错误Failed to resolve component
如何动态加载组件?我有大量的组件,后端可以发送回来,所以我想懒惰地加载它们。
下面是如何从外部组件使用它:

<app-page :title="page.title" container-class="w-full">
  <compiled-content :content="page.content_html" />
</app-page>

HTML的内容可能看起来像这样(content prop ):

<p>this is a nice sentence</p>
<page-calculator />
<p>this is a <router-link :to="{name: 'home'}">link</router-link></p>
jckbn6z7

jckbn6z71#

你应该更好地使用Vue slots而不是props
你也不应该插入HTML,因为它不能与组件一起工作。

template: `<div class="content">${this.content}</div>`,

使用Vue Render Functions代替。

const { createApp, h, defineAsyncComponent  } = Vue;

const test = { template: 'Test' }
const PageCalculator = 
  defineAsyncComponent(() => {
    return new Promise((resolve, reject) => {                
       resolve( { template: 'My PageCalculator' } )
    })
  })

const CompiledContent = {
  template: 'Slot: <slot></slot>'  
}

const App = { 
  components:  {CompiledContent, PageCalculator }
}

const app = createApp(App)
const vm = app.mount('#app')
#app { line-height: 2; }
[v-cloak] { display: none; }
<div id="app" v-cloak>
 <compiled-content><page-calculator></page-calculator></compiled-content>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
46scxncf

46scxncf2#

这是一个痛苦的旅程,但答案是如此简单。

下面是如何从服务器动态呈现vue组件的方法,即使它们混合在html中

我非常惊讶答案不是在更多的地方。..人们让我注册全局组件,使用不起作用的方法。实际上,我最终只是偶然发现了它在我自己,而试图拼凑成吨不同的答案。
以下是最终版本:
1.从服务器实时编译vue代码
1.使用该组件中的组件和方法执行此操作,而不需要全局组件

<script>
import { h } from 'vue';
import AppAlert from '@/components/AppAlert.vue';

export default {
  props: {
    content: {
      type: String,
      default: '',
    },
  },
  render() {
    const r = {
      components: {
        AppAlert,
      },
      template: `<div class="content">${this.content || ''}</div>`,
      methods: {
        hello() {
          // method "hello" is also available here
        },
      },
    };
    return h(r);
  },
};
</script>

如果你的内容中有很多组件,你也可以让它们都是异步组件:

components: {
  AppAlert: defineAsyncComponent(() => import('@/components/AppAlert.vue')), 
  ...

相关问题