Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

1.1K
Visualizações
¿Cómo creo un elemento personalizado de Vue 3, incluidos los estilos de componentes secundarios?

defineCustomElement() de Vue para crear un elemento personalizado, pero los estilos de los componentes secundarios no están incluidos en la raíz oculta por algún motivo.

Luego traté de crear manualmente mi shadow root usando la API nativa Element.attachShadow() en lugar de usar defineCustomElement() (basado en un Codesandbox ), pero luego no se cargaron estilos en absoluto:

Código : main.js :

 import { createApp } from "vue"; import App from "./App.vue"; import router from "./router"; import store from "./store"; let treeHead = document.querySelector("#app"); let holder = document.createElement("div"); let shadow = treeHead.attachShadow({ mode: "open" }); shadow.appendChild(holder); createApp(App).use(store).use(router).mount(holder);

Código vue.config.js :

 module.exports = { chainWebpack: (config) => { config.module .rule("vue") .use("vue-loader") .loader("vue-loader") .tap((options) => { options.shadowMode = true; return options; }); config.module .rule("css") .oneOf("vue-modules") .use("vue-style-loader") .tap((options) => { options.shadowMode = true; return options; }); config.module .rule("css") .oneOf("vue") .use("vue-style-loader") .tap((options) => { options.shadowMode = true; return options; }); }, };

package.json :

 { "name": "shadow-root", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" }, "dependencies": { "vue": "^3.2.20", "vue-loader": "^16.8.2", "vue-router": "^4.0.0-0", "vue-style-loader": "^4.1.3", "vuex": "^4.0.0-0" }, "devDependencies": { "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/compiler-sfc": "^3.0.0", "node-sass": "^4.12.0", "sass-loader": "^8.0.2" }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ] }

¿Cómo puedo crear un elemento personalizado con todos sus estilos en la raíz de la sombra?

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Esa configuración de Vue no es necesaria en Vue 3. Solo la necesitaba el servidor de desarrollo en Vue 2 para representar los estilos en elementos personalizados.

El uso defineCustomElement() es la forma recomendada de registrar elementos personalizados. Sin embargo, hay un problema abierto al usar defineCustomElement() , donde los estilos de componentes anidados no se representan en absoluto ( @vuejs/vue-next#4462 ).

Una solución es importar todos los componentes como elementos personalizados para que los estilos se adjunten a la definición del componente en lugar de agregarse a <head> , luego inserte esos estilos en el DOM al montarlos:

  • Habilite el modo customElement vue-loader en vue.config.js :

     // vue.config.js module.exports = { chainWebpack: config => { config.module .rule('vue') .use('vue-loader') .tap(options => { options.customElement = true return options }) } }

    Como alternativa, cambie el nombre de todas las extensiones de nombre de archivo de componentes de .vue a .ce.vue .

  • Cree una función de utilidad que envuelva defineCustomElement() de Vue y haga lo siguiente en un setup() :

    1. Cree una instancia de aplicación temporal que agregue una mixin para los enlaces de ciclo de vida mounted y unmounted .
    2. En el enlace mounted , inserte los estilos propios del componente desde this.$.type.styles en el DOM en una etiqueta <style> . Haga lo mismo con las definiciones de componentes del mapa this.$options.components .
    3. En el gancho unmounted , elimine la etiqueta <style> que se insertó desde el mounted .
    4. Copie el _context de la instancia de la aplicación temporal en el contexto de la aplicación actual desde getCurrentInstance() .
    5. Devuelve una función de representación para el componente.
     // defineCustomElementWithStyles.js import { defineCustomElement as VueDefineCustomElement, h, createApp, getCurrentInstance } from 'vue' const nearestElement = (el) => { while (el?.nodeType !== 1 /* ELEMENT */) el = el.parentElement return el } export const defineCustomElement = (component) => VueDefineCustomElement({ setup() { const app = createApp() 1️⃣ app.mixin({ mounted() { const insertStyles = (styles) => { if (styles?.length) { this.__style = document.createElement('style') this.__style.innerText = styles.join().replace(/\n/g, '') nearestElement(this.$el).prepend(this.__style) } } 2️⃣ insertStyles(this.$?.type.styles) if (this.$options.components) { for (const comp of Object.values(this.$options.components)) { insertStyles(comp.styles) } } }, unmounted() { this.__style?.remove() 3️⃣ }, }) 4️⃣ const inst = getCurrentInstance() Object.assign(inst.appContext, app._context) 5️⃣ return () => h(component) }, })
  • Edite public/index.html para reemplazar el <div id="app"> con un elemento personalizado (p. ej., llamado " app-root "):

    Antes:

     // public/index.html <body> <div id="app"></div> </body>

    Después:

     // public/index.html <body> <app-root id="app"></app-root> </body>
  • En lugar de createApp() , usa defineCustomElement() de arriba para crear un elemento personalizado de tu aplicación:

    Antes:

     // main.js import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')

    Después:

     // main.js import { defineCustomElement } from './defineCustomElementWithStyles' import App from './App.vue' customElements.define('app-root', defineCustomElement(App))

manifestación

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda