需求點:
一句話概括 —— 爲營造活動氛圍,在主要頁面添加訂單成功提示,詳情參考拼多多;
細分需求 ——
1. 在首頁,商情頁,購物車,搜索頁和列表頁等只要頁面添加氣氛提醒;
2. 請求接口拿到對應當前時段的用戶下單數據,根據接口記錄下次接口的請求參數;
3. 數據在每個頁面均連續展示,一個接口最多五十條數據;
4. 頁面滯留時間超出全部數據彈出完畢也不發送接口,到其他頁面之後(或者刷新頁面)發送請求;
5. 添加氣泡出現動畫.
思路細分 ——
1.氣泡的展示是連續且多頁面的,所以製作成組件;
2.接口數據返回的是多條,但是每一條數據是獨立存在的;
3.需要記錄接口返回的數據,當前進行到第幾條;
4.動畫需求.
代碼展示
<template>
<div class="bubbleTips">
<!-- <transition name="fade" mode="out-in"> -->
<div :class="['order_info','item'+item.payTime+Math.floor(Math.random()*100)]" v-for="item in currentArr" :key="item.payTime+Math.floor(Math.random()*100)">
<img class="user_img" :src="item.headimgurl!='' ? item.headimgurl:'https://oss-image.dfs168.com/market/315/normal.png'"
alt="" />
<p v-if="item.text!=''" class="copy_writing">{{item.text}}</p>
<p v-if="item.text==''" class="nickname">{{item.nickname==""?'****':item.nickname}}</p>
<p class="copy_writing" v-if="item.text==''&&item.goods_name==''">{{item.payDate}}訂單支付成功</p>
<p class="copy_writing" v-if="item.text==''&&item.goods_name!=''">{{item.payDate}}購買了{{item.goods_name|cutOutStr}}</p>
</div>
<!-- </transition> -->
</div>
</template>
<script>
import Api from "@/api/server";
export default {
props: {
discharge: {
type: Boolean,
default: false
}
},
data() {
return {
index: 0,
arr: JSON.parse(localStorage.getItem("bubbleList")) || [],
currentArr: [],
timer: null
};
},
methods: {
getBubbleList(time) {
var params = {
'payings[time]': time
}
Api.common.getBubbleList(params).then(res => {
if (res.state == 1) {
localStorage.setItem("payingsTime", res.data.payings.time);
if (res.data.payings.list) {
this.arr = res.data.payings.list;
} else {
this.arr = [];
}
localStorage.setItem("bubbleList", JSON.stringify(this.arr));
}
})
},
goFadeBubble() {
var _this = this;
this.index = localStorage.getItem("currentInex") || 0;
this.timer = setInterval(function() {
_this.currentArr = _this.arr.slice(
_this.index,
_this.index * 1 + 1 * 1
);
localStorage.setItem("currentInex", _this.index);
_this.index++;
}, 4000);
}
},
created() {
var index = localStorage.getItem("currentInex"),
payingsTime = localStorage.getItem("payingsTime"),
bubbleList = JSON.parse(localStorage.getItem("bubbleList")) || [];
if (!payingsTime && bubbleList.length == 0) {
this.getBubbleList(0);
localStorage.setItem("currentInex", 0);
} else if (payingsTime && bubbleList.length - index <= 0) {
this.getBubbleList(localStorage.getItem("payingsTime"));
localStorage.setItem("currentInex", 0);
}
this.goFadeBubble();
},
mounted() {
this.$emit("getTimer", this.timer);
},
watch: {
index() {
if (this.index - this.arr.length > 0) {
clearInterval(this.timer);
this.timer = null;
return false;
}
},
discharge() {
if (this.$props.discharge) {
localStorage.setItem("currentInex", this.index);
clearInterval(this.timer);
this.timer = null;
return false;
} else {
var currentInex = localStorage.getItem("currentInex") || this.arr.length;
if (currentInex - this.arr.length < 0) {
this.goFadeBubble();
}
}
}
},
filters:{
cutOutStr(value){
if(value.length>6){
return value.substring(0, 6);
}else{
return value;
}
}
}
};
</script>
<style scoped="scoped">
.bubbleTips .order_info {
position: absolute;
top: 0;
left: 0;
padding: 0.04rem 0.32rem 0.04rem 0.04rem;
box-sizing: border-box;
display: flex;
align-items: center;
border-radius: 0.32rem;
background: rgba(0, 0, 0, .7);
box-shadow: 0px 6px 24px 0px rgba(0, 0, 0, 0.32);
animation: fade_in 2s ease;
}
.bubbleTips .order_info .user_img {
width: 0.56rem;
height: 0.56rem;
border-radius: 50%;
margin-right: .13rem;
}
.bubbleTips .order_info p {
line-height: .3rem;
font-size: 0.24rem;
font-weight: bold;
color: rgba(255, 255, 255, 1);
white-space: nowrap;
}
.bubbleTips .order_info .nickname {
max-width: 1.22rem;
overflow: hidden;
text-overflow: ellipsis;
margin-right: .07rem;
}
@keyframes fade_in {
0% {
opacity: 0;
}
80% {
opacity: 0;
}
100% {
opacity: 1;
}
}
</style>
調用代碼
<!-- 導入 -->
<bubbleTips id="Bubble" v-if="!hasBubble" @getTimer="closeInterval" />
<script>
<!-- 頁面保持狀態(使用keep-alive) -->
import bubbleTips from '../../components/bubbleTips';
export default {
data () {
return {
hasBubble: false
}
},
methods:{
closeInterval(timer) {
this.timer = timer;
}
},
activated: function(){
this.hasBubble = false;
},
deactivated() {
this.hasBubble = true;
clearInterval(this.timer);
}
}
</script>
<bubbleTips id="Bubble" @getTimer="closeInterval" />
<script>
<!-- 未使用keep-alive -->
import bubbleTips from '../../components/bubbleTips';
export default {
data () {
return {
}
},
methods:{
closeInterval(timer) {
this.timer = timer;
}
},
beforeDestroy(){
clearInterval(this.timer);
},
}
</script>
要點介紹
1.由於商場的特殊性,某些頁面(例如首頁)需要保持狀態,使用到keep-alive,有些頁面又沒有使用到,所以在處理需求中的連續時,及在處理需求時,對特殊頁面要進行特殊處理,這裏需要強調的是,生命鉤子的秩序順序在第一次進入頁面時舒服順序和一般頁面一樣,之後再進入時觸發activated,離開時觸發deactivated(注:keep-alive的頁面,組件離開時需要卸載).
2.定時器是全局存在的,在清除數據的同時也要清除定時器,這裏使用了子傳父自定義事件的方式,把定時器的id傳遞給調用組件的父組件,在離開頁面時清除定時器.
3.v-for和v-if的衝突性,在使用時一般是算好滿足條件的數據進行for循環.
4.動畫效果是每一個獨立的信息在進入時有淡入淡出動畫,vue在for循環時需要標註key值(特定且唯一),使生成的每一條數據與其他數據不用,這樣在下一個數據出現時,內核處理爲認爲是兩個不同且獨立的數據,重新進行進入動畫.