Vue3 has been released for some time now. There are a lot of articles about Vue3, including the composite API, Typescript, source code, etc., but there are a lot of articles about global API components, so let’s share how to develop and use global API components
Let’s first review the implementation in VUe2
Take an alert component as an example
<template> <transition name="alert-fade" @after-leave="destroyElement"> <div class="alert" v-if="show"> <div class="ht-modal" @click="close"></div> <div class="alert-box" :style="'width:'+ width"> <div class="alert-header"> <i class="iconfont icon-error alert-close" @click="close"></i> </div> <div class="alert-body"> {{ message }} </div> <div Class ="alert-footer"> <slot name="footer"> <div class="alert-btn" @click="close"> Set </div> </slot> </div> </transition> </template> <script> export default { name: 'Alert', props: { width: { type: String, required: false, default: '30%', }, msg: { type: String, required: false, default: () => 'some message' }, handleClose: { type: Function, required: false, default: null } }, data () { return { show: true, message: this.msg } }, methods: { close($event) { this.show = false this.$emit('close', $event) }, destroyElement() { this.handleClose && this.handleClose() } }, } </script>Copy the code
The file name is alert.vue. Create the alert.js file in the same directory
import Main from './alert.vue'
const Alert = {}
Alert.install = Vue => {
let instance
let show = false
let AlertConstructor = Vue.extend(Main)
const loadAlert = options => {
if ( show ) return
let { handleClose } = options
options.handleClose = () => {
handleClose && handleClose()
show = false
}
instance = new AlertConstructor({
propsData: options
})
const component = instance.$mount()
document.body.appendChild(component.$el)
}
Vue.prototype.$alert = loadAlert
}
export default Alert
Copy the code
The key here is to invoke the extend method on Vue to inherit the Alert component property. Of course, you can also create a new Vue example to achieve the same effect, because the example is created by instantiating the Vue constructor, so binding the API methods to the constructor’s prototype object can achieve inheritance
import Alert from 'alert.js' import Vue from 'vue' Vue.use(Alert) new Vue(...) .$mount(el)Copy the code
Once registered, we can call this method from anywhere to render the component through this
This.$alert({width: '50%', MSG: 'this is a global API component ', handleClose: function() {console.log(' I was shut down!! ')}})Copy the code
So that’s a brief review of how to develop and use an API component in Vue2. What’s the difference in Vue3 implementation
In Vue3, the createApp method is used to return the instance object, and the extend method is cancelled. We mentioned above that we can create a new instance object to implement this method
import { createApp } from 'vue' import Main from './alert.vue' const Alert = {} Alert.install = app => { let instance let container = null const loadAlert = options => { if (container) return let { handleClose } = options options.handleClose = () => { handleClose && handleClose() document.body.removeChild(container) instance.unmount() container = null } container = document.createElement('div') instance = createApp(Main, options) instance.mount(container) document.body.appendChild(container) } app.config.globalProperties.$alert = loadAlert } export default AlertCopy the code
$mount (dom) = $mount (dom) $mount (dom) = $mount (dom) $mount (dom) = $mount (dom) 3 is added to the global properties of the Config object of the instance application, and the following registration and use methods are completely the same
Further down the line, one of the most important features of Vue3 is the composite API, which gives us great flexibility to write code, The main reason for using the Vue component is to take advantage of its ability to render the DOM in a responsive manner so that rendering operations can be done easily and efficiently. The main apis are createVnode, H and Render, and we can use these apis to achieve the same effect
import { h, createVNode, render } from 'vue'
Copy the code
The h and createVnode methods both return a VNode object, which has the same effect or can be used interchangeably
const vnode = h(Main, options)
const vnode = createApp(Main, options)
Copy the code
Finally we need to call the Render method to pass in the vNode and the parent element to mount
render(vnode, container)
Copy the code
And finally our code can be changed to
import { h, createVNode, render } from 'vue' import Main from './alert.vue' const Alert = {} Alert.install = app => { let container = null const loadAlert = options => { if (container) return let { handleClose } = options options.handleClose = () => { handleClose && handleClose() document.body.removeChild(container) container = null } container = document.createElement('div') const vnode = h(Main, options) //const vnode = createVNode(Main, Options) / / can also use createVnode method replacing h render (vnode, container) document. The body. The appendChild (container)} app.config.globalProperties.$alert = loadAlert } export default AlertCopy the code
Create a VNode, call render, and mount it to the container. Create a vNode, call render, and mount it to the container. So that’s one of the advantages of a composite API, where I import whatever I need to do to avoid code redundancy, right
Finally, we analyze the implementation of global call mode of 2 and 3. In 2, through the inheritance of prototype chain, API methods are exposed on the prototype object of the Vue constructor, and singleton is applied for global call. 3, the Proxy agent, by rewriting reading behavior, enclosing $alert access to is in fact the app. Config. GlobalProperties. $alert method