了解vue3
Vue3.0
于 2022 年 2 月 7 日星期一成为新的默认版本!vue3的性能高,打包体积小,
由传统的options选项式 => composition
组合式,大大的提高了代码的可阅读性、逻辑复用性以及更好的类型推导(全面拥抱ts
),重写了diff
算法(更快 更小)。
回到正题,开发中有可能因为有一些业务需求不同,很多时候不能直接使用一些组件库给我提供的组件,如一些messsage
提示信息、messagebox
信息弹窗等,而自己封装一个合适的组件会对开发带来很多便利。
封装组件的先了解messagebox的组件的意义以及它的作用,像封装messagebox这些组件,为了便利使用,一般封装成函数式
组件。通过vue给我们提供的render
渲染函数以及h
函数
生成dom。
功能分析:messagebox一般有 确认/提交
和 取消
按钮,我们需要给使用者可以使用点击/提交后执行一个回调函数,让使用者在该回调里执行一些自定义逻辑,给使用者点击取消后,执行另一个回调,所以需要用到Promise
实现,思路,内部返回一个Promise对象,当使用者点击了确认按钮,执行Promise的resolve
,点击取消执行Promise的reject
,使用者可以使用该函数可以在它的then
的第一个参数的回调执行点击确认后的自定义逻辑,then
的第二个参数的回调执行取消后的操作。
如下图:
MessageBox({
text: '亲,您是否确认删除商品吗'
}).then(
() => {
// 点击确认后干些什么...
},
() => {
// 点击取消后干些什么...
}
)
开始动手实现
src/components
下创建XZMessageBox文件夹(包括 index.ts、XZMessageBox.vue)
src/components/XZMessageBox/XZMessageBox.vue
<template>
<div class="xz-confirm" :class="{ fade: show }">
<div class="wrapper" :class="{ fade: show }">
<div class="head">
<p>{{ title }}</p>
<i class="iconfont icon-guanbi" @click="cancelCallback"></i>
</div>
<div class="body">
<i class="iconfont icon-warning"></i>
<span>{{ text }}</span>
</div>
<div class="foot">
<span class="left" @click="cancelCallback">取消</span>
<span class="right" @click="confirmCallback">确认</span>
</div>
</div>
</div>
</template>
<script setup name="XZMessageBox" lang="ts">
import { defineProps, onMounted, PropType, ref } from 'vue'
const props = defineProps({
text: {
type: String,
default: '这是一条默认文本'
},
title: {
type: String,
default: '温馨提示'
},
点击 确认/提交 后执行
confirmCallback: {
type: Function as PropType<() => void>
},
点击 取消 后执行
cancelCallback: {
type: Function as PropType<() => void>
}
})
const show = ref(false)
实现渐入过渡效果
onMounted(() => {
setTimeout(() => {
show.value = true
}, 20)
})
</script>
<style lang="scss">
$XZColor: #27ba9b;
.xz-confirm {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 8888;
background: rgba(0, 0, 0, 0);
&.fade { // 过渡效果
transition: all 0.4s;
background: rgba(0, 0, 0, 0.5);
}
}
.wrapper {
display: flex;
flex-direction: column;
justify-content: space-between;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 420px;
height: 164px;
padding: 15px;
border-radius: 4px;
background: #fff;
opacity: 0;
&.fade { // 过渡效果
transition: all 0.4s;
transform: translate(-60%, -50%); // 由右往左渐入效果
opacity: 1;
}
> .head {
display: flex;
align-items: center;
justify-content: space-between;
> .iconfont {
cursor: pointer;
}
> p {
font-size: 18px;
}
}
> .body {
margin-left: 30px;
.icon-warning {
margin-right: 6px;
color: #cf4444;
}
}
.foot {
display: flex;
justify-content: flex-end;
> span {
display: block;
padding: 6px 15px;
color: #fff;
border-radius: 4px;
cursor: pointer;
&.left {
border-color: #ccc;
background: #ccc;
}
&.right {
margin-left: 15px;
border-color: $XZColor;
background: $XZColor;
}
}
}
}
</style>
src/components/MeMessageBox/index.ts
import { h, render } from 'vue'
import XZMessageBox from './XZMessageBox.vue'
import XZMessage from '../XZMessage'
// 定义类型
interface Props {
text?: string
title?: string
}
export default function MessageBox ({ text, title }: Props) {
const div = document.createElement('div')
div.setAttribute('class', 'xz-message-box-container')
document.body.appendChild(div)
return new Promise((resolve, reject) => {
const confirmCallback = () => {
document.body.removeChild(div) // 手动移除render生成的dom
resolve(undefined)
XZMessage.success('删除成功!')
}
const cancelCallback = () => {
document.body.removeChild(div) // 手动移除render生成的dom
reject(undefined)
XZMessage.warning('取消成功')
}
const vNode = h(XZMessageBox, {
text,
title,
confirmCallback,
cancelCallback
})
render(vNode, div)
})
}
使用:
MessageBox({
text: '亲,您是否确认删除商品吗'
}).then(
() => {
// 发请求删除商品...
},
() => {
// 提示信息...
}
)
效果图:
点击确认按钮: