最近项目上出现了一个“收集用户反馈”需求,大概的执行流程就是:点击按钮,弹出对话框,在对话框中收集用户评价,最后再输出。正好这个项目是用的ElementUi,所以考虑使用Notification这个组件,但是在使用过程中遇到了一系列问题,踩了不少坑,这里做一下总结分享。
1、什么是Notification组件
Notification 组件提供通知功能,Element 注册了
$notify
方法,接收一个options
字面量参数,在最简单的情况下,你可以设置title
字段和message
字段,用于设置通知的标题和正文。默认情况下,经过一段时间后 Notification 组件会自动关闭,但是通过设置duration
,可以控制关闭的时间间隔,特别的是,如果设置为0
,则不会自动关闭。注意:duration
接收一个Number
,单位为毫秒,默认为4500
。
这是来自官方文档给出的解释,其具体的执行效果如下:
2、Notification组件的基本使用
html部分:
<el-button plain @click="open"> 可自动关闭 </el-button>
js部分:
open() {
this.$notify({
title: '提示', //标题
message: '这是一条不会自动关闭的消息', //内容
duration: 0, //设置弹框消失事件
position:'bottom-right', // 设置弹框在屏幕的哪个角弹出(只能设置4个角)
type: 'warning', //给标题前加一个小图标
offset: 100, //偏移量:距离四个角的偏移程度(默认偏移了16px)
dangerouslyUseHTMLString: true, //是否支持弹出框内传入 HTML 片段
message: '<strong>这是 <i>HTML</i> 片段</strong>', //开启后,这里可以写html
showClose: false, //隐藏关闭按钮(右上角的x 默认为true,显示)
close(){
console.log('弹框被关闭了')
} //点击关闭按钮的回调函数
});
}
Notification组件的执行过程
1)Notification组件是通过触发点击事件open事件发生的;
2)open这个方法执行Element上面注册的$notify的方法;
3)关于close回调函数的使用:
关闭某个弹框:this.$notify.close() //想要关闭单个弹框的话需要传入弹框的ID
关闭全部弹框:this.$notify.closeAll()
注意:如果在Notification组件中传入Html片段,message里面的html子符串其实是脱离了vue,例如不能用@click方法绑定事件,因此,应该用js的操作dom来绑定。
3、实际案例
假设我们有这样一个需求:我们需要点击一个按钮,用来收集用户反馈,我们应该如何使用Notification组件呢?
案例效果:




需求分析:
1)我们页面上需要一个可以点击的按钮,来触发这个Notification组件;
2)在Notification组件我们需要输入Html片段;
3)每一个收集到的用户意见,需要自动弹出下一个问题(这里只需要将message的内容写成变量,就不需要再次产生一个弹框了)
注意事项:
1)在第一次触发弹框后,按钮不能再次被点击而触发下一次弹框;
2)在反馈过程中,点击关闭按钮后,能够点击按钮再次弹出第一个弹框,从而再次收集用户反馈;
3)弹框最后一个是“Thank you”内容,需要自动消失。
代码实现:
html部分:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- import CSS --> <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/theme-chalk/index.css"> <link rel="stylesheet" href="./index.css"> </head> <body> <div id="app"> <template> <el-button class="feedback" plain @click="open"> FEEDBACK </el-button> </template> </div> </body> <script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.15.9/index.js"></script> </html>
js部分:(使用vue2)
data: { feedback: { expericene: '', information: '', article: '', useful: false, }, tittle: '', message: '', }, methods: { open() { that = this document.querySelector('.el-button').disabled = true this.$notify({ title: 'How would you rate your experience?', message: '这是第一条消息', duration: 0, dangerouslyUseHTMLString: true, message: `<ul class="rectangle-content"> <li id="0" class="first"></li> <li id="1" class="second"></li> <li id="2" class="third"></li> <li id="3" class="fourth"></li> <li id="4" class="fifth"></li> </ul>`, onClose() { document.querySelector('.el-button').disabled = false console.log('that.feedback', that.feedback) } }); let rectangle = document.querySelectorAll(".rectangle-content li") var expericene = ['like1', 'like2', 'like3', 'like4', 'like5'] rectangle.forEach((value) => { var that = this value.onclick = function () { this.className = this.className + '-light' that.feedback.expericene = expericene[this.id] if (that.feedback.expericene != '') { that.getInformation() } } }) }, getInformation() { this.title = 'Were you able to find the information you were looking for?' this.message = `<div class="rectangle-box"> <div class="box-no">NO</div> <div class="box-yes">YES</div> </div>` var notifyTitle = document.querySelector('.el-notification__title') var notifyBox = document.querySelector('.el-notification__content p') notifyTitle.innerHTML = this.title notifyBox.innerHTML = this.message let box = document.querySelectorAll(".rectangle-box div") let information = '' for (i = 0; i < box.length; i++) { var that = this box[i].onclick = function () { that.feedback.information = this.innerHTML.toLowerCase() if (that.feedback.information != '') { that.getArticle() } } } }, getArticle() { this.title = 'How useful was this article?' this.message = `<ul class="artic-content""> <li class="first">1</li> <li class="second">2</li> <li class="third">3</li> <li class="fourth">4</li> <li class="fifth">5</li> </ul> <div class="useful"> <span class="left">Not useful</span> <span class="right">Very useful</span> </div` var notifyTitle = document.querySelector('.el-notification__title') var notifyBox = document.querySelector('.el-notification__content p') notifyTitle.innerHTML = this.title notifyBox.innerHTML = this.message let artic = document.querySelectorAll(".artic-content li") let article = '' for (i = 0; i < artic.length; i++) { var that = this artic[i].classList.remove('colorAdd') artic[i].onclick = function () { this.classList.add('colorAdd') that.feedback.article = this.innerHTML if (that.feedback.article != '') { that.getEnd() } } } }, getEnd() { this.feedback.useful = true this.title = 'Thank you for sharing your feedback with us.' this.message = `<span class='rectangle_detail'>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.</span>` var notifyTitle = document.querySelector('.el-notification__title') var notifyBox = document.querySelector('.el-notification__content p') notifyTitle.innerHTML = this.title notifyBox.innerHTML = this.message console.log('first', this.feedback) if (this.feedback.useful) { this.feedback = { expericene: '', information: '', article: '', useful: false, } setTimeout(() => { this.$notify.closeAll() document.querySelector('.el-button').disabled = this.feedback.useful }, 1000) } }, },
css部分:(此处涉及一些图标,可以自己找一些替换一下)
.feedback { position: fixed; right: 0; bottom: 29%; width: 49px; height: 150px; background-color: #e62f46; color: white; border-radius: 0; } .feedback span { display: inline-block; font-size: 16px; width: 62.5px; margin-left: -27px; transform: rotate(-90deg); letter-spacing: 0.89px; position: relative; } .feedback:hover, .feedback:active, .feedback:focus { background: #e62f46 !important; border-color: #e62f46 !important; color: white !important; } .feedback span::after { position: absolute; top: -3px; right: 68px; content: ''; display: inline-block; width: 20px; height: 20px; background: url(./img/smail.jpg) no-repeat; background-size: contain; transform: rotate(90deg); } .rext { display: none; } .el-notification { /* display: block !important; */ top: 70% !important; width: 450px; height: 180px; box-shadow: 4px 4px 22px 0 rgba(0, 0, 0, 0.2); background-color: var(--white); text-align: center; box-sizing: border-box; overflow: hidden; border-radius: 0; border: none; right: 60px !important; justify-content: center; } .el-notification .el-notification__title { /* max-width: 330px; */ padding: 0 10px; font-size: 20px; font-weight: 550; margin: 20px auto 23px; color: #19516c; letter-spacing: -1.4px; } .el-notification .rectangle-content { display: flex; justify-content: center; padding: 0; margin: 0; margin-top: 23px; } .el-notification .el-icon-close:before { content: ''; display: inline-block; width: 20px; height: 20px; background: url(./img/icon-close-default.png) no-repeat; background-size: cover; } .el-notification .rectangle-content li { width: 42px; height: 42px; list-style: none; margin: 0 15px; cursor: pointer; text-align: center; } .el-notification .rectangle-content .first { background: url(./img/first_dark.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .first-light { background: url(./img/first.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .first:hover { background: url(./img/first.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .first::before, .el-notification .rectangle-content .first-light::before { display: none; content: 'Like'; font-size: 12px; transform: translateY(46px); color: rgba(0, 0, 0, 0.2); } .el-notification .rectangle-content .first:hover::before, .el-notification .rectangle-content .first-light:hover::before { display: block; } .el-notification .rectangle-content .second { background: url(./img/second_dark.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .second-light { background: url(./img/second.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .second:hover { background: url(./img/second.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .second::before, .el-notification .rectangle-content .second-light::before { display: none; content: 'Like'; font-size: 12px; transform: translateY(46px); color: rgba(0, 0, 0, 0.2); } .el-notification .rectangle-content .second:hover::before, .el-notification .rectangle-content .second-light:hover:before { display: block; } .el-notification .rectangle-content .third { background: url(./img/third_dark.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .third-light { background: url(./img/third.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .third:hover { background: url(./img/third.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .third::before, .el-notification .rectangle-content .third-light::before { display: none; content: 'Like'; font-size: 12px; transform: translateY(46px); color: rgba(0, 0, 0, 0.2); } .el-notification .rectangle-content .third:hover::before, .el-notification .rectangle-content .third-light:hover::before { display: block; } .el-notification .rectangle-content .fourth { background: url(./img/fifth_dark.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fourth-light { background: url(./img/fifth.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fourth:hover { background: url(./img/fourth.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fourth::before, .el-notification .rectangle-content .fourth-light::before { display: none; content: 'Like'; font-size: 12px; transform: translateY(46px); color: rgba(0, 0, 0, 0.2); } .el-notification .rectangle-content .fourth:hover::before, .el-notification .rectangle-content .fourth-light:hover::before { display: block; } .el-notification .rectangle-content .fifth { background: url(./img/fifth_dark.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fifth-light { background: url(./img/fifth.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fifth:hover { background: url(./img/fifth.jpg) no-repeat; background-size: contain; } .el-notification .rectangle-content .fifth::before, .el-notification .rectangle-content .fifth-light::before { display: none; content: 'Like'; font-size: 12px; transform: translateY(46px); color: rgba(0, 0, 0, 0.2); } .el-notification .rectangle-content .fifth:hover::before, .el-notification .rectangle-content .fifth-light:hover::before { display: block; } /* second */ .el-notification .rectangle-box { display: flex; justify-content: center; text-align: center; } .el-notification .rectangle-box .box-no { width: 125px; height: 50px; box-sizing: border-box; margin: 0 30px 0 0; background-color: #19516c; font-size: 16px; letter-spacing: 0.53px; font-weight: 550; color: white; line-height: 50px; cursor: pointer; } .el-notification .rectangle-box .box-yes { width: 125px; height: 50px; box-sizing: border-box; background-color: #e62f46; font-size: 16px; letter-spacing: 0.53px; font-weight: 550; color: white; line-height: 50px; cursor: pointer; } /* third */ .el-notification .artic-content { display: flex; justify-content: center; padding: 0; margin: 0; cursor: pointer; margin-bottom: 10px; text-align: center; } .el-notification .artic-content li { width: 65px; height: 50px; box-sizing: border-box; margin: 0 7px; line-height: 50px; background-color: #f0f0f0; list-style: none; font-size: 18px; font-weight: 550; color: #19516c; } .el-notification .artic-content li.colorAdd { background-color: #19516c; color: white; } .el-notification .artic-content li:hover { background-color: #19516c; color: white; } .el-notification .useful { display: flex; justify-content: center; text-align: center; } .el-notification .useful span { color: #777777; font-size: 16px; line-height: 22px; letter-spacing: 0.53px; } .el-notification .useful span.left { margin-right: 200px; } /* fourth */ .el-notification .rectangle_detail { margin-top: -10px; padding: 0 35px; display: block; font-size: 16px; color: black; line-height: 24px; text-align: center; } @media screen and (max-width:750px) { body { margin: 0; } .feedback { position: fixed; bottom: 40%; } .el-notification { display: block; right: 0 !important; top: 65% !important; left: 50%; transform: translateX(-50%); width: 330px; height: 170px; } .el-notification .rectangle-content .first::before, .el-notification .rectangle-content .second::before, .el-notification .rectangle-content .third::before, .el-notification .rectangle-content .fourth::before, .el-notification .rectangle-content .fifth::before { transform: translateY(24px); } .el-notification .el-notification__title { font-size: 16px; } .el-notification .rectangle-content li { width: 35px; height: 35px; margin: 0px 10px; } .el-notification .rectangle_icon { width: 18px; height: 18px; } .el-notification .rectangle_title { max-width: 275px; font-size: 16px; } .el-notification .rectangle-box .box-no, .el-notification .rectangle-box .box-yes { width: 118px; height: 40px; line-height: 40px; font-size: 15px; } .el-notification .artic-content { padding: 0 10px; } .el-notification .artic-content li { width: 50px; } .el-notification .useful span { font-size: 15px; display: inline-block; width: 85px; } .el-notification .useful span.left { margin-right: 66px; } .el-notification .useful span.right { width: 90px; } .el-notification .rectangle_detail { padding: 0 15px; } }
如果小伙伴们在开发过程中遇到其他相关问题,欢迎评论区大家一起讨论起来!!!