vue實現訂單氣泡提示

需求點:

一句話概括 —— 爲營造活動氛圍,在主要頁面添加訂單成功提示,詳情參考拼多多;
細分需求 ——
          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值(特定且唯一),使生成的每一條數據與其他數據不用,這樣在下一個數據出現時,內核處理爲認爲是兩個不同且獨立的數據,重新進行進入動畫.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章