最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vue.js - Vue+Vite+Quasar as web component - Stack Overflow

programmeradmin0浏览0评论

I have vue3+vite+quasar project with pages, components, etc. and I want individual components to be able to be turned into web components so that they can be used in any other places, I already had a little experience with this but now because of third-party libraries I have problems that I can't solve if you can help please

vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { quasar } from '@quasar/vite-plugin';

export default defineConfig({
  plugins: [
    vue(),
    quasar({
      autoImportComponentCase: 'pascal',
    }),
  ],
  define: {
    'process.env': {},
  },
  build: {
    target: 'esnext',
    rollupOptions: {
      output: {
        globals: {
          vue: 'Vue',
          quasar: 'Quasar',
        },
        assetFileNames: (assetInfo) => {
          if (assetInfo.name.endsWith('.css')) {
            return 'web.css';
          }
          return 'assets/[name]-[hash][extname]';
        },
        format: 'es',
        manualChunks: null,
        inlineDynamicImports: true,
      },
      external: [],
    },
    lib: {
      entry: 'src/main.ts',
      name: 'web',
      fileName: (format) => `web.${format}.js`,
      formats: ['es', 'umd', 'iife'],
    },
  },
});

main.ts

import 'quasar/dist/quasar.css';
import { createApp, defineCustomElement } from 'vue';
import { Quasar, QCard } from 'quasar';
import HelloWorld from './components/HelloWorld.vue';

const app = createApp(HelloWorld);

app.use(Quasar, {
    config: {
        dark: false,
    },
    components: {
        QCard,
    },
    plugins: [],
});

const createInstantGameElement = defineCustomElement(HelloWorld);

customElements.define('my-web-component', createInstantGameElement);


app.mount('#app');

HelloWorld.vue

<script setup lang="ts">
import { QCard } from 'quasar'
</script>

<template>
  test1
  <QCard class="q-pa-lg">
    test2
  </QCard>
</template>

<style scoped>

</style>

Try index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../dist/web.css">
    <script type="module" src="../dist/web.es.js"></script>
</head>
<body>
<my-web-component/>
</body>
</html>

at the exit I see string 'test1' and warn with error [Vue warn]: Unhandled error during execution of render function at <QCard class="q-pa-lg" > at <VueElement >

and Uncaught TypeError: Cannot read properties of undefined (reading 'dark')

I have vue3+vite+quasar project with pages, components, etc. and I want individual components to be able to be turned into web components so that they can be used in any other places, I already had a little experience with this but now because of third-party libraries I have problems that I can't solve if you can help please

vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { quasar } from '@quasar/vite-plugin';

export default defineConfig({
  plugins: [
    vue(),
    quasar({
      autoImportComponentCase: 'pascal',
    }),
  ],
  define: {
    'process.env': {},
  },
  build: {
    target: 'esnext',
    rollupOptions: {
      output: {
        globals: {
          vue: 'Vue',
          quasar: 'Quasar',
        },
        assetFileNames: (assetInfo) => {
          if (assetInfo.name.endsWith('.css')) {
            return 'web.css';
          }
          return 'assets/[name]-[hash][extname]';
        },
        format: 'es',
        manualChunks: null,
        inlineDynamicImports: true,
      },
      external: [],
    },
    lib: {
      entry: 'src/main.ts',
      name: 'web',
      fileName: (format) => `web.${format}.js`,
      formats: ['es', 'umd', 'iife'],
    },
  },
});

main.ts

import 'quasar/dist/quasar.css';
import { createApp, defineCustomElement } from 'vue';
import { Quasar, QCard } from 'quasar';
import HelloWorld from './components/HelloWorld.vue';

const app = createApp(HelloWorld);

app.use(Quasar, {
    config: {
        dark: false,
    },
    components: {
        QCard,
    },
    plugins: [],
});

const createInstantGameElement = defineCustomElement(HelloWorld);

customElements.define('my-web-component', createInstantGameElement);


app.mount('#app');

HelloWorld.vue

<script setup lang="ts">
import { QCard } from 'quasar'
</script>

<template>
  test1
  <QCard class="q-pa-lg">
    test2
  </QCard>
</template>

<style scoped>

</style>

Try index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="../dist/web.css">
    <script type="module" src="../dist/web.es.js"></script>
</head>
<body>
<my-web-component/>
</body>
</html>

at the exit I see string 'test1' and warn with error [Vue warn]: Unhandled error during execution of render function at <QCard class="q-pa-lg" > at <VueElement >

and Uncaught TypeError: Cannot read properties of undefined (reading 'dark')

Share Improve this question asked Mar 28 at 15:55 Максим ПетруняМаксим Петруня 11 bronze badge
Add a comment  | 

1 Answer 1

Reset to default 0

app.use(Quasar) can't affect Quasar components, while they are expected to rely on framework-specific configuration. Web components are rendered in isolation from the rest of Vue application, even if they are implemented with Vue components. The documentation mentions provide/inject, but this is a special case of the mentioned problem.

This requires to be aware of framework components in use and their implementation. It can be seen that QCard relies on $q global component property that is normally provided with app.use(Quasar) and uses props as a fallback.

So it could be fixed with:

...
<QCard class="q-pa-lg" :dark="false">
...

Or by installing Quasar plugin to application instance that web component uses with configureApp option:

defineCustomElement(HelloWorld, {
  configureApp(app) {
    app.use(Quasar, {
      config: {
        dark: false,
      }
    });
  },
});

No components is necessary because QCard is imported locally. app.use(Quasar) for main application instance isn't needed.

发布评论

评论列表(0)

  1. 暂无评论