对于后台管理系统,有很多弹框的功能,这时候,我们就可以将弹框封装成一个公共组件进行复用。

1. 新建弹窗组件页

在公共组件文件夹(components)下建一个弹框组件文件夹(EditboxForm)

element plus dialog弹窗弹出点击遮罩层弹窗不关闭 vue element 弹窗组件封装_ci

<template>
	<div>
		<transition name="slide">
			<div class="editBoxFrom" v-show="editBoxFromShow">

				<div class="editBox" :class="fromClassName" :style="{width:editBoxWidth}">
					<slot name="closeBtn"></slot>
                    <!--标题-->
					<div class="title">
						<slot name="title"></slot>
					</div>
                    <!--内容-->
					<slot name="center"></slot>
                    <!--确认按钮-->
					<div class="tableBtn">
							<slot name="tableBtn"></slot>
					</div>
				</div>
			</div>
		</transition>
		<div class="editBoxBg" v-if="editBoxFromShow">
		</div>
	</div>
</template>

<script>
	export default {
		name: 'EditboxForm',
		inheritAttrs: false,
		props: {

			//是否显示
			editBoxShow: {
				type: Boolean,
				default: function() {
					return false
				}
			},

			//是否有传class,默认为空
			className: {
				type:String,
				default: function() {
					return ''
				}
			},
			widthData:{
				type:Number,
				default: function() {
					return 360
				}
			},

		},
		data() {
			return {
				editBoxFromShow: this.editBoxShow,
				fromClassName: this.className,
				editBoxWidth:this.widthData+'px'//设置弹框的宽度
			}
		},
		mounted() {
		},
		watch: {
			editBoxShow(val) {
				this.editBoxFromShow = val
			},
			className(val) {
				this.fromClassName = val
			},
			widthData(val) {
				this.editBoxWidth = val+'px'
			},

		}

	}
