Vue 3 h() с пользовательским компонентом

Я прочитал около 100 тем по этому поводу и до сих пор не могу понять.

Я пытаюсь разобрать шаблон строки из внутреннего API и отобразить его с помощью пользовательских компонентов.

У меня есть псевдоним для сборки esm vite.config.js:

  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):

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

где вы используете PageCalculator?

Boussadjra Brahim 23.04.2023 23:34

@BoussadjraBrahim, я отредактировал свой вопрос. его HTML в качестве опоры

Tallboy 23.04.2023 23:41

Вы пытались определить псевдоним src с помощью пути ? alias: { '@': path.resolve(__dirname, './src') }. Такой конфигурации как у вас я еще не видел.

Samuel Eiche 24.04.2023 10:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
209
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам лучше использовать слоты Vue для контента вместо 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>

Эй, спасибо. Как это будет работать с моим полным примером с фактическим текстом? Это будут страницы объемом более 2000 слов с добавлением компонентов vue.

Tallboy 25.04.2023 15:41

Неважно, что вы положите внутрь слота. Просто создайте свой код вокруг этой концепции или примите ее на основе своего кода.

Tolbxela 25.04.2023 17:44
Ответ принят как подходящий

Вау, это было такое болезненное путешествие, но ответ так прост.

вот как вы динамически визуализируете компоненты vue с сервера, даже если они смешаны в html

Я очень удивлен, что ответ не в большем количестве мест ... люди заставляли меня регистрировать глобальные компоненты, используя методы, которые не работали. На самом деле, в конце концов, я просто наткнулся на него сам, пытаясь собрать воедино множество разных ответов.

Вот окончательная версия, которая:

  1. компилирует код vue в реальном времени с сервера
  2. делает это с компонентами и методами внутри этого компонента, не требуя глобальных компонентов
<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')), 
  ...

Другие вопросы по теме