我尝试创建一个带有操作按钮的 vue/bootstrap 通知组件。
这就是我当前的结果,无论我做什么,按钮都是通知正文本身的一部分:
按钮应占据整个宽度。
vue组件当前版本:
<template>
<ul class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1050;">
<li v-for="(notification, index) in notifications" :key="index"
class="toast show align-items-center text-white border-0 mb-2 auto-dissmis" @click="removeNotification(index)">
<div class="toast-indicator" :class="'bg-' + notification.type"></div>
<div class="toast-body" v-html="notification.message"></div>
<div class="toast-footer">
<button class="btn btn-outline-primary d-block" @click="action.handler(action, $event)"
v-for="action in notification.actions">
{{ action.title }}
</button>
</div>
</li>
</ul>
</template>
<script>
export default {
name: "Notification",
data() {
return {
notifications: [],
};
},
methods: {
addNotification(message, opts) {
opts = Object.assign({
message,
type: "primary",
actions: [{
title: "Foo",
handler: (self, event) => {
if (event) {
event.stopPropagation();
event.preventDefault();
}
alert("Clicked", self, event);
}
}]
}, opts);
this.notifications.push(opts);
setTimeout(() => {
if (this.notifications.length > 0) {
//this.notifications.shift();
}
}, 2400);
},
removeNotification(index) {
this.notifications.splice(index, 1);
},
},
mounted() {
this.addNotification(`Sample notification #1`);
/*
["info", "primary", "success", "warning", "danger"].forEach((color, i) => {
setTimeout(() => {
this.addNotification(`Sample notification #${i}`, color);
}, i * 1000);
});
*/
},
};
</script>
<style scoped>
.btn-group button:nth-child(1) {
border-top-left-radius: 0;
}
.btn-group button:last-child {
border-top-right-radius: 0;
}
.toast-container {
width: 380px;
list-style: none;
}
.toast {
position: relative;
overflow: hidden;
width: 100%;
display: flex;
align-items: center;
cursor: pointer;
background-color: #343a40 !important
}
.toast-footer {
padding: 0.5rem;
border-top: 1px solid #dee2e6;
}
.toast-indicator {
position: absolute;
bottom: 0;
left: 0;
width: 6px;
height: 100%;
}
.toast-actions {
margin: 0;
}
li.auto-dissmis>.toast-indicator {
animation: progress 2.4s linear forwards;
}
@keyframes progress {
0% {
height: 100%;
}
100% {
height: 0;
}
}
</style>
</style>
找到解决方案。 在
div
元素内创建两个 li
,一个用于 toast 本身,一个用于按钮:
<template>
<!--
<ul class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1050;">
<li class="toast show align-items-center text-white border-0 mb-2 auto-dissmis">
<div class="toast-indicator"></div>
<div class="toast-body">
Hello Wrodl Message
</div>
<div class="btn-group d-flex" role="group" aria-label="Basic example">
<button type="button" class="btn btn-outline-primary flex-fill">Left</button>
<button type="button" class="btn btn-outline-primary flex-fill">Middle</button>
<button type="button" class="btn btn-outline-primary flex-fill">Right</button>
</div>
</li>
</ul>
-->
<ul class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1050;">
<li v-for="(notification, index) in notifications" :key="index" @click="removeNotification(index)" class="mb-2 ">
<div class="toast align-items-center text-white border-0"
:class="{ 'toast-no-bottom-border-radius': notification.actions.length > 0 }">
<div class="toast-indicator" :class="'bg-' + notification.type"></div>
<div class="toast-body" v-html="notification.message"></div>
</div>
<div class="btn-group d-flex">
<button type="button" class="btn btn-outline-primary flex-fill" v-for="(action, index) in notification.actions"
:key="index" @click="action.handler(action, $event)">
{{ action.title }}
</button>
</div>
</li>
</ul>
</template>
<script>
export default {
name: "Notification",
data() {
return {
notifications: [],
};
},
methods: {
addNotification(message, opts) {
opts = Object.assign({
message,
type: "primary",
actions: []
}, opts);
this.notifications.push(opts);
setTimeout(() => {
if (this.notifications.length > 0) {
//this.notifications.shift();
}
}, 2400);
},
removeNotification(index) {
this.notifications.splice(index, 1);
},
},
mounted() {
let handler = (self, event) => {
if (event) {
event.stopPropagation();
event.preventDefault();
}
alert("Clicked", self, event);
};
this.addNotification(`Sample notification #1`, {
actions: [{
title: "Foo",
handler,
}, {
title: "Bar",
handler,
}]
});
this.addNotification(`Sample notification #2`, {
type: "success"
});
/*
["info", "primary", "success", "warning", "danger"].forEach((color, i) => {
setTimeout(() => {
this.addNotification(`Sample notification #${i}`, color);
}, i * 1000);
});
*/
},
};
</script>
<style scoped>
.btn-group button:nth-child(1) {
border-top-left-radius: 0;
}
.btn-group button:last-child {
border-top-right-radius: 0;
}
.toast-container {
width: 380px;
list-style: none;
}
.toast {
position: relative;
overflow: hidden;
width: 100%;
min-height: 60px;
display: flex;
align-items: center;
cursor: pointer;
background-color: #343a40 !important
}
.toast-no-bottom-border-radius {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.toast-indicator {
position: absolute;
bottom: 0;
left: 0;
width: 6px;
height: 100%;
}
.toast-actions {
margin: 0;
}
.btn-group button {
pointer-events: auto;
}
li.auto-dissmis>div.toast>.toast-indicator {
animation: progress 2.4s linear forwards;
}
@keyframes progress {
0% {
height: 100%;
}
100% {
height: 0;
}
}
</style>