本人自從事前端工做以來,往往遇到技術問題後,都是向百度/谷歌求教,長此以往便養成了伸手即來的‘本領’。。。多是出於‘懶’的緣由(沒錯,就是由於懶),從未發表過技術文章或開發經驗,深感慚愧,故洗心革面,決心分享一些東西。
本文所述僅冰山一角,歡迎你們留言寶貴經驗~。
頁面屬於活動頁面
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); }
歡迎各位大佬指正 後續會分享自定義日曆組件/城市地點選擇組件等等,歡迎你們一塊兒討論學習!