vue3 中如何像 vue2 的 extend 一样挂载未挂载的组件,拿到标签本身($el)
简介:最近在用 vue3 写个新项目,需要挂载自定义的组件,但是发现 vue3 中不再支持 extend 方法了,于是查看了 vant 最新的源码,发现里面有类似实现,特此提炼总结出来。
1.vue2 写法
1 |
|
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 写法
1 |
|
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://unpkg.com/vue@3.0.2"></script> |
8 | </head> |
9 | |
10 | <body></body> |
11 | |
12 | <script> |
13 | const { createApp, h, ref } = Vue |
14 | // vant 源码中是直接用的setup返回的jsx,我这里用的是vue的cdn用法,没有环境支持 |
15 | const app = createApp({ |
16 | setup(props) { |
17 | const name = ref('小米') |
18 | return { name } |
19 | }, |
20 | render() { |
21 | return h('div', { style: { fontSize: '24px' } }, '你好' + this.name) |
22 | } |
23 | }) |
24 | // 提供一个父元素 |
25 | const parent = document.createElement('div') |
26 | //mount方法不再像vue2一样支持未挂载的实例,必须得挂载,即必须得给参数 |
27 | const instance = app.mount(parent) |
28 | console.log(instance) |
29 | console.log(instance.$el) |
30 | </script> |
31 | </html> |
3.(补充) 在应用之间共享配置
JS 用户把里面的类型删除就可以了
1 | import { createApp as createBaseApp, Component } from 'vue' |
2 | import router from './router' |
3 | import store from './store' |
4 | import ElementPlus from 'element-plus' |
5 | import 'element-plus/dist/index.css' |
6 | import { createI18n } from 'vue-i18n' |
7 | |
8 | import Foo from './Foo.vue' |
9 | import Bar from './Bar.vue' |
10 | |
11 | const messages = { |
12 | en: { |
13 | message: { |
14 | message1: 'hello world -1', |
15 | message2: 'hello world -2' |
16 | } |
17 | }, |
18 | zh: { |
19 | message: { |
20 | message1: '你好,世界 -1', |
21 | message2: '你好,世界 -2' |
22 | } |
23 | } |
24 | } |
25 | |
26 | const i18n = createI18n({ |
27 | locale: 'en', |
28 | fallbackLocale: 'en', |
29 | messages |
30 | }) |
31 | |
32 | export const createApp = ( |
33 | options: Component, |
34 | rootProps?: Record<string, unknown> | null |
35 | ) => { |
36 | const app = createBaseApp(options, rootProps) |
37 | app.use(ElementPlus).use(i18n).use(router).use(store) |
38 | return app |
39 | } |
40 | |
41 | const app2 = createApp(Foo).mount('#foo') |
42 | const app3 = createApp(Bar).mount('#bar') |
参考链接
1.https://github.com/youzan/vant/blob/v3.0.0-beta.10/src/dialog/index.js
2.https://github.com/youzan/vant/blob/v3.0.0-beta.10/src/utils/mount-component.ts