本人自從事前端工做以來,往往遇到技術問題後,都是向百度/谷歌求教,長此以往便養成了伸手即來的‘本領’。。。多是出於‘懶’的緣由(沒錯,就是由於懶),從未發表過技術文章或開發經驗,深感慚愧,故洗心革面,決心分享一些東西。
本文所述僅冰山一角,歡迎你們留言寶貴經驗~。css
頁面屬於活動頁面
a.進入頁面會請求後臺接口,拉取當前用戶抽獎剩餘次數
b.點擊九宮格開始按鈕,開始轉動,並請求後臺接口
c.接口請求成功,根據接口返回的停留位置中止轉動
d.可連續抽獎,直至抽獎次數爲0 大體展現效果以下前端
template部分ios
<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部分git
1.接口說明:若是本地localhost啓動,能夠用setTimeout模擬post請求 2.函數說明:github
move函數 爲100ms轉動,切最小轉動次數爲12(一圈半,也就是防止接口返回太快,剛開始轉就中止),當接口返回成功後,記錄當前index及服務器的返回中止位置stopIndex,並執行enter函數; enter函數 100ms轉動,接受參數,計算當前index與stopIndex的差值,若是>4,就能夠執行遞減,===4時;<=4,再次判斷是否>-4(這個判斷是爲了計算多轉幾回),執行stop函數; stop函數 爲300ms轉動,只轉4次,而後完成整個流程;ajax
3.對於setInterval,當組件銷燬時,要清除定時器axios
<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部分bash
關於正方形佈局,經過{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源碼以下cookie
// 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);
}
複製代碼
歡迎各位大佬指正 後續會分享自定義日曆組件/城市地點選擇組件等等,歡迎你們一塊兒討論學習!