javascript - 如何在新的vue自定义元素中正确注册和使用props?

标签 javascript vue.js vue-component vuejs3

我用新 future defineCustomElement从 vue 3.2 版本开始。

代码main.js:

    import { defineCustomElement } from './defineCustomElementWithStyles'
    import App from './App.ce.vue'
    import store from './store'
    import router from './router'
    
    customElements.define(
      'app-root',
      defineCustomElement(App, {
        plugins: [store, router],
      })
    )

代码defineCustomElementWithStyles.js:

import { defineCustomElement as VueDefineCustomElement, h, createApp, getCurrentInstance } from 'vue'

const getNearestElementParent = (el) => {
  while (el?.nodeType !== 1 /* ELEMENT */) {
    el = el.parentElement
  }
  return el
}

export const defineCustomElement = (component, { plugins = [] }) =>
  VueDefineCustomElement({
    render: () => h(component),
    setup() {
      const app = createApp()

      // install plugins
      plugins.forEach(app.use)

      app.mixin({
        mounted() {
          const insertStyles = (styles) => {
            if (styles?.length) {
              this.__style = document.createElement('style')
              this.__style.innerText = styles.join().replace(/\n/g, '')
              getNearestElementParent(this.$el).prepend(this.__style)
            }
          }

          // load own styles
          insertStyles(this.$?.type.styles)

          // load styles of child components
          if (this.$options.components) {
            for (const comp of Object.values(this.$options.components)) {
              insertStyles(comp.styles)
            }
          }
        },
        unmounted() {
          this.__style?.remove()
        },
      })

      const inst = getCurrentInstance()
      Object.assign(inst.appContext, app._context)
      Object.assign(inst.provides, app._context.provides)
    },
  })

代码App.ce.vue,我在其中注册和使用prop:

<template>
  <div id="app">
    <p>{{ title }}</p>
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
    <main>
      <router-view />
    </main>
  </div>
</template>
<script>
export default {
  name: 'App',
  props: {
    title: String,
  },
}
</script>

代码index.html,我在其中设置属性title的值:

<app-root title="hello"></app-root>

收到错误消息:

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

完整演示项目 here

最佳答案

由于 App 组件被包装在 defineCustomElementWithStyle 中,因此包装器的 props 应在以下范围内传递给 App: setup().

  1. 将组件的 props 复制到包装器的 props 中:

  2. 将包装器的 render 属性移至 setup() 的返回值中。

  3. setup()props 参数传递给 App 的渲染 (h() 接收 props 作为其第二个参数)。

export const defineCustomElement = (component, { plugins = [] }) =>
  VueDefineCustomElement({
    props: component.props, 1️⃣
    // render: () => h(component), 2️⃣
    setup(props 3️⃣) {
      ⋮
      return () => h(component, props 3️⃣)
    }
  })

demo

关于javascript - 如何在新的vue自定义元素中正确注册和使用props?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69834745/

相关文章:

javascript - vue.js 未渲染组件

npm - 使用使用 TailwindCSS 的组件库

javascript - 如何根据复选框设置另一个表单字段?

javascript - ES6 类多重继承

typescript - 将数据传递给根 Vue 类组件

javascript - NativeScript-vue 应用程序中的 Laravel 身份验证,有人做过吗?

vue.js - Vuetify v-data-table 仅居中对齐一列

javascript - 在变量函数中调用 Javascript 函数[解决]

algorithm - 反向打印数字系列的Javascript程序

javascript - 更改存储中的值后如何调用组件中的函数?