vue封装带确定、取消按钮的弹窗和提示组件,可用promise回调

一、前言

   学习vue也有一段时间了,通过一段时间的学习,逐渐了解了vue框架的一些用法,目前我能感受到vue框架最强大的功能之一就是组件,即代码的复用。而在之前的写项目中经常会用到一些弹窗,在之前的项目中这些弹窗都是写在一个模板页面中,去调用。在学了vue之后我就想着能不能用vue去封装一个全局的弹窗组件,可以使用类似vuex的的方式通过this.$xxx的方式直接调用。

效果演示

封装组件演示

二、弹窗组件代码封装
<template>
  <div class="myAlertDiv" v-show="show">
    <div class="myAlertItem" v-show="type === 1">
      <button class="iconSty" @click="cancelBtnFn">
        <i class="el-icon-close"></i>
      </button>
      <div class="tittle">{{ title }}</div>
      <div class="msg" v-text="message"></div>
      <div class="operator">
        <button @click="sureBtnFn" class="generalSty suerSty hoverSty">
          {{ sureMsg }}
        </button>
        <button @click="cancelBtnFn" class="generalSty cancelSty hoverSty">
          {{ cancelMsg }}
        </button>
      </div>
    </div>
    <div class="hintMsg hintGeneralSty animationSty" v-show="type === 2">
      <span>
        <i class="el-icon-warning-outline"></i>
      </span>
      <span>
        {{ message }}
      </span>
    </div>
    <div class="warningMsg hintGeneralSty animationSty" v-show="type === 3">
      <span>
        <i class="el-icon-warning-outline"></i>
      </span>
      <span>
        {{ message }}
      </span>
    </div>
    <div class="successMsg hintGeneralSty animationSty" v-show="type === 4">
      <span>
        <i class="el-icon-circle-check"></i>
      </span>
      <span>
        {{ message }}
      </span>
    </div>
  </div>
</template>

<script>
import { Icon } from "element-ui";
export default {
  data() {
    return {
      // 提示标题
      title: "提示",
      //   提示内容
      message: "提示信息",
      //   确定按钮内容
      sureMsg: "确定",
      //   取消按钮内容
      cancelMsg: "取消",
      //   用于指定是什么类型的提示信息,1表示带确定和取消的弹窗,2表示提示信息,3表示警告,4表示成功
      type: 4,
      //   是否展示
      show: false,
    };
  },
  //这里用到了element-ui的图标,因为这里只在这个组件中使用了,所以就局部注册了图标组件
  components: {
    [Icon.name]: Icon,
  },
  methods: {
    // 初始化函数
    init() {
      this.show = true;
      //当类型是1时,弹窗带取消和确定按钮,可以通过this.$xx的方式调用之后通过.then(表示确定)或.catch(表示取消)来表示是取消还是成功
      if (this.type == 1) {
        return new Promise((resolve, resject) => {
          this.promiseResult = { resolve, resject };
        });
      } else {
      //类型不是1,则是提示弹窗,不需要确定按钮和取消按钮,但是需要等动画执行完毕之后再销毁组件实例
        // 销毁组件(需等动画执行完)
        setTimeout(() => {
          //执行销销毁组件实例函数
          this.destruction();
        }, 1500);
      }
    },
    // 确定函数
    sureBtnFn() {
      this.promiseResult.resolve();
      //执行销毁组件实例函数
      this.destruction();
    },
    // 取消函数
    cancelBtnFn() {
      this.promiseResult.resject();
      this.destruction();
    },
    // 销毁函数
    destruction() {
      this.show = false;
      //   销毁实例
      this.$destroy(true);
      //将组件从body中移除
      this.$el.parentNode.removeChild(this.$el);
    },
  },
};
</script>
<style scoped>
button {
  outline: none;
  background-color: white;
  color: white;
  border: none;
  cursor: pointer;
}

.myAlertDiv {
  width: 100%;
  height: 100%;
  position: fixed;
  background-color: rgba(0, 0, 0, 0.5);
  top: 0px;
  left: 0px;
}

.myAlertDiv > div {
  padding: 10px;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -150%);
  text-align: center;
}

.myAlertItem {
  width: 500px;
  min-height: 100px;
  max-height: 400px;
  background-color: white;
}

.tittle {
  font-size: 20px;
  font-weight: bold;
}

.msg {
  margin-top: 20px;
  word-wrap: break-word;
  max-height: 100px;
  overflow: auto;
}

.generalSty {
  padding: 5px 15px;
  margin-top: 10px;
  margin-right: 20px;
}

.suerSty {
  background-color: #67c23a;
}

.cancelSty {
  background-color: #f56c6c;
}

.hoverSty:hover {
  opacity: 0.8;
}

.iconSty {
  position: absolute;
  right: 20px;
  color: black;
}

.hintGeneralSty {
  width: 400px;
  color: white;
}

.hintGeneralSty > span {
  display: block;
  padding: 5px 10px;
}

/* 提示信息 */
.hintMsg {
  background-color: #f39c12;
}

/* 警告 */
.warningMsg {
  background-color: red;
}

.successMsg {
  background-color: #27ae60;
}

.animationSty {
  animation: hintAnimation 1s ease alternate;
}

//动画
@keyframes hintAnimation {
  from {
    top: 10px;
  }
  to {
    top: 50%;
  }
}
</style>
三、简单分析

现在我们有了一个公共的组件和样式,那么我们就要想,要怎么实现再任意地方使用this. $xxx的方式调用呢。既然通过this. $xxx的方式调用那么我们会想到我们什么时候这样用过这种方式去调用呢?
vuex中我们使用过,全局事件总线我们也使用过。那么我们就必须利用一个vue的一个重要的内置关系VueComponent.prototype.proto===Vue.prototype
那么我就需要把我们组件的一些方法放到Vue的原型上边。只有这样才能实现全局通过this. $xxx的方式调用
使用过vuex的我们都知道,我们需要在创建vm之前使用Vue.use(vuex)的方式才能在全局使用,里边复杂的东西我也不太清楚,不过能确定的一点就是,他里边一定有一个Vue.prototype. $ xxx=xxx,还有就是vuex里边肯定有一个install函数,而且vue会自动调用这个函数

四、Vue.use之前的准备

既然知道了这些,我们就可以利用这些东西写一个配置文件,用于最后的Vue.use最后就能全局使用了,这个是js文件而非vue文件

// 引入弹窗组件
import myAlert from '../components/myComponent/myAlert'
//引入Vue
import Vue from 'vue'

// 创建组件构造函数
const hint = Vue.extend(myAlert)
// 注册全局组件
Vue.component('myHint', hint)
// 创建函数(传入配置对象)
const hintFn = function (options) {
    let data = {
        message: (options && options.message) || '提示信息',
        type: (options && options.type) || 2
    }
    if (options.type == 1) {
        data.title = (options && options.title) || '提示信息'
        data.sureMsg = (options && options.sureMsg) || '确定'
        data.cancelMsg = (options && options.cancelMsg) || '取消'
    }
    // 实例化组件对象
    const Instance = new hint({
        data: data
    })
    // 挂载
    let vm = Instance.$mount()
    // 添加到body里边
    document.body.appendChild(vm.$el)
    //调用的是弹窗组件的init方法
    return vm.init()
}
// 暴露
export default {
    install: (Vue) => {
    //这里写成$hintFn,是为了迎合vue的一些方法名
        Vue.prototype.$hintFn = hintFn // 挂到Vue的原型上使用
    }
}
五、main文件的配置及组件的使用

main.js文件的配置

import Vue from 'vue'
import App from './App.vue'
//引入上一步写的js文件
import myHint from './myAlert/index'
//使用
Vue.use(myHint)

new Vue({
  render: h => h(App),
   mounted() {
   //我们可以在这里输出的this的原型上看到我们自己定义的方法$hintFn
    console.log('this', this);
  },
}).$mount('#app')

组件的使用

<template>
  <div>
    <button @click="show">我是app的点击显示带交互的按钮</button>
    <button @click="show1">我是app的点击显示提示的按钮</button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    show() {
      this.$hintFn({
        title: "测试",
        message: "第一次测试",
        type: 1,
      })
        .then(() => {
          console.log("点击了确定");
        })
        .catch(() => {
          console.log("点击了取消");
        });
    },
    show1() {
      this.$hintFn({
        type: 2,
        message: "测试",
      });
    },
  },
  mounted() {
  //我们同样可以看到组件原型的上有我们定义的$hintFn方法
    console.log("app组件中的this", this);
  },
};
</script>

<style>
</style>
六、总结

到这里封装的东西就结束了,第一次封装,还有很多不足,这里欢迎大佬们及时指正。
下周继续努力吧!!

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue2 中使用 `Promise.all` 访问多个已经封装的接口可以这样实现: 假设我们有三个已经封装好的接口 `getUserInfo`、`getPostList` 和 `getCommentList`,它们的调用方式类似于: ```javascript getUserInfo() .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误情况 }) getPostList() .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误情况 }) getCommentList() .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误情况 }) ``` 我们可以将这些接口的 Promise 对象放入一个数组中,然后使用 `Promise.all` 执行这些 Promise,等待所有 Promise 都成功完成后,`then` 方法中的回调函数就会被执行,此时的 `responses` 数组包含了所有接口的响应数据。代码如下: ```javascript const promiseArray = [ getUserInfo(), getPostList(), getCommentList() ] Promise.all(promiseArray) .then(responses => { const userInfo = responses[0].data const postList = responses[1].data const commentList = responses[2].data console.log(userInfo, postList, commentList) }) .catch(error => { console.log(error) }) ``` 以上代码中,`promiseArray` 数组里包含了多个已经封装好的接口的 Promise 对象,使用 `Promise.all` 执行这些 Promise,等待所有 Promise 都成功完成后,`then` 方法中的回调函数就会被执行,此时的 `responses` 数组包含了所有接口的响应数据。可以根据需要修改相应的变量名和处理响应数据的代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值