本人自从事前端工做以来,往往遇到技术问题后,都是向百度/谷歌求教,长此以往便养成了伸手即来的‘本领’。。。多是出于‘懒’的缘由(没错,就是由于懒),从未发表过技术文章或开发经验,深感惭愧,故洗心革面,决心分享一些东西。
本文所述仅冰山一角,欢迎你们留言宝贵经验~。
页面属于活动页面
a.进入页面会请求后台接口,拉取当前用户抽奖剩余次数
b.点击九宫格开始按钮,开始转动,并请求后台接口
c.接口请求成功,根据接口返回的停留位置中止转动
d.可连续抽奖,直至抽奖次数为0
大体展现效果以下
template部分css
<template> <div class="v-common-com-lottery"> <ul class="list"> <li class="item" :class="['item' + index, {'active': item.active}]" :key="index" v-for="(item, index) in list"> <img class="icon" :src="item.img" :alt="item.info" /> <span class="info">{{item.info}}</span> <span class="mask"></span> </li> <li class="btn" @click="move"> <span class="text">按钮</span> <i class="mask"></i> </li> </ul> <div class="lucky-times"> <span>您有{{luckyTimes}}次抽奖机会</span> </div> </div> </template>
script部分前端
1.接口说明:若是本地localhost启动,能够用setTimeout模拟post请求
2.函数说明:iosmove函数 为100ms转动,切最小转动次数为12(一圈半,也就是防止接口返回太快,刚开始转就中止),当接口返回成功后,记录当前index及服务器的返回中止位置stopIndex,并执行enter函数;
enter函数 100ms转动,接受参数,计算当前index与stopIndex的差值,若是>4,就能够执行递减,===4时;<=4,再次判断是否>-4(这个判断是为了计算多转几回),执行stop函数;
stop函数 为300ms转动,只转4次,而后完成整个流程;3.对于setInterval,当组件销毁时,要清除定时器git
<script> import { post } from '@common/js/ajax'; import { deepQuery } from '@mfw/trans-core'; export default { data() { return { // 奖单 list: [ { img: 'https://n3-q.mafengwo.net/s12/M00/43/1C/wKgED1v__MqAPEuxAABG61CRQek46.jpeg', info: '谢谢参与', active: false }, { img: 'https://b1-q.mafengwo.net/s12/M00/43/1C/wKgED1v__MqATFWOAAA8r6he_a471.jpeg', info: '北京-东京往返机票', active: false }, { img: 'https://n3-q.mafengwo.net/s12/M00/42/2C/wKgED1v__AyAGkNKAAA33_Ke5y444.jpeg', info: '50元代金券', active: false }, { img: 'https://n3-q.mafengwo.net/s12/M00/43/1C/wKgED1v__MqAPEuxAABG61CRQek46.jpeg', info: '马蜂窝护照包', active: false }, { img: 'https://b1-q.mafengwo.net/s12/M00/43/1C/wKgED1v__MqATFWOAAA8r6he_a471.jpeg', info: '谢谢参与', active: false }, { img: 'https://n3-q.mafengwo.net/s12/M00/42/2C/wKgED1v__AyAGkNKAAA33_Ke5y444.jpeg', info: '北京-札幌往返机票', active: false }, { img: 'https://b1-q.mafengwo.net/s12/M00/43/1C/wKgED1v__MqATFWOAAA8r6he_a471.jpeg', info: '蚂蜂窝旅行箱', active: false }, { img: 'https://n3-q.mafengwo.net/s12/M00/42/2C/wKgED1v__AyAGkNKAAA33_Ke5y444.jpeg', info: '马蜂窝日历', active: false }, ], // 上次停留位置 index lastIndex: 0, // 服务器返回停留位置 index stopIndex: 0, // 正常转动动画 timer1: null, // 进入低速转动动画 timer2: null, // 低速转动动画 timer3: null, // 正在执行动画 isMoving: false, // 转动次数 最小12次(一圈半) 防止转动时间太短 times: 0, // 接口成功返回中止stopIndex 标识 ajaxEnd: false, // 进入低速转动动画 标识 timerEnd: false, // 用户抽奖次数(实际应该是后台返回的次数) luckyTimes: 5, }; }, watch: { times(val) { // 若是计数过程当中,ajax未成功 if (!this.ajaxEnd) { return false; } if (val >= 12) { this.timerEnd = true; } }, }, methods: { getStopIndex() { // 获取服务器返回的index post('/lottery') .then((res) => { if (deepQuery(res, 'data', 'success')) { this.stopIndex = deepQuery(res, 'data', 'data'); if (this.lastIndex !== this.stopIndex || this.lastIndex === this.stopIndex) { this.ajaxEnd = true; } } else { return Promise.reject(deepQuery(res, 'data', 'message')); } }) .catch((err) => { // 初始化数据 clearInterval(this.timer1); this.list.map((e) => { e.active = false; }); this.lastIndex = 0; this.isMoving = false; this.lastIndex = 0; this.times = 0; const errMsg = typeof err === 'string' ? err : '服务器繁忙,请稍后重试'; this.showToast(errMsg); }); }, move() { // 点击开始游戏按钮 if (!this.luckyTimes) { console.error('没有抽奖次数了'); return false; } if (this.isMoving) { return false; } this.isMoving = true; this.ajaxEnd = false; this.timerEnd = false; this.times = 0; console.error('上次中止位置: ', this.lastIndex); let i = this.lastIndex; // 执行ajax请求数据 this.getStopIndex(); // 执行动画 this.timer1 = setInterval(() => { this.times++; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); // 当获取到服务器数据 index if (this.timerEnd) { console.log('服务器返回的中止位置: ', this.stopIndex); clearInterval(this.timer1); this.enter(i, this.stopIndex); } }, 100); }, enter(cur, stop) { // 计算须要中止的index console.log(cur, stop); let count = stop - cur; if (count <= 4) { count = count > -4 ? count + 8 : count + 16; } let i = cur; this.timer2 = setInterval(() => { count--; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); if (count === 4) { clearInterval(this.timer2); this.stop(i, stop); } }, 100); }, stop(cur, stop) { // 计算须要中止的index let count = 0; let i = cur; this.timer3 = setInterval(() => { count++; i++; if (i === 8) { i = 0; } this.list.map((e) => { e.active = false; }); this.$set(this.list[i], 'active', true); if (count === 4) { clearInterval(this.timer3); this.isMoving = false; this.lastIndex = this.stopIndex; this.luckyTimes--; } }, 300); }, showToast(err) { // toast 提示 alert(err); }, }, beforeDestroy() { // 组件销毁前 // 清除定时器 clearInterval(this.timer1); clearInterval(this.timer2); clearInterval(this.timer3); }, }; </script>
style部分github
关于正方形布局,经过{width:100%;padding-bottom:100%;}实现
<style lang="scss"> .v-common-com-lottery { height: 100%; font-size: .24rem; color: #fff; .list { position: relative; background: lightblue; width: 100%; padding-bottom: 100%; } .item { width: 32%; padding-bottom: 32%; position: absolute; background: lightgreen; border-radius: .24rem; overflow: hidden; &.item0 { left: 0; top: 0; } &.item1 { left: 34%; top: 0; } &.item2 { left: 68%; top: 0; } &.item3 { left: 68%; top: 34%; } &.item4 { left: 68%; top: 68%; } &.item5 { left: 34%; top: 68%; } &.item6 { left: 0; top: 68%; } &.item7 { left: 0; top: 34%; } .icon { position: absolute; height: 100%; width: 100%; z-index: 1; } .info { position: absolute; left: 0; bottom: 0; background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .5)); height: .48rem; width: 100%; z-index: 2; display: flex; align-items: center; justify-content: center; } .mask { position: absolute; left: 0; top: 0; z-index: 3; width: 100%; height: 100%; background: rgba(0, 0, 0, .4); opacity: 0; } &.active .mask{ opacity: 1; } } .btn { width: 32%; padding-bottom: 32%; background: lightsalmon; position: absolute; left: 34%; top: 34%; font-size: .72rem; border-radius: .24rem; overflow: hidden; .text { position: absolute; height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; z-index: 2; } .mask { position: absolute; height: 100%; width: 100%; display: flex; align-items: center; justify-content: center; z-index: 2; } } .lucky-times { color: #000; font-size: .36rem; } } </style>
@common/js/ajax源码以下
// https://github.com/axios/axios const axios = require('axios'); // 超时 15秒 // axios.defaults.timeout = 15000; // 容许发送cookie axios.defaults.withCredentials = true; /** * get请求 * @param {string} url - 请求的路径 * @param {Object} params - 参数 * @return {Promise} */ export function get(url, params = {}) { return axios.get(url, { params, }); } /** * post请求 * @param {string} url - 请求的路径 * @param {Object} data - 参数 * @param {Object} config - 原始配置 * @return {Promise} */ export function post(url, data = {}, config = {}) { return axios.post(url, data, config); }
deepQuery源码以下
/** * 深度查询 deepQuery({},"a","b","c") * @param {any} func 要查询的对象 * @return {boolean} true or false */ export function deepQuery(obj, ...args) { return args.reduce((a, b) => (a ? a[b] : a), obj); }
欢迎各位大佬指正 后续会分享自定义日历组件/城市地点选择组件等等,欢迎你们一块儿讨论学习!