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值(特定且唯一),使生成的每一条数据与其他数据不用,这样在下一个数据出现时,内核处理为认为是两个不同且独立的数据,重新进行进入动画.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值