vue functional pop-up window
I have read a lot of articles before, and I always wanted to make my own, mainly based on secondary packaging and Vue.extend. I will share the pitfalls I stepped on and how to deal with them.
The main functions are as follows:
- support title
- Load child component rendering
- Provides a communication mechanism callback
- Promise
Journey
Me: Today I want to make a showDialog
function popup window
Crazy research (all kinds of Baidu), 1 hour later… I rely on, it seems that there is nothing I want, look through the api Vue.extend to create a subclass, okay, I will use you
One operation, display and close showDialog
has been implemented… But what about loading subcomponents? Do I pass a path and mount it using import(path)
with dynamic components?
showDialog({<!-- --> title:'Title' path: 'demo' })
If you have a thought, you will report an error. Import does not support dynamic variables. The path is undefined. Oh, and require()
can be used. Hey, now you can dynamically load subcomponents. Let’s test it and submit it. commit -m ‘feat complete functional popup’
Day 2
Supervisor: Why can’t my uni project run anymore?
Me: I started it with a knowing smile (obviously I don’t know that I caused the problem!) What happened to the node stack overflow, it was fine before I submitted the functional pop-up window, but it didn’t work. Damn, delete my code, it’s ok started
Inside of me: what rubbish performance
Me: Tell everyone, it seems to be a problem with the pop-up window, I have registered him from the global, you update the code
evening
My heart: Why did I report an error, so I started to review, and I remembered that there was an article before. The difference between require()
and import()
is roughly synchronous and asynchronous loading, import()
only loads relevant content when calling and is lazy. In router
, we use lazy loading of routes because of import()
. require()
is different. It will load the content synchronously from the beginning. uni
can’t be started. I will load the components synchronously, and the related dependencies will be parsed, resulting in an overflow problem. This is also a problem. The reason why I didn’t plan to use require()
at the beginning, of course, require()
is still very commonly used when loading some pictures, this is because of its synchronous loading feature To, and then analyze uni
compiled error webpack
related, I tried to configure require()
on-demand reference configuration but I did not seem to be successful, So let me explain why using import(path)
fails, because a variable webpack4
set by path
belongs to static path
will cause the parsing to fail. To sum up the above problems, you can come up with a solution. I don’t use path
. I pass a uiLoader
function, which is ()=>import('demo')
It’s like lazy loading of routes, but after debugging, this is indeed feasible
After a lot of tossing, I will show you how to realize it, based on the secondary packaging of uview u-modal
Implementation
There must still be a vue file
xxx-modal.vue
<template> <view> <u-modal :show-title="false" @confirm="confirm" :title="title" v-model="model.visible" :show-cancel-button="true" :show-confirm-button="true" > <component:is="component" v-if="component"></component> </u-modal> </view> </template> <script> export default {<!-- --> name: 'Tsl-Dialog', props: {<!-- --> uiLoader: {<!-- --> type: Function, }, title: {<!-- --> type: String, }, onClose: {<!-- --> type: Function, }, onSuccess: {<!-- --> type: Function, }, }, data() {<!-- --> return {<!-- --> component: null, model: {<!-- --> visible: false, }, emitter: null, }; }, methods: {<!-- --> async on() {<!-- --> this.model.visible = true; this.uiLoader().then(() => {<!-- --> this.component = this.uiLoader; }); }, confirm() {<!-- --> \t\t\t\t// Data collection this.onSuccess(this.emitter); }, cancel() {<!-- --> this. onClose(); }, }, created() {<!-- -->}, mounted() {<!-- --> // cannot use import() uni compilation should be using webpack4 does not support variable input uni.$on('POST_ACTION', (v) => {<!-- --> this. emitter = v; }); }, beforeDestroy() {<!-- --> uni.$off('POST_ACTION'); }, }; </script> <style lang="scss" scoped></style>
Description:
When it is on, mount the component on the communication by executing uiLoadeer
or use bus
because it needs to be Promise
, so my internal components receive POST_ACTION stores the information and executes the callback
showDialog.js
// Because it is the final version, some parameters can be ignored import Modal from './modal.vue'; import Vue from 'vue'; const Instance = Vue. extend(TslModal); function showDialog(props) {<!-- --> const {<!-- --> title, uiLoader, content, showButton = false, borderRadius = 30, confirmColor = '#2979ff', cancelColor = '#606266' } = props; return new Promise((resolve, reject) => {<!-- --> const dialogContext = new Instance(); // Mount the loader dialogContext.uiLoader = uiLoader; // mount props dialogContext.title = title; dialogContext. content = content; dialogContext. borderRadius = borderRadius; dialogContext.confirmColor = confirmColor; dialogContext. cancelColor = cancelColor; if (showButton) {<!-- --> dialogContext.showConfirmButton = true; dialogContext.showCancelButton = true; } // open the popup dialogContext.on(); // success button callback dialogContext.onSuccess = function (v) {<!-- --> props.onSuccess & amp; & amp; props.onSuccess(v); resolve(v); remove(); }; // mount dom document.body.appendChild(dialogContext.$mount().$el); // cancel event dialogContext.cancel = function () {<!-- --> dialogContext. close(); remove(); }; // remove mount dom function remove() {<!-- --> document.body.removeChild(dialogContext.$mount().$el); } }); } export default showDialog;
Description:
Introduce the modal component through Vue.extend()
and then construct an instance. If you are not too familiar with the internal source code, you can add it one by one, using Promise
There is a confirmation and cancel button at the bottom of the package pop-up window. When you click Confirm, execute resolve(v)
and send the corresponding data. Remember to remove the dom< when closing /strong> The order is from top to bottom. We manually call on
and open the pop-up window and load the component at the same time. Because we mounted uiLoader
at the top at the beginning, soon
already exists when it is executed. Finally, export can be used to import or mount the prototype
How to use
import showDialog from '@/components/modal/showDialog'; showDialog({<!-- --> title: 'I am a pop-up window', showButton: true, borderRadius: 0, content: '123', uiLoader: () => import('./demo.vue'), uni.$emit('POST_ACTION', 'value'); in demo onSuccess: (res) => {<!-- --> console.log('postaction1', res); // value }, }).then((res) => {<!-- --> console.log('postaction', res); // value }); content is still supported and uiLoader priority, I made a judgment internally
Conclusion:
As a bug repair engineer, I realized that my knowledge is still not enough in this implementation. Through this problem, I slowly analyzed and finally dealt with it. In fact, the process is still a bit difficult. Isn’t it the employment winter recently? I hope you can still put your mind at ease and always keep yourself at the edge. I’m pretty good at it, and I can only learn a little bit every day. If I can surpass 50% of my peers, I will be satisfied. Knowledge reserves are still very important, so I should probably prepare more A few k more than the current salary, so that you will be competitive. Finally, I would like to send you a sentence: There is always a chance or two in the world, fill my thousand and eight thousand dreams