A common scenario when writing business is that you need to call the same form on different pages. The common interaction is to display the form in the form of a pop-up window, but it is sometimes troublesome to repeatedly introduce the form component on each page. There are two solutions:
Of course, the business Dialog component must have a set of specifications. Props receives an onOk and onCancel callback, and defines a visible property in data. <template> <el-dialog :title="title" :visible.sync="visible" append-to-body> <!-- Business code --> </el-dialog> </template> <script> export default { props: ['onOk', 'Other properties required by the business'], data() { return { visible: false } } } </script> Vue2 WritingIn Vue2, I personally feel that it is easier to write it as a plug-in. The implementation is as follows. Some operations are done using mixins to decouple it from the business. The downside is that the component is inserted dynamically, and Vue devtools needs to be refreshed to see the component. const mixin = { mounted() { document.body.appendChild(this.$el) this.visible = true }, watch: visible(value) { // Destroy the instance after the animation ends if (value === false) { setTimeout(() => { this.$destroy() if (this.$el && this.$el.parentNode) { this.$el.parentNode.removeChild(this.$el) } }, 400) } } } } export default { install(Vue, options) { Vue.prototype.$dialog = (name, props) => { // Relative to the location of the plugin, import('../components/dialogs/' + name) will be checked during static compilation .then(module => { const component = module.default const mixins = component.mixins || [] mixins.push(mixin) // Automatically open, dynamically mix in lifecycle functions and destruction operations component.mixins = mixins return Vue.extend(component) }) .then(Dialog => { const dialog = new Dialog({ propsData: props || {} }) dialog.$mount() }) } } } The calling method is as follows. Note that the this pointer of the onOk callback can be avoided by using an arrow function. this.$dialog('GroupEdit.vue', { type: 'edit', group: {}, onOk: () => { this.freshList() } }) Vue3 plugin version writingUnfortunately, due to the upgrade of Vue3, Vue.extend is gone, $mount is gone, and components can only be rendered in the application. The data between each application is isolated, so plug-ins and the like need to be reintroduced. At the same time, if you want to interact, it is also troublesome. It should be possible to introduce the same vuex instance, but I haven't tried it. In order to reduce coupling, you can only create a new application to mount the rendering import { createApp, defineComponent } from 'vue' import ElementPlus from 'element-plus' const mixin = { mounted() { document.body.appendChild(this.$el) this.visible = true }, watch: visible(value) { // Destroy the instance after the animation ends if (value === false) { setTimeout(() => { this.$.appContext.app.unmount() }, 400) } } } } export default { install(app) { app.config.globalProperties.$dialog = (name, props) => { import('../components/dialogs/' + name) .then(module => { const component = module.default let mixins = component.mixins || [] mixins.push(mixin) component.mixins = mixins return defineComponent(component) }) .then(Dialog => { const app = createApp(Dialog, props || {}) app.use(ElementPlus) app.mount(document.createElement('div')) }) } } } Vue3 dynamic component writingIn Vue3, the plugin version also meets the requirements, but it is a completely new application. It is still a bit troublesome to access this.$root, vuex, and router in the business. Therefore, dynamic components are better in Vue3. Introduce dynamic component in the root component and define some control variables <template> <router-view></router-view> <component :is="currentDialog" v-bind="currentDialogProps" /> </template> <script> export default { data() { return { currentDialog: null, currentDialogProps: null } } } </script> If you call this.$root.$dialog(), it looks too ugly. In fact, you can still manually simulate the effect of the plug-in. const app = createApp(App) const vm = app.mount('#app') initDialog(app, vm) function initDialog(app, vm) { const mixin = { mounted() { this.visible = true }, watch: visible(value) { // Destroy the instance after the animation ends if (value === false) { setTimeout(() => { this.$root.currentDialog = null this.$root.currentDialogProps = {} }, 400) } } } } app.config.globalProperties.$dialog = (name, props) => { import('./components/dialogs/' + name).then(module => { const component = module.default let mixins = component.mixins || [] mixins.push(mixin) component.mixins = mixins // defineComponent(component) is not needed vm.currentDialog = markRaw(component) vm.currentDialogProps = markRaw(props || {}) }) } } Some hacky ways to writeVue3 component instance gets the application instance vm.$.appContext.app == app Vue3 application instance gets the component instance. Note that _instance is only accessible in the dev environment. app._instance.proxy == vm app._instance.root.proxy == vm app._instance.ctx.$root == vm There are still some tricks, but it’s best not to use them. const app = createApp(App) const vm = app.mount('#app') if (process.env.NODE_ENV === 'production') { app._instance = { proxy: vm, root: { proxy: vm }, ctx: { $root:vm } } } This is the end of this article about Vue's implementation of Dialog encapsulation. For more relevant Vue Dialog encapsulation content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: Linux file system operation implementation
>>: Mysql error: Too many connections solution
Preface Recently our server was attacked by hacke...
<br />When thoughts were divided into East a...
This article shares the specific code for WeChat ...
Document mode has the following two functions: 1. ...
In the recent project, we need to create an effec...
Preface: When designing a table in MySQL, MySQL o...
After installing the database, if you accidentall...
The mathematical expression calc() is a function ...
The task of concurrency control in a database man...
If you want to understand React Router, you shoul...
1. Install libfastcommon-1.0.43. The installation...
Table of contents DOM node Element node: Text nod...
Sometimes the theme of a project cannot satisfy e...
This article shares the installation method of My...
Preface In most projects, you will encounter onli...