Vue el-dialog realizes infinite nesting of pop-up windows (click on the pop-up window to pop up a new pop-up window, you can always click on it)

Usage scenario:

It is required to click on the data to display the pop-up window, click on the data in the pop-up window to display a new pop-up window, and the pop-up window inside can continue to click on the new pop-up window, and the pop-up window can be nested unlimitedly

Why not use el-dialog’s append-to-body?

Reason: Because some pop-up windows are both the parent pop-up window and the bullet window, an error will be reported when using it, and a loop nesting error will be reported

Effect image:

Unlimited clicks and unlimited nesting

Code details:

Step 1: Create a new commonData.js and put it in the utils folder

Encapsulate js method

commonData.js file

import Vue from "vue";
let common = {};
if (window) window. common = common;
/**
 *
 * The common object places all common methods
 * common.dialog() is the method to call the pop-up box
 */
common.dialog = function(option) {
  var m = document. createElement("div");
  document.getElementsByTagName("body")[0].appendChild(m);
  var v = "";
  let template = "";
  template = `<div class="w680" v-if="show">
    <el-dialog
    :title="title"
    :visible.sync="show"
    width="${option.DialogWidth ? option.DialogWidth : "70%"}"
    top="${option.Dialogtop ? option.Dialogtop : "15vh"}"
    :class="parentClass"
    :close-on-click-modal="false"
    :close-on-press-escape="false" :before-close="handleClose" @close="close">
      <child v-on:callback="callback" ref="childrenRef" @closeDialog="closeDialog">
      </child>

      <span style="display: flex; justify-content: center; align-items: center" slot="footer" class="dialog-footer" v-if='${
        option.btnShow.show
      }'>
        <el-button size="small" style="padding: 8px 25px;
          background: #089d81;
          color: #fff;
          border: 1px solid #089d81;" v-if='${
            option.btnShow.showSubmit
          }' @click="submit">
         ${option.btnShow.showSubmitText || "OK"}
        </el-button>
        <el-button size="small" style="padding: 8px 25px;
        background: #089d81;
        color: #fff;
        border: 1px solid #089d81;" @click="show = false" v-if='${
          option.btnShow.showCancel
        }'>
         ${option.btnShow.showCancelText || "Cancel"}
        </el-button>
      </span>
     </el-dialog>
    </div>
    `;
  v = new Vue({
    el: m,
    data: function() {
      return {
        title: option.title,
        type: option.type,
        style: option. style,
        show_close: true,
        show: true,
        parentClass: option. parentClass,
        initData: option.initData,
      };
    },
    template: template,
    mounted: function() {
      this. $nextTick(() => {
        this.$refs.childrenRef.init('The value you want to pass');
      });
    },
    methods: {
      closeDialog() {
        this. show = false;
      },
      // Confirm button
      submit(){
        this.$refs.childrenRef.submit('submit')
      },
      handleClose(done) {
        var aa = document. getElementsByClassName("w680")[1];
        if (!aa) {
          var bb = document. getElementsByClassName("v-modal")[0];
          if (bb) {
            document.getElementsByTagName("body")[0].removeChild(bb);
          }
        }
        if (option. close) {
          option. close();
        }
        done();
      },
      close() {
        var aa = document. getElementsByClassName("w680")[1];
        if (!aa) {
          var bb = document. getElementsByClassName("v-modal")[0];
          if (bb) {
            document.getElementsByTagName("body")[0].removeChild(bb);
          }
        }
        if (option. close) {
          option. close();
        }
      },
      callback(result) {
        if (option._source != null) {
          option.callback.call(option._source, result);
          this. show = false;
          return;
        }
        //If the type is not passed or the type is equal to close or cancel, close the popup box directly
        if (!result.type || result.type == "close" || result.type == "cancel") {
          this. show = false;
        } else if (result.type == "sure") {
          //If type is equal to sure, call the callback function passed by parent
          this. show = false;
          if (option. callback) {
            option. callback(result. data);
          }
        }
      }
    },
    components: {
      child: option.component
    }
  });
  return v;
};

export default common;

Step 2: Create a vue file

