Background:
The company's front-end technology framework looks forward, VUe2.x --> Vue3.0. The business side wants to keep the original UICopy the code
The preparatory work
- ELDialog (ELDialog
- Vue3.0 official website component registration and CompositionApi Vue Chinese documents
- Vue – cli upgrade Vue/cli
Third party component registration – XDialog
- The install method is required when a component is injected into a Vue instance (use when the root component is created).
// main.js
import { createApp } from 'vue'.import XDialog from '@/components/XDialog/index'
createApp(App)
.use(XDialog) // Inject the component
.use(...)
// @/components/XDialog/index.js. I'm going to omit one here20A few lines// When exporting, the install method is given
export default {
install: (App) = > {
// Why provide/inject it?
App.provide('XDialong', MyDialog)
// You can also use the following method (but I will tell you: I want to make the call in script, not in template)
// app.component.ponent (xdialog.name, XDialog}}Copy the code
- Component calls
<script lang="ts">
import{... , inject }from 'vue';
export default defineComponent({
setup() {
🤷♀️🤷 port //
const $Dialog: Function = inject('XDialog') || noop;
const addSomethins = () = > {
// Note that the first few parameters are consistent with the dialog parameters in element-plus
// For more custom configurations, please continue to see 🤣
$Dialog({
title: 'new add'.width: '500px'.closeOnClickModal: false.contentComponent: defineAsyncComponent(() = > import('./Form.vue')),
confirm: (component: Component) = > {
// Component is a reference to the asynchronous component to get component parameters
console.log(component)
// If you return false in this function the popover will not close
},
cancel: () = > {}
})
}
}
})
</script>
Copy the code
- Core implementation of component secondary encapsulation 🤞🤞🤞🤞
It is important to note that the implementation of the registration is entirely based on the implementation of the element- Plus component registration, equivalent to taking someone else’s stuff, and then install their own cow *. Face the wind.
// @/components/XDialog/index.js
// Import composition-API, compsition-API, compsition-API, compsition-API, compsition-API
import { h, render } from 'vue'
import XDialog from 'XDialog.vue'
const getContainer = () = > document.createElement('div')
const initInstance = (props, container) = > {
const vnode = h(XDialog, props) // Create a VNode virtual DOM
render(vnode, container) // Render to container without hanging to the body
const $el = container.firstElementChild
document.body.appendChild($el) // Add to the body
// Return the current EL and the instance
return {
$el,
instance: vnode.component
}
}
const show = (options) = > {
const container = getContainer()
const { instance, $el } = initInstance(options, container)
const vm = instance.proxy // The vm here is a proxy for instance -- h is generated in this way.
for (const prop in options) {
// pass props (can't override private properties inside the component)
if(options.hasOwnPrroperty(prop) && ! vm.$props.hasOwnProperty(prop)) { vm[prop] = options[prop] } } vm.visible =true // Visible here is controlling the Dialog to display hidden fields - customization is also supported
return {
$el,
vm,
instance
}
}
function MyDialog (options) {
constcontext = show({ ... options,// closeCallback removes the current dialog and its parent div when the inner dialog is closed
closeCallback() {
context.vm.visible = false
setTimeout(() = > {
document.body.removeChild(context.$el)
}, 150)}}}// When exporting, the install method is given
export default {
install: (App) = > {
// Why provide/inject it?
App.provide('XDialong', MyDialog)
// You can also use the following method (but I will tell you: I want to make the call in script, not in template)
// app.component.ponent (xdialog.name, XDialog}}Copy the code
- Xdialog.vue key function
- The close
setup(props){...const close = () = > props.colseCallback && props.colseCallback()
}
Copy the code
- Confirm the function
setup(props){...// Verify that the function is executed and the component instance is exposed
const confirmHandler = async() = > {if (typeofprops.confirm ! = ='function'| | -awaitprops.confirm(dialogRef.value) ! = =false)
) {
close()
}
}
}
Copy the code
Third-party component registration – XConfirm
- Component registration and component invocation are similar to XDialog and are based on the El-Dialog component
Only the component’s show method was tampered with
- Give the relevant code directly
// @/components/XConfirm/index.async function MyConfirm (options) {
let ctx
// Why only use resolve, because you don't want to write a catch in the outer chain call
return new Promise(resolve= >{ ctx = show({ ... options,confirm() {
resolve(true)},cancel() {
resolve(false)},closeCallback() {
ctx.vm.visible = false
setTimeout(() = > {
document.body.removeChild(ctx.$el)
}, 150)}})})}export default {
install (App) {
App.provide('XConfirm', MyConfirm)
}
}
// when the business code is called
const $confirm = inject('XConfirm')
const doSomthing = () = > {
$confirm({
title: 'lift in'.message: 'Sure about chicken tonight? '.width: '400px'.top: '20vh'.closeOnClickModal: false
}).then(async (bool) => {
if(bool) { ..... Do your shit } }) }Copy the code
Third-party component registration – XMessage
- Directly on the code — you can expand yourself
// @/components/XMessage/index.function MyMessage (options) {
const delay = options.delay || 2000
constctx = show({ ... options })setTimeout(() = > {
ctx.vm.visible = false
setTimeout(() = > {
document.body.removeChild(ctx.$el)
}, 150)
}, delay)
}
export default {
install(App) {
App.provide('XMessage', MyMessage)
}
}
Copy the code
Finally: Play ball together?
I want to change company, can you recommend?