Vue3 的官方文档中大致介绍了这三种全局API。但是我看完过后,对于一些点还是处于一个比较懵逼的状态,于是自己去查阅了一些资料以及手写代码去尝试,才渐渐领悟了过来。
在看官方文档期间,我把自己在脑海中疑惑的问题整理了一下,然后写在了这篇文章中,并从网上和实践中去找寻到了一些答案。
咱们先来看文档中对于这三个全局API的介绍:
文档中第一句话很容易看懂,说白了就是从实现上看,用了或者跟不用这个api没多大区别~~但是呢,第二句话说的好像又有一些区别,不过我没太看懂。。。于是我自己的第一个问题就来了:
这个API一般是在ts或者tsx文件中使用的,所以,当我们创建了一个这种类型的文件后,它是不知道我们是要去写 vue 实例代码的,所以在这种情况下,我们需要defineComponent来帮我们做内部的一些options的提示,我们可以看一个使用了defineComponent和没有使用defineComponent的例子:
当然这背后的原理是利用 TypeScript 定义了defineComponent 参数类型实现的。
拿 setup 来说,defineComponent 可以为 setup 函数的 props 传参做出正确的类型推断,看下图:
如果没有使用 defineComponent 的话,是没有办法推断出来的,需要自己显式地去定义类型。
这也是官方文档中所说的,我在代码中尝试了一下,发现确实可以在其返回的构造函数中去定义一些钩子和属性等,如下图:
这就是目前我对这个API的一些理解吧~后续有新发现再补充
这个API主要是用来定义异步组件的,先来看下官方文档的介绍:
其实关于这个API的话,我个人觉得官方文档中介绍得已经非常清楚了,就是用来定义一个异步组件,然后利用Promise将其在应该渲染的时候加载出来。
关于其高阶用法的相关配置,大家可以去文档中自寻查找。
https://v3.cn.vuejs.org/api/global-api.html#defineasynccomponent
最开始看到这个API的名字的时候,我有点懵,以为是和component api相同的功能:创建一个自定义组件就完事儿了。结果忽略了最后一个单词:Element。
这个API是用来创建原生的自定义元素的,由它创建出来的组件经过注册可以在其他框架(不只是Vue)甚至脱离框架去使用。我们先来看看它的官方介绍:
官方文档中介绍得非常简单。在文档中引出了一个原生API的概念:customElements。关于这个 API ,主要作用就是它能够使开发者能够将HTML页面的功能封装为 custom elements(自定义标签)。大家有兴趣可以去MDN上看看:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_custom_elements
言归正传,在这里,我抛出了自己脑海里的第二个问题:
先来看看是否有同样的状态管理能力:
import { createApp, h, defineCustomElement, ref } from 'vue'
const app = createApp(App)
const MyVueElement = defineCustomElement({
setup () {
const count = ref(0)
return () => h('div', {
onClick: () => count.value++
}, `点击${count.value}`)
}
})
customElements.define('my-vue-element', MyVueElement)
我按照文档中所说的方式创建并注册了一个原生自定义元素 my-vue-element,然后我现在打开浏览器,直接在浏览器控制台中输入这两行代码:
然后我看到在页面中确实渲染出了我们刚刚注册的组件,并且点击元素,其设置的count会正常增加,说明它确实是实现了自身的状态管理功能的:
OK,自身状态管理没问题,那么再来看看是否支持事件。我们需要稍微修改一下代码,然后先测试一下,普通的Vue 组件的自定义事件是否能跑通,防止代码写错了:
import { createApp, h, defineComponent } from 'vue'
const app = createApp(App)
const MyVueElement = defineComponent({
props: {
title: {
type: String,
required: true
}
},
emits: ['update:title'],
setup (props, { emit }) {
return () => h('div', [
h('div', props.title),
h('input', {
value: props.title,
onInput: (e: any) => emit('update:title', e.target.value)
})
])
}
})
app.component('MyVueElement1', MyVueElement)
OK,普通的Vue自定义组件没问题,接下来看看 defineCustomElement 创建的原生自定义元素是否支持:
import { createApp, h, defineCustomElement } from 'vue'
const app = createApp(App)
const MyVueElement = defineCustomElement({
props: {
title: {
type: String,
required: true
}
},
emits: ['update:title'],
setup (props, { emit }) {
return () => h('div', [
h('div', props.title),
h('input', {
value: props.title,
onInput: (e: any) => emit('update:title', e.target.value)
})
])
}
})
customElements.define('my-vue-element', MyVueElement)
结果得出,由 defineCustomElement 创建出来的组件没办法支持事件处理的。
OK,三种API差不多介绍完啦~目前我只研究到了这个程度,如大佬们看到有问题的地方,请多多指教哈