Create a folder testDialog folder Create a folder according to your own needs (this is for my demonstration, you can create it yourself according to your own project)

index.vue file

html part

<template>
  <div
    style="width:200px;height:200px;background:#eee;color:#000;"
    @click="openDialog"
    class="div"
  >
    Click me to open the infinite pop-up tour
  </div>
</template>

js part

<script>
import common from "@/utils/commonData.js";
import dialog from "./components/dialog.vue";
export default {
  data() {
    return {};
  },
  methods: {
    openDialog() {
      var obj = {
        aa: "1"
      };
      let option = {
        title: "I am a pop-up window 0000000000000", //Title
        initData: obj, // the passed value
        type: "addInspection", //Multiple pop-up windows with different requirements can be distinguished by type
        DialogWidth: "60%", //The width of the pop-up window is 70% by default
        Dialogtop: "3vh", //The height of the pop-up window from the top is not written as 15vh by default
        btnShow: {
          show: true, //Whether to display the button
          showSubmit: true, //Whether to show the OK button
          // showSubmitText: "", //Confirm button text replacement (optional, can be written or not, if not written, the default is OK)
          showCancel: true //whether to show the cancel button
          // showCancelText: "" //Cancel button text replacement ((not required, can be written or not, if not written, the default is cancel)
        },
        parentClass: "addInspection", //class name
        component: dialog // component
      };
      common.dialog(option);
    }
  }
};
</script>

css part

<style>
.div {
  display: flex;
  align-items: center;
  cursor: pointer;
  justify-content: center;
  position: fixed;
  left: calc(50% - 100px);
  top: 30%;
}
</style>

dialog.vue file

html part

<template>
  <div class="dialogDiv" @click="openDialog">
    I am the pop-up window 000000000000000000
  </div>
</template>

js part

<script>
import dialogOne from './dialogOne.vue'
export default {
  data() {
    return {
      property: "value"
    };
  },
  methods: {
    init(data, dataOne, dataTwo) {
      console.log(data, dataOne, dataTwo);
    },
    openDialog() {
      var obj = {
        aa: "1"
      };
      let option = {
        title: "I am the pop-up window 1111111111111111111", //title
        initData: obj, // the passed value
        type: "addInspection", //Multiple pop-up windows with different requirements can be distinguished by type
        DialogWidth: "60%", //The width of the pop-up window is 70% by default
        Dialogtop: "3vh", //The height of the pop-up window from the top is not written as 15vh by default
        btnShow: {
          show: true, //Whether to display the button
          showSubmit: true, //Whether to show the OK button
          // showSubmitText: "", //Confirm button text replacement (optional, can be written or not, if not written, the default is OK)
          showCancel: true //whether to show the cancel button
          // showCancelText: "" //Cancel button text replacement ((not required, can be written or not, if not written, the default is cancel)
        },
        parentClass: "addInspection", //class name
        component: dialogOne // component
      };
      common.dialog(option);
    },
    submit() {
      this.$emit("closeDialog");
    }
  }
};
</script>

css part

<style lang="scss">
.dialogDiv {
  width: 200px;
  height: 200px;
  background: #000;
  color: #fff;
}
.el-dialog__header {
  padding: 10px 20px 10px;
  background-color: #19a199;
}
.el-dialog__header .el-dialog__title {
  font-size: 15px;
  color: #ffffff;
  font-weight: 700;
}
.el-icon-close: before {
  color: #fff;
}
.el-dialog__body {
  padding: 10px 20px;
  height: 50vh;
}
.el-dialog__headerbtn {
  top: 15px;
}
// You can write your own styles
// .dialog-footer {
// .el-button {
// padding: 8px 25px !important;
// background: #089d81;
// color: #fff;
// border: 1px solid #089d81;
// }
// }
// .el-dialog__body {
// padding-top: 10px;
// height: 50vh;
// overflow-y: auto;
// }
// .el-dialog__headerbtn .el-dialog__close {
// color: #fff;
// }
</style>

The remaining two files can be created by yourself according to this. If you want to loop infinitely, write the pop-up window of the last file to the first one, and you can nest unlimitedly!

It’s not easy to develop, if you like it, please pay attention and like it, thank you!