下面是针对“vue3手动封装弹出框组件message的方法”的完整攻略:
1. 前置知识
在封装message组件之前,需要掌握Vue3的以下知识点:
- 使用Vue3的Composition API编写组件
- 如何在Vue3中进行全局组件注册
- 如何在Vue3的setup函数中使用provide和inject来进行父子组件之间的通信
2. 开始封装message组件
首先,我们需要在Vue3的官方文档中寻找message组件源码并进行分析,以此为基础来进行我们的封装。
<template>
<div class="el-message"></div>
</template>
<script>
import { ref, watchEffect, computed, onMounted, onBeforeUnmount } from 'vue'
import { ElMessageOptions, MessageType, MESSAGE_TYPES, SEVERITY_TYPES } from './types'
const baseClass = 'el-message'
export default {
name: 'ElMessage',
setup() {
const messages = ref<ElMessageOptions[]>([])
const removeMessage = (msg: ElMessageOptions) => {
const idx = messages.value.indexOf(msg)
if (idx > -1) {
messages.value.splice(idx, 1)
}
}
const addMessage = (msg: ElMessageOptions) => {
messages.value.push(msg)
if (msg.duration > 0) {
setTimeout(() => {
removeMessage(msg)
}, msg.duration)
}
}
const close = (msg: ElMessageOptions) => {
removeMessage(msg)
}
const getMessageClasses = (msg: ElMessageOptions) => {
const result: string[] = []
if (msg.type) {
const typeClass = `el-message-${msg.type}`
if (MESSAGE_TYPES.includes(msg.type)) {
result.push(typeClass)
} else {
console.error(`[ElMessage] Invalid message type ${msg.type}`)
}
}
if (msg.severity) {
const severityClass = `el-message-severity-${msg.severity}`
if (SEVERITY_TYPES.includes(msg.severity)) {
result.push(severityClass)
} else {
console.error(`[ElMessage] Invalid message severity ${msg.severity}`)
}
}
return result
}
const getIconClass = (msg: ElMessageOptions) => {
if (msg.type === MessageType.Success) {
return 'el-icon-success'
} else if (msg.type === MessageType.Warning) {
return 'el-icon-warning'
} else if (msg.type === MessageType.Error) {
return 'el-icon-error'
} else if (msg.type === MessageType.Info) {
return 'el-icon-info'
} else {
return ''
}
}
const getMsgsWithComputedValues = computed(() => {
return messages.value.map(msg => {
return {
...msg,
classes: getMessageClasses(msg),
iconClass: getIconClass(msg)
}
})
})
const handleOptionMessage = (option: string) => {
addMessage({
message: option,
duration: 3000,
type: MessageType.Info
})
}
watchEffect((onInvalidate) => {
const register = (func: (msg: string) => void) => {
onInvalidate(() => {
ipcRenderer.removeListener('el-message', func)
})
ipcRenderer.on('el-message', func)
}
// register ipc listener
const handler = (event: any, arg: any) => {
if (arg.type === 'el-message') {
const msg = arg.payload
addMessage(msg)
}
}
register(handler)
return () => {
ipcRenderer.removeListener('el-message', handler)
}
})
onMounted(() => {
window.$message = handleOptionMessage
})
onBeforeUnmount(() => {
window.$message = null
})
return {
messages: getMsgsWithComputedValues,
close
}
}
}
</script>
从上面的源码中,我们可以看到,message组件的主要功能是:接收消息、展示消息、定时移除消息。因此,我们需要在自己封装的组件中也实现这几个功能。
2.1 父组件向子组件传递数据
在Vue3中,父组件可以使用provide来向子组件传递数据,而子组件可以使用inject来接收数据。这种方式在传递状态管理库如Vuex中的store实例时尤其常用。
例如,在父组件中,我们可以这样定义provide:
import { provide } from 'vue'
export default {
setup() {
provide('message', this.$message) // 传递message方法给子组件
}
}
然后,在我们封装的message组件中,就可以这样来使用inject来接收message方法:
import { inject } from 'vue'
export default {
setup() {
const message = inject('message')
// 使用message方法展示弹窗
message({
type: MessageType.Info,
message: 'Hello World',
duration: 3000
})
}
}
为了方便起见,我们把message方法直接传递给window全局变量,这样在使用的时候就可以直接调用window.$message方法来展示弹窗了。
2.2 编写弹出框组件
知道了如何父组件向子组件传递数据后,我们就可以编写我们自己的弹出框组件了。我们要实现的功能是:弹出框显示到页面上并在指定时间后自动消失。
<template>
<div class="my-message" :class="isShow ? 'show' : ''">
{{ message }}
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true
},
duration: {
type: Number,
default: 3000 // 默认展示时间为3秒钟
}
},
data() {
return {
isShow: false
}
},
mounted() {
this.isShow = true
setTimeout(() => {
this.isShow = false
}, this.duration)
}
}
</script>
<style scoped>
.my-message {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
padding: 16px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transition: all 0.3s;
opacity: 0;
z-index: 1000
}
.my-message.show {
opacity: 1;
}
</style>
按照上面的代码来编写自己的弹出框组件,然后再在全局组件注册中注册它,这样就可以在任意位置使用自己的message方法来展示弹框了。
示例1:定义一个包含message和duration参数的message方法
import { createApp } from 'vue'
import App from './App.vue'
import Message from './components/Message.vue'
const app = createApp(App)
app.component('my-message', Message)
app.config.globalProperties.$message = function(message, duration = 3000) {
const mountNode = document.createElement('div')
document.body.appendChild(mountNode)
const close = () => {
app.unmount(mountNode)
setTimeout(() => {
document.body.removeChild(mountNode)
}, 300)
}
const props = {
message,
duration
}
const vm = app.mount(mountNode, {
template: `<my-message v-bind="$props" />`,
setup() {
return {
props
}
}
})
setTimeout(close, duration)
}
这样,我们就可以在任意的Vue3组件中使用window.$message方法来展示弹出框了,例如:
<template>
<div>
<button @click="handleMessageClick">点击展示信息</button>
</div>
</template>
<script>
export default {
setup() {
const handleMessageClick = () => {
window.$message('Hello World', 3000)
}
return {
handleMessageClick
}
}
}
</script>
示例2:在组件中使用message方法
<template>
<button @click="handleClick">点击展示信息</button>
</template>
<script>
import { onMounted, onBeforeUnmount } from 'vue'
import { inject } from 'vue'
export default {
setup() {
const message = inject('message')
const duration = 3000
const handleClick = () => {
message('Hello World', duration)
}
return {
handleClick
}
}
}
</script>
通过上面的代码,我们就可以在任意Vue3组件中使用我们自己定义的message方法来展示弹出框了,不再局限于在全局使用Vue2的组件。同时,由于我们的自定义组件也符合Vue3的规范,因此在更改项目为Vue3之后,我们无需再做额外的兼容性修改。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue3手动封装弹出框组件message的方法 - Python技术站