vue自定义插件-弹框

Vue自定义消息弹窗组件
<template>
    <transition name="msgbox">
      <div v-if="show" class="msgbox-container" :class="className">
        <header>{{title}}</header>
        <div class="content-body">
          <div>弹出内容可以嵌入html标签</div>
        </div>
        <footer>
          <a v-if="cancel" href="javascript:;" @click="cancelBtn" class="button">{{cancel}}</a>
          <a href="javascript:;" @click="successBtn" class="button">{{confirm}}</a>
        </footer>
      </div>
    </transition>
</template>
<script>
export default {
  data () {
    return {
      show: false,
      title: '提示',
      content: '',
      confirm: '确定',
      cancel:'',
      className:''
    }
  },
  watch:{
    show (val) {
      if (val) {
        if(!this.hasClass(document.body,"pop-mask")){
          this.addClass(document.body,"pop-mask");
        }
      }else{
        this.removeClass(document.body,"pop-mask");
      }
    }
  },
  beforeMount () {
    //如果已经存在,则阻止出现第二次
    let node = document.querySelector('.msgbox-container')
    if (node && node.parentNode) {
      node.parentNode.removeChild(node)
    }
  },
  methods: {
    successBtn () {
      this.show = false;
    },
    cancelBtn () {
      this.show = false;
    },
    addClass(obj, cls){
      var obj_class = obj.className,
          blank = (obj_class != '') ? ' ' : '';
      var added = obj_class + blank + cls;
      obj.className = added;
    },
    removeClass(obj, cls){
      var obj_class = ' '+obj.className+' ';
      obj_class = obj_class.replace(/(\s+)/gi, ' ');
      var removed = obj_class.replace(' '+cls+' ', ' ');
      removed = removed.replace(/(^\s+)|(\s+$)/g, '');
      obj.className = removed;//替换原来的 class.
    },
    hasClass(obj, cls){
      var obj_class = obj.className,
          obj_class_lst = obj_class.split(/\s+/);
      var x = 0;
      for(x in obj_class_lst) {
        if(obj_class_lst[x] == cls) {
            return true;
        }
      }
      return false;
    }
  }
}
</script>
<style lang="scss" scoped>
.msgbox-container{
  position: fixed;
  top:50%;
  left:50%;
  width: 90%;
  background: #fff;
  color: #555;
  border-radius: 0.8rem;
  transform:translate(-50%,-50%) scale(1, 1);
  header{
    margin: 0;
    padding: 1.2rem 0;
    text-align: center;
    color: #333;
    height: 2rem;
    line-height: 2rem;
    font-size: 1.7rem;
    border-radius: 0.8rem 0.8rem 0 0;
    background: #fff;
    border-width: 0;
    border-bottom: 1px solid #ccc;
  }
  .content-body{
    font-size: 1.5rem;
    margin: 2rem 1rem;
    line-height: 2;
    max-height: 20rem;
    overflow-y: auto;
    color: #666;
    div{
      padding: 0 1rem;
      text-align: justify;
      word-break: break-all;
    }
  }
  footer {
    width: 100%;
    text-align: center;
    display: block !important;
    border-width: 0;
    border-top: 1px solid #ccc;
    overflow: hidden;
    background: transparent;
    border-radius: 0 0 0.8rem 0.8rem;
    .button{
      float: left;
      padding: 1rem 0;
      width: 50%;
      color: #999;
      box-sizing: border-box;
      line-height: 3rem;
      font-size: 1.7rem;
      background: #f7f7f7;
      border-right: 1px solid #D5D7D6;
      text-decoration: none;
      -webkit-tap-highlight-color: transparent;
    }
    .button:first-child:nth-last-child(1) {
        width: 100%;
    }
    .button:first-child:nth-last-child(2) ~ .button {
        width: 50%;
    }
  }
}
.msgbox-enter,.msgbox-leave-to{
  -webkit-transform:  translate(-50%,-50%) scale(0,0);
}
.msgbox-enter-active,.msgbox-leave-active{
  -webkit-transition: all .3s;
  transition: all .3s;
}
.msgbox-enter-to,.msgbox-leave{
    -webkit-transform:  translate(-50%,-50%) scale(1,1);
}
</style>

最后在 main.js 里面 配置 

import emComponent from './components/custom/index'
Vue.use(emComponent)

 

具体使用方法

<template>
  <div>
    <label id="msgbox" @click.stop="showMsgbox">点击我显示msgbox</label>
  </div>
</template>
<script>
<script>
export default {
  name: 'test',
  data(){
    return {

    }
  },
  methods:{
    showMsgbox(){
      this.$msgbox({
          title:'温馨提示',
          cancel:'取消',
          content:'这里是消息弹出内容',
          confirm:'确定按钮',
          className:'pop-custom'
      }).then(()=>{
          console.log("我点击了确定按钮")
      }).catch((err)=>{
        console.log("error");
      })
    }
  }
}
</script>

 

源码地址 https://github.com/zuobaiquan/vue/tree/master/vueExercise/vue-component/src/components/custom

转载于:https://www.cnblogs.com/zuobaiquan01/p/8435996.html

### 关于 `vue-fullscreen` 和 `el-dialog` 组合使用不显示的问题 当组合使用 `vue-fullscreen` 和 `el-dialog` 时,如果遇到不显示的情况,通常是因为全屏模式改变了 DOM 的结构或样式优先级,从而影响到了 `el-dialog` 正常渲染的位置和可见性。 #### 可能的原因分析 1. **DOM 结构变化** 当进入全屏状态时,浏览器会改变页面的布局方式,这可能导致某些元素被移除出正常的文档流,进而使得依赖相对定位或其他特定位置关系呈现的内容受到影响[^2]。 2. **CSS 样式冲突** 全屏插件可能会注入额外的 CSS 或者修改现有样式的权重,特别是对于绝对定位、固定定位以及 z-index 属性的影响较大。而 `el-dialog` 默认情况下是通过设置较高的 z-index 来确保其始终位于最顶层显示;一旦这个值被覆盖,则可能出现遮挡现象或者完全不可见的情形[^1]。 3. **Vue 实例生命周期管理不当** 如果是在某个 Vue 组件内部开启全屏并尝试展示 dialog,在处理组件销毁与重新挂载的过程中如果没有妥善管理好数据绑定(如 visible 控制变量),也可能造成视图更新不同步而导致看不到预期中的窗[^4]。 #### 解决方案建议 针对上述可能原因,可以采取如下措施: - **调整 Z-index 设置** 为了防止其他元素盖住 Dialog, 需要确认 `el-dialog` 使用了一个足够高的 z-index 值,并且在启用全屏功能前后都保持一致。可以通过自定义类名的方式增加一层保险: ```css /* 定义一个新的高优先级z-index*/ .el-dialog__wrapper.custom-zindex { z-index: 9999 !important; } ``` 然后在调用 `<el-dialog>` 时加上对应的 class 参数: ```html <el-dialog :class="'custom-zindex'" ...> </el-dialog> ``` - **优化 FullScreen 插件配置** 检查所使用的 `vue-fullscreen` 版本及其官方文档说明,看是否有提供专门针对模态窗口的支持选项或是钩子函数允许开发者手动干预全屏期间的行为逻辑。必要时可通过监听 full-screen change events 并在此基础上做进一步定制化操作来解决问题[^5]。 - **确保正确的 Visible 状态同步** 仔细审查涉及控制 `el-dialog` 显示隐藏的相关代码片段,尤其是那些涉及到异步请求或者其他复杂业务流程的地方,保证每次触发显示/隐藏动作都能及时反映到界面上去。另外考虑到可能存在多个嵌套层次下的父子组件通信场景,推荐采用 Vuex Store 这样的集中式状态管理模式来进行跨组件的状态共享[^3]。 最后提醒一点就是测试过程中要注意区分开发环境和生产环境下表现差异,有时候由于打包工具链的不同配置也会引发意想不到的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值