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
  1. The close
    setup(props){...const close = () = > props.colseCallback && props.colseCallback()
    }
Copy the code
  1. 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?