zoukankan      html  css  js  c++  java
  • 基于Vant封装一套弹窗插件

    ​ 最近这段时间,公司要求做一套移动端审批流程的页面。大量页面包含了固定样式的提示窗口。类似(alert、toast、confirm)的提示弹窗。考虑到移动端开发,所以采用了市面上面比较火的Vant(友赞)的UI框架。

    ​ 但是一般公司的设计都会比较定制化,会再原有的基础之上,做些主题、样式、交互上的一些调整。不过话说回来,毕竟用的是基于Vue这种框架。此时插槽不就是信手拈来。

    ​ 考虑到多人协作开发,弹窗又都是一样。所以就自己封装了一套插件,供其他人使用。虽可能不尽完美,但是确实是学习到了一些底层封装的思路。这不就是我们作为开发的人热衷的方向吗?做这些事情实际上也是在锻炼自己的技术,学习其他框架编写的思路,理解底层业务的实现原理。这一套封装虽不是多么强大,但也算是重新给我打开了一扇大门,让我对Javascript的有了更进一步的理解。

    公司UI


    封装的弹窗最终效果

    虽然可能有些出入(button,主要是没完善)

    设计思路

    ​ 最开始想到的肯定是Components,因为Vue本身全部都是组件,所有页面也都是以组件的形式开发,包括Template。通常如果封装弹窗组件,使用顺序一般都是import、然后声明、再然后用标签注入到相对应的页面上面使用,其实感觉并不是很友好。而且操作起来很麻烦,还要考虑到子组件注册弹窗后调用的时候,生命周期问题。如果对依赖顺序不太理不清的时候,会出现类似this.$refs... is undifiend | not function的情况。

    ​ 那为什么不能用类似this.$confirm 或者 this.$alert的形式,再我想要用到的时候直接一条命令就可以了呢?想到这里,就想到Vue提供的插件开发的支持。也就有了上面的最终效果。

    供上代码

    目录结构

    VMessage
        ├── Confirm
        │   ├── main.js
        │   └── main.vue
        └── index.js
    

    Confirm/mian.vue

    <template>
      <div class="private-vant-confirm-container">
        <private-dialog
          v-model="show"
          :before-close="beforeClose"
          :show-cancel-button="showCancelButton"
          :show-confirm-button="showConfirmButton"
          :close-on-click-overlay="closeOnClickOverlay"
        >
          <section>
            <svg-icon :icon-class="iconClass" v-if="iconClass" class-name="icon"></svg-icon>
            <span v-if="tips" class="tips">{{tips}}</span>
            <span v-if="message" class="message">{{message}}</span>
          </section>
        </private-dialog>
      </div>
    </template>
    
    <script>
    /* 确认弹窗 */
    import { Dialog } from "vant";
    
    export default {
      components: {
        "private-dialog": Dialog.Component
      },
      data() {
        return {
          show: false,
          type: "success",
          tips: "",
          icon: "",
          message: "",
          showCancelButton: false /* 是否展示取消按钮 */,
          showConfirmButton: false /* 是否展示确认按钮 */,
          closeOnClickOverlay: false /* 是否在点击遮罩层后关闭弹窗 */,
          onClose: null,
          duration: 2000
        };
      },
      watch: {
        show(val) {
          const { showCancelButton, showConfirmButton, duration } = this.$data;
          if (val && !showCancelButton && !showConfirmButton) {
            setTimeout(() => {
              this.show = false;
              this.handleCallback("close");
            }, duration);
          }
        }
      },
      computed: {
        iconClass() {
          return this.icon || this.type;
        }
      },
      methods: {
        beforeClose(action, done) {
          this.show = false;
          done();
          this.handleCallback(action);
        },
        handleCallback(action) {
          if (typeof this.onClose === "function") {
            this.onClose(action);
          }
        }
      }
    };
    </script>
    
    <style lang="scss" scoped>
    .private-vant-confirm-container {
      section {
        padding: 20px 0;
        display: flex;
        justify-content: space-around;
        align-items: center;
        flex-direction: column;
        .icon {
          font-size: 65px;
        }
        span {
          margin-top: 10px;
        }
        .tips {
          color: #2c2d2f;
          font-size: 20px;
        }
        .message {
          color: #48494c;
          font-size: 17px;
        }
      }
    }
    </style>
    

    Confirm/mian.js

    import Vue from "vue";
    import Main from "./main.vue";
    let ConfirmConstructor = Vue.extend(Main);
    
    const Confirm = function(options) {
      options = options || {};
      if (typeof options === "string") {
        options = {
          message: options,
        };
      }
    
      let instance = new ConfirmConstructor({
        data: options,
      });
      instance.$mount();
      document.body.appendChild(instance.$el);
      instance.show = true;
    
      return instance;
    };
    
    ["success", "warning"].forEach((type) => {
      Confirm[type] = (options) => {
        if (typeof options === "string") {
          options = {
            message: options,
          };
        }
        options.type = type;
        return Confirm(options);
      };
    });
    
    export default Confirm;
    

    VMessage/index.js

    /* 确认弹窗 */
    import Confirm from "./Confirm/main";
    
    /**
    
      使用示例
      this.$vConfirm.success({
        message: "提交成功",
        onClose(action) {
          console.log(action, " action");
        }
      });
    
      this.$vConfirm.warning({
        message: "确定同意该申请?",
        tips: "提示",
        showCancelButton: true,
        showConfirmButton: true,
        onClose(action) {
          console.log(action, " action");
        }
      });
    
      try {
        const action = await this.$vConfirmSync({
          type: "warning",
          message: "提交成功",
          showCancelButton: true,
          closeOnClickOverlay: false
        });
        console.log(action, " action");
      } catch (error) {
        console.log(error, " error");
      }
    
    */
    
    /**
     * 同步用法
     * @param {String} tips 提示
     * @param {String} message 内容
     * @param {String} type success (default) | warning
     * @param {String} icon 图标 load svg-icon
     * @param {Boolean} showCancelButton 是否展示取消按钮 default:false
     * @param {Boolean} showConfirmButton 是否展示确认按钮 default:false
     * @param {Boolean} closeOnClickOverlay 是否在点击遮罩层后关闭弹窗 default: false
     * @param {Number} duration 关闭时间 showCancelButton为false && showConfirmButton为false时 default:2000
     */
    function vConfirmSync(options) {
      return new Promise((resolve, reject) => {
        Confirm({
          ...options,
          onClose(action) {
            if (action === "confirm") resolve(action);
            else reject(action);
          },
        });
      });
    }
    
    /**
     * @author Gj
     * 封装Vant Dialog
     */
    const install = function(Vue) {
      Vue.prototype.$vConfirm = Confirm;
      Vue.prototype.$vConfirmSync = vConfirmSync;
    };
    
    export default {
      install,
    };
    

    src/main.js vue的注入口文件注册

    import { VMessage } from "@/components/index";
    Vue.use(VMessage);
    
    ...
    new Vue({
      router,
      store,
      i18n,
      render: (h) => h(App),
    }).$mount("#app");
    
  • 相关阅读:
    postman接口测试工具
    fiddler如何做弱网测试
    支付的测试点
    公交卡测试点
    http的请求方式及http和https的区别
    百度输入框测试点
    ADB常用命令
    Python 操作注册表
    App测试流程及测试点
    python3.7 打包成exe的一种方法 pyinstaller
  • 原文地址:https://www.cnblogs.com/ivday/p/13073285.html
Copyright © 2011-2022 走看看