Vue3的组件封装 – Confirm
一. Confirm的交互逻辑
二. 组件的封装
- 实现组件基础结构和样式。
- 实现函数式调用组件方式和完成交互。
- 加上打开时动画效果。
- 给vue挂载原型函数$confirm
// confirm.vue 组件封装
<template>
<div class="confirm" @click.self="cancelCallback" :class="{ fade }">
<div class="wrapper" :class="{ fade }">
<div class="header">
<h3>{{ title }}</h3>
// icon-close图标自己选择哈
<a @click.stop="cancelCallback" href="JavaScript:;" class="iconfont icon-close-new"></a>
</div>
<div class="body">
<i class="iconfont icon-warning"></i>
<span>{{ text }}</span>
</div>
<div class="footer">
<Button size="mini" @click.stop="cancelCallback" type="gray">取消</Button>
<Button size="mini" @click.stop="submitCallback" type="primary">确认</Button>
</div>
</div>
</div>
</template>
<script>
import { onMounted, ref } from "vue";
import Button from "./Button.vue"; // 额外封装的button组件(可查看其他文章)
export default {
name: "Confirm",
props: {
title: {
type: String,
default: "温馨提示"
},
text: {
type: String,
default: ""
},
submitCallback: {
type: Function // 确认事件
},
cancelCallback: {
type: Function // 取消事件
}
},
setup(props) {
const fade = ref(false)
onMounted(() => {
// 当元素渲染完毕立即过渡的动画不会触发
setTimeout(() => {
fade.value = true
}, 0)
})
return { fade }
},
components: { Button }
}
</script>
<style scoped lang="less">
.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 {
width: 400px;
background: #fff;
border-radius: 4px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -60%);
opacity: 0;
&.fade {
transition: all 0.4s;
transform: translate(-50%, -50%);
opacity: 1;
}
.header,
.footer {
height: 50px;
line-height: 50px;
padding: 0 20px;
}
.body {
padding: 20px 40px;
font-size: 16px;
.icon-warning {
color: @priceColor;
margin-right: 3px;
font-size: 16px;
}
}
.footer {
text-align: right;
.button {
margin-left: 20px;
}
}
.header {
position: relative;
h3 {
font-weight: normal;
font-size: 18px;
}
a {
position: absolute;
right: 15px;
top: 15px;
font-size: 20px;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
color: #999;
&:hover {
color: #666;
}
}
}
}
}
</style>
三. 组件的挂载
- Confirm组件是事件触发, 不应该直接调用, 应该在触发时自动渲染到页面
-
返回的是
Promise
, 但点击确认,或取消时执行
reslove()
,
reject()
在触发相应事件 -
以下渲染页面逻辑
Confirm.js
import {
createVNode,
render
} from "vue"
import confirm from './confirm.vue'
// 创建一个dom节点
const div = document.createElement('div')
div.setAttribute('class', 'confirm-container')
// 挂载到body就可以在最顶层直接控制显示隐藏
document.body.appendChild(div)
export default ({
title,
text
}) => {
/**
* Confirm有两种状态, 确认和取消
* 确认: 返回reslove(), 给confirm组件添加确认时方法
* 取消: reject()
*/
return new Promise((reslove, reject) => {
// 封装组件属性方法
const submitCallback = () => {
//调用完毕后应该清空节点
render(null, div)
reslove()
}
// 封装组件属性方法
const cancelCallback = () => {
//清空节点
render(null, div)
reject()
}
// 在此处才创建节点并挂载属性
const VNode = createVNode(confirm, {
title,
text,
submitCallback,
cancelCallback
})
// 渲染节点到指定dom
render(VNode, div)
})
}
四. 组件的使用
Confirm组件的全局挂载
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import Confirm from '@/components/Confirm.vue' //按自己文件路径导入
const app = createApp(App)
app.config.globalProperties.$Confirm = Confirm //全局挂载Confirm
app.use(router)
app.mount('#app')
组件的使用
// 非全局挂载使用时导入Confirm
import Confirm from '@/cpompoents/Confirm.js'
const delete = () => {
Confirm({ text: '您确定从删除该此项吗?' }).then(() => {
console.log('点击确认事件处理')
}).catch(e => {
console.log('点击取消事件处理')
})
}
效果图
版权声明:本文为m0_46444000原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。