原文地址:https://blog.csdn.net/qq_39953537/article/details/110437554

vue3 中如何像 vue2 的 extend 一样挂载未挂载的组件,拿到标签本身($el)

简介:最近在用 vue3 写个新项目,需要挂载自定义的组件,但是发现 vue3 中不再支持 extend 方法了,于是查看了 vant 最新的源码,发现里面有类似实现,特此提炼总结出来。

1.vue2 写法

 1 <!DOCTYPE html>
 2 <html lang="en">
 3   <head>
 4     <meta charset="UTF-8" />
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 6     <title>Document</title>
 7     <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
 8   </head>
 9 
10   <body>
11     <div id="app"></div>
12   </body>
13 
14   <script>
15     // 创建构造器
16     const DemoConstructor = Vue.extend({
17       render(h, props) {
18         return h('div', { style: { fontSize: '24px' } }, '你好' + this.name)
19       }
20     })
21     // 创建 DemoConstructor 实例
22     const instance = new DemoConstructor({ data: { name: '小米' } })
23     // 手动地挂载一个未挂载的实例。
24     instance.$mount()
25     console.log(instance.$el)
26   </script>
27 </html>

2、vue3

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://unpkg.com/vue@3.0.2"></script>
  </head>

  <body></body>

  <script>
    const { createApp, h, ref } = Vue
    // vant  源码中是直接用的setup返回的jsx,我这里用的是vue的cdn用法,没有环境支持
    const app = createApp({
      setup(props) {
        const name = ref('小米')
        return { name }
      },
      render() {
        return h('div', { style: { fontSize: '24px' } }, '你好' + this.name)
      }
    })
    // 提供一个父元素
    const parent = document.createElement('div')
    //mount方法不再像vue2一样支持未挂载的实例,必须得挂载,即必须得给参数
    const instance = app.mount(parent)
    console.log(instance)
    console.log(instance.$el)
  </script>
</html>

3.(补充) 在应用之间共享配置

`

import { createApp as createBaseApp, Component } from 'vue'
import router from './router'
import store from './store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import { createI18n } from 'vue-i18n'

import Foo from './Foo.vue'
import Bar from './Bar.vue'

const messages = {
  en: {
    message: {
      message1: 'hello world -1',
      message2: 'hello world -2'
    }
  },
  zh: {
    message: {
      message1: '你好,世界 -1',
      message2: '你好,世界 -2'
    }
  }
}

const i18n = createI18n({
  locale: 'en',
  fallbackLocale: 'en',
  messages
})

export const createApp = (options: Component, rootProps?: Record<string, unknown> | null) => {
  const app = createBaseApp(options, rootProps)
  app.use(ElementPlus).use(i18n).use(router).use(store)
  return app
}

const app2 = createApp(Foo).mount('#foo')
const app3 = createApp(Bar).mount('#bar')