vue中使用el-dialog+Promise二次封装确认弹窗

744 阅读2分钟

小引

在很多时候,我们axios请求,或者采用第三方UI库进行二次封装的时候,经常会遇见下面这个问题,明明我想获取到的是一个Object的实例,可是抓取到的是一个Promise,我该怎么处理呢? image.png

简单的写一个Promise用例

让我们先写一段简单的Promise的调用的不同方式的结果并输出:

const success = true
function getTimeStamp() {
    return new Promise((resolve, reject) => {
        if (success) resolve(new Date())
        reject(new Error('异常'))
    })
}
const getPromiseValue1 = () => {
    const res = getTimeStamp()
    console.log('res', res)
}
const getPromiseValue2 = async () => {
    const res = await getTimeStamp()
    console.log('res', res)
}
const getPromiseValue3 = async () => {
    getTimeStamp().then(res=>{
        console.log('res', res)
    })
}
getPromiseValue1() // res Promise { 2023-11-02T04:56:27.386Z }
getPromiseValue2() // res 2023-11-02T04:56:27.393Z
getPromiseValue3() // res 2023-11-02T04:56:27.393Z

通常我们使用thenawait的方式从Promise的实例获取数据,但是因为then嵌套层级过深的时候,会掉进回调地狱,因此推荐使用await

vue中使用el-dialog+Promise二次封装确认弹窗

在父页面:

const confirm = await this.$refs.modalRefName.confirm('提示','这是提示信息')
if(confirm === 'confirm') {
    // 点击确定
} else {
    // 点击取消
}

子组件

<template>
  <div>
    <el-dialog v-model="visible" :show-close="false" width="450px" align-center>
      <div>
        <el-icon color="#FFC440" size="45px">
          <WarningFilled />
        </el-icon>
      </div>
      <div class="title">{{ title }}</div>
      <div class="sub-title">{{ subTitle }}</div>
      <div class="justify-evenly">
        <div class="btn-cancel" @click="cancelBtn">取消</div>
        <div class="btn-confirm" @click="confirmBtn">确定</div>
      </div>
    </el-dialog>
  </div>
</template>
	  
<script lang="ts">
export default { name: 'TipModal' }
</script>
	  
<script setup inherit-attrs="false" lang="ts" >
import { ref } from 'vue'
import { WarningFilled } from '@element-plus/icons-vue'

const visible = ref(false)
const title = ref('')
const subTitle = ref('')

const confirmBtn = ref();
const cancelBtn = ref();
const open = async () => {
  visible.value = true;
  return new Promise((resolve) => {
    confirmBtn.value = () => {
      visible.value = false;
      resolve('confirm');
    };
    cancelBtn.value = () => {
      visible.value = false;
      resolve('cancel');
    };
  });
};

defineExpose({
  async confirm(p_title = '提示', p_subTitle = '确认进行次操作?') {
    title.value = p_title
    subTitle.value = p_subTitle
    return await open();
  }
})
</script>
	  
<style scoped lang="scss">
.title {
  text-align: center;
  margin-top: 20px;
  font-size: 18px;
  font-weight: bolder;
  color: #334266;
}

.sub-title {
  text-align: center;
  margin-top: 6px;
  font-size: 16px;
  font-weight: 400;
  color: #334266;
}

.justify-evenly {
  display: flex;
  justify-content: space-evenly;
  margin-top: 38px;

  .btn-cancel {
    width: 110px;
    height: 32px;
    background: #fff;
    border-radius: 5px;
    opacity: 1;
    font-size: 14px;
    font-weight: 400;
    color: #8c93a4;
    border: 1px solid #d9d9d9;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
  }

  .btn-confirm {
    width: 110px;
    height: 32px;
    background: linear-gradient(270deg, #3392ff 0%, #8c9eff 100%);
    border-radius: 5px;
    opacity: 1;
    font-size: 14px;
    font-weight: 400;
    color: #ffffff;
    display: flex;
    justify-content: center;
    align-items: center;
    cursor: pointer;
  }
}

:deep(.el-dialog) {
  border-radius: 10px;
  overflow: hidden;
}

:deep(.el-dialog__header) {
  margin-right: 0 !important;
  padding: 0 !important;
}

:deep(.el-dialog__body) {
  padding: 18px;
  text-align: center;
}
</style>