</script>
<style scoped>
    .editBoxBg {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        z-index: 2000;
        background-color: rgba(0, 0, 0, .6);
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .editImgBg {
        position: fixed;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        z-index: 2010;
        background-color: rgba(0, 0, 0, .6);
        display: flex;
        justify-content: center;
        align-items: center;
    }
    /*高度不固定垂直居中*/
    
    .editBoxFrom {
        position: fixed;
        z-index: 2001;
        top: 0;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    .editBox {
        width: 360px;
        max-height: 80%;
        overflow: hidden;
        overflow-y: auto;
        background: #fff;
        position: relative;
        border: 1px solid #D7D7D7;
        padding: 10px 15px;
        .closeBtn {
            position: absolute;
            right: 10px;
            top: 10px;
            color: $themeColor;
            height: 35px;
            line-height: 35px;
            cursor: pointer;
            font-size: 16px;
        }
        .title {
            border-bottom: 1px solid #D7D7D7;
            font-weight: 700;
            font-size: 18px;
            height: 35px;
            line-height: 35px;
            text-align: center;
            margin-bottom: 10px;
        }
        .el-select {
            width: 100%;
        }
        .editBoxTable {
            table-layout: fixed;
        }
        .editBoxTable td {
            padding: 5px 0;
            word-wrap: break-word;
            vertical-align: middle;
        }
        .editBoxTable tr td:first-child {
            width: 130px;
        }
        .tdCenter {
            text-align: center;
        }
        .tableBtn {
            border-top: 1px solid #D7D7D7;
        }
    }
    
    
    .imgDivBg {
        width: 80%;
        height: 80%;
        margin: 0px auto;
        position: relative;
        //      background: #fff;
        .imgDivClose {
            height: 20px;
            width: 20px;
            text-align: center;
            background: #fff;
            line-height: 20px;
            border-radius: 20px;
            border: 1px solid $themeColor;
            position: absolute;
            top: -10px;
            right: -10px;
            cursor: pointer;
        }
        .imgDiv {
            width: 100%;
            height: 100%;
            text-align: center;
        }
        .imgDiv img {
            max-width: 100%;
            max-height: 100%;
        }
        .imgDiv video {
            //          height: 100%;
            //          width: 100%;
        }
    }
    
    .slide-enter-active {
        animation-name: slideOutDown;
        animation-duration: 1s;
        animation-fill-mode: both;
    }
    
    .slide-leave-active {
        animation-name: slideInUp;
        animation-duration: 1s;
        animation-fill-mode: both;
    }
    
    @keyframes slideInUp {
        0% {
            opacity: 1;
            transform: translateY(0);
        }
        to {
            opacity: 0;
            transform: translateY(-100%);
        }
    }
    
    @keyframes slideOutDown {
        0% {
            opacity: 0;
            transform: translateY(-100%);
        }
        to {
            opacity: 1;
            transform: translateY(0);
        }
    }
</style>

2.在公共组件文件夹(components)下建一个install.js文件

element plus dialog弹窗弹出点击遮罩层弹窗不关闭 vue element 弹窗组件封装_vue.js_02

// 组件全局注册
import Vue from 'vue'
// 这些都是自己建的组件库
import EditboxForm from './EditboxForm'//弹框

// 组件库
const Components = [
    EditboxForm,
]

// 注册全局组件
Components.map((com) =>{
    Vue.component(com.name, com)
})

export default Vue

3.在main.js中引入公共组件

element plus dialog弹窗弹出点击遮罩层弹窗不关闭 vue element 弹窗组件封装_前端_03

import './components/install'

 4.在自己需要有弹窗的页面,挂载弹框(这个是我项目的整个页面,逻代码比较多,可以仔细研究一下是可以看懂的)

<template>
  <div class="sys-page">
    <div class="page-content">
      <app-search>
        <el-form
          :inline="true"
          :model="queryParams"
          class="searchForm customerAccountManage"
        >
          <el-form-item>
            <el-button type="primary" @click="addNotice">新增</el-button>
          </el-form-item>
        </el-form>
      </app-search>
      <table-mixin
        v-loading="tableData.loading"
        :pagination="pagination"
        :startRow="startRow"
        :endRow="endRow"
        :currentPage="queryParams.pageNum"
        :paginationTotal="total"
        :pageSize="queryParams.pageSize"
        @currentPageChange="currentPageChange"
      >
        <el-table :data="tableData.body" @selection-change="selectionChange" border  style="width: 100%"
                  max-height="700">
          <el-table-column
            type="selection"
            width="40"
            align="center"
          >
          </el-table-column>
          <el-table-column
            prop="serialNo"
            label="编号"
            align="center"
            width="100"
          >
            <template slot-scope="scope">
              {{scope.$index+1 +(queryParams.pageNum-1)*10}}
            </template>
          </el-table-column>
          <el-table-column
            prop="createTime"
            label="添加时间"
            align="center"
            width="220"
          ></el-table-column>
          <el-table-column
            prop="content"
            label="公告内容"
            align="center"
            min-width="220"
          >
          </el-table-column>
          <el-table-column
            prop="state"
            label="状态"
            align="center"
            min-width="220"
          >
            <template slot-scope="scope">
              <div v-if="scope.row.state == 0">未上架</div>
              <div v-if="scope.row.state == 1">已上架</div>
            </template>
          </el-table-column>
          <el-table-column
            label="操作"
            align="center"
            width="160"
            fixed="right"
          >
            <template slot-scope="scope">
              <el-button type="text" size="large" @click="putShelf(scope.row)" v-if="scope.row.state == 0"
                >上架</el-button
              >
              <el-button type="text" size="large" @click="offShelf(scope.row)" v-if="scope.row.state == 1"
                >下架</el-button
              >
              <el-button type="text" size="large" @click="editNotice(scope.row)" v-if="scope.row.state == 0"
                >修改</el-button
              >
            </template>
          </el-table-column>
        </el-table>
      </table-mixin>
    </div>
<!--    Vue动态组件, 提供了一个特殊的元素<comment>用来动态地挂载不同的组件,使用is特性来选择要挂载的组件。引入弹框组件的地方-->
    <comment
      :is="editboxName"
      @cancel="cancel"
      :propData="propData"
      @saveBox="saveBox"
    ></comment>
  </div>
</template>

<script>
import { mapState } from "vuex";
import addNotice from "./noticeMgmt/noticeCommon";
import putShelf from "../starCollectionMgmt/common/putShelf.vue";
export default {
  name: "homepageNotice",
  components: {
    addNotice,
    putShelf,
  },
  data() {
    return {
      queryParams: {
        pageNum: this.common.pageNum, //当前页
        pageSize: this.common.pageSize, //每页显示条数
      },
      total: 0, //总条数
      startRow: 0,
      endRow: 0,
      tableData: {
        loading: false,
        body: [],
      },
      pagination: false,
      editboxName: "",
      propData: {},
      multipleSelection: [],
      setId:'',//商家id
      content:''//内容修改
    };
  },

  computed: {
    ...mapState({
      roleType(state) {
        return state.auth.roleType;
      },
    }),
  },
  mounted() {
    this.getTableData();
  },
  methods: {
    //获取所有选择的项
    selectionChange(val) {
      this.multipleSelection = val;
    },
    // 获取table数据
    async getTableData() {
      let queryParams = this.queryParams;
      await this.$api.operateMgmt
        .announcementBanner(queryParams)
        .then((res) => {
          if (res.code == 200) {
            this.tableData.loading = false;
            let resData = res.data;
            this.tableData.body = resData.records;
            this.total = resData.total;
            if (this.total > 0) {
              this.pagination = true;
            } else {
              this.pagination = false;
            }
            this.startRow = resData.startRow;
            this.endRow = resData.endRow;
          } else {
            this.common.messageTipCode(res, "error");
          }
        });
    },
    //删除Banner
    deleteBtn(row) {
      console.log(row);
      this.$confirm("确定要删除该活动Banner嘛, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.deleteBanner(row);
        })
        .catch(() => {});
    },
    //删除Banner接口
    deleteBanner(row) {
      this.$api.announcementBanner.deleteBanner({ id: row.id }).then((res) => {
        let that = this;
        if (res.code == 200) {
          this.$message({
            message: "删除banner成功",
            duration: this.common.duration,
            type: "success",
            onClose: function () {
              //									window.location.reload();
              that.getTableData();
            },
          });
        } else {
          this.common.messageTipCode(res, "error");
        }
      });
    },
    //首页下架
    offShelf(row) {
      this.$confirm("确定在首页下架该藏品嘛, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.batchsoldOut(row)
        })
        .catch(() => {});
    },
    // 首页下架接口
    async batchsoldOut(row) {
      let params = {
        id: row.id,
        state: "0",
      }
      console.log(params)
      await this.$api.operateMgmt.standDown(params)
        .then((res) => {
          let that = this;
          if (res.code == 200) {
            this.$message({
              message: "下架成功",
              duration: this.common.duration,
              type: "success",
              onClose: function () {
                //window.location.reload();
                that.getTableData();
              },
            });
          } else {
            this.common.messageTipCode(res, "error");
          }
        });
    },
    //首页上架
    putShelf(row) {
      this.editboxName = "putShelf";
      this.propData.id = row.id
      this.propData.from='homepageNotice'
    },
    //新增通知
    addNotice() {
      this.propData = {
        type: 1,
      };
      this.editboxName = "addNotice";
    },
    //编辑通知
    editNotice(row) {
      this.propData = {
        type: 2,
        id:row.id,
        content:row.content
      };
      this.editboxName = "addNotice";

    },
    //点击查询按钮
    searchTableData() {
      this.queryParams.pageNum = this.common.pageNum;
      this.queryParams.pageSize = this.common.pageSize;
      this.tableData.loading = true;
      this.getTableData();
    },

    //设置时间格式
    dateFormatTime(row, column, cellValue, index) {
      const daterc = row[column.property];
      if (daterc != null) {
        return this.common.formatDateTime(daterc, "yyyy-MM-dd hh:mm:ss");
      }
    },

    //设置日期格式
    dateFormat(row, column, cellValue, index) {
      const daterc = row[column.property];
      if (daterc != null) {
        return this.common.formatDateTime(daterc, "yyyy-MM-dd");
      }
    },
    //保存后关闭弹窗
    saveBox() {
      this.multipleSelection = [];
      this.editboxName = "";
      this.getTableData();

    },
    //关闭弹窗
    cancel() {
      let that = this;
      setTimeout(function () {
        that.editboxName = "";
      }, that.common.durationBox);
    },

    //当前显示页
    currentPageChange(pageNum) {
      this.queryParams.pageNum = pageNum;
      this.getTableData();
    },



  },
};
</script>

 5.可以在自己所写表格页面文件夹里新建一个弹框页面。例如新增和修改弹框(这个页面根据自己所需要的弹框写的,只需要将插槽一一对应,写出自己的弹框样式即可)。

<template>
	<div class="platformVerify">
		<editbox-form :editBoxShow="editBoxShow">
			<div slot="title" v-if='verifyData.type==2'>
				编辑
			</div>
			<div slot="title" v-else>
				添加
			</div>
			<div slot="center">
				<table width="100%" class="editBoxTable">

					<tr>
						<td>
							公告内容
						</td>
						<td>
							<el-input type="textarea" :rows="2" placeholder="请输入公告内容" v-model="content">
							</el-input>
						</td>
					</tr>

				</table>
			</div>
			<ul slot="tableBtn">
				<li @click="save(verifyData.type)" v-preventReClick="this.common.duration">
					提交
				</li>
				<li class="cancel" @click="cancel">
					取消
				</li>
			</ul>
		</editbox-form>
	</div>
</template>
<style type="text/css">
	.platformVerify .editBoxBg .editBox {
		width: 460px;
	}

	.platformVerify th {
		background: #F2F2F2;
		height: 40px;
		line-height: 40px;
	}

	.platformVerify td {
		text-align: center;
	}

	.platformVerify .first td {
		text-align: left;
	}

	.platformVerify .editBoxTable {
		margin-bottom: 10px;
	}

	.platformVerify .el-select .el-input__inner {
		padding: 0 10px;
	}
</style>
<script>
	export default {
		name: 'noticeCommon',
		props: {
			propData: {
				default: function() {
					return {}
				}
			},
		},
		data() {
			return {
				verifyData: this.propData,
				editBoxShow: false,
        content:'',//公告内容
			}
		},
		mounted() {
			this.editBoxShow = true
      this.getcontent()
		},
		methods: {
      getcontent(){
        if(this.verifyData.type==2){
          this.content=this.verifyData.content
        }
      },
			save(type) {
				if(event.target.disabled) {
					if(document.getElementsByClassName('el-message--warning').length) return
					this.common.messageTip("操作太频繁", 'warning');
					return
				} else {
					if(!this.content) {
						this.common.messageTip("请输入公告内容", 'error');
						return
					}
          if(type==1){
            let verifyData = {
              content:this.content
            }
            this.$api.operateMgmt.newlyIncreased(verifyData).then(res => {
              if(res.code == 200) {
                let that = this
                this.$message({
                  message: "提交成功",
                  duration: this.common.duration,
                  type: 'success',
                  onClose: function() {
                    that.$emit('saveBox')
                  }
                });
              } else {
                let that = this
                this.$message({
                  message: res.message,
                  duration: this.common.duration,
                  type: 'error',
                  onClose: function() {
                    that.$emit('saveBox')
                  }
                });
              }
            })

          }
          if(type==2){
            let verifyData = {
              content:this.content,
              id: this.propData.id,
            }
            this.$api.operateMgmt.updataIncreased(verifyData).then(res => {
              if(res.code == 200) {
                let that = this
                this.$message({
                  message: "提交成功",
                  duration: this.common.duration,
                  type: 'success',
                  onClose: function() {
                    that.$emit('saveBox')
                  }
                });

              } else {
                let that = this
                this.$message({
                  message: res.message,
                  duration: this.common.duration,
                  type: 'error',
                  onClose: function() {
                    that.$emit('saveBox')
                  }
                });
              }
            })

          }

				}

			},

			cancel() {
				this.editBoxShow = false
				this.$emit('cancel')
			},
		},
		watch: {
			propData(val) {
        console.log(val,1213)
				this.verifyData = val
			},
		}
	}
</script>

这个里面也有新增和修改公用一个弹框组件的逻辑,(进行传不同的type实现的)可以研究一下。