vue3實現一個抽獎小專案

曦12發表於2023-01-20

前言

實現目標

  • 資料儲存:無後端,純前端實現,瀏覽器重新整理或者關閉資料不能丟失。
  • 姓名切換:點選中部開始按鈕姓名快速切換。
  • 獎項切換:獎項為操作人員手動切換設定。
  • 歷史記錄:抽獎完成後需要有歷史記錄。
  • 資料匯入:允許參與人員的表格匯入。

資料儲存

無後臺,純前端實現而且需要重新整理關閉瀏覽器資料不丟失,很容易便會想到使用localStorage,localStorage存入的資料具有永續性,不會因為重新整理或關閉瀏覽器而變化(除非手動刻意的清除),有別於sessionstorage,localStorage的生命週期是永久,sessionstorage是瀏覽器或者標籤頁關閉。

因為存入的資料不是單純的字串,而是具有結構性的物件陣列,所以需要配合JSON.stringify與JSON.parse來使用。這是存入資料的方法:

localStorage.setItem("luckDrawHis", JSON.stringify(luckDrawHis));//JSON.stringify將json轉換為字串

這是讀取資料的方法:

JSON.parse(localStorage.getItem("luckDrawHis"))//JSON.parse將字串轉換為json

姓名切換

抽獎的方式是資料匯入後,點選中間的圓形開始按鈕,姓名便開始快速切換,再次點選按鈕便停止姓名切換,彈出對話方塊顯示當前姓名以及設定的獎項。

切換姓名利用了vue的資料響應式原理。先獲取到所有的參與人員資料,然後亂序處理,最後迴圈展示,我這裡每個姓名展示的時間為50毫秒,你也可以自己設定。這裡的陣列亂序我使用了洗牌演算法,其實就是利用Math.random獲取陣列的隨機下標,然後與最後一個元素進行位置交換。

//洗牌演算法(亂序陣列)
function shuffle(arr) {
  let l = arr.length
  let index, temp
  while (l > 0) {
    index = Math.floor(Math.random() * l)
    temp = arr[l - 1]
    arr[l - 1] = arr[index]
    arr[index] = temp
    l--
  }
  return arr;
}

//迴圈列表
function forNameList(list) {
  list = shuffle(list);
  for (let i = 0; i < list.length; i++) {
    setTimeout(() => {
      if (!isStop.value) {
        curName.value = list[i].name;
        (i == list.length - 1) && (forNameList(nameList.value));//陣列耗盡迴圈
      }
    }, 50 * i);
  }
}

獎項切換

獎項切換直接使用elementPlus的單選框即可。

歷史記錄

每次點選抽獎出現結果時,將之前的抽獎結果取出來,然後把當前的結果新增到末尾。

點選抽獎歷史按鈕時再將所有歷史資料取出來。

資料匯入

由於需要匯入人員表格資料,這裡我使用了xlsx外掛與file-saver外掛來實現。

首先是下載模板。
在這裡插入圖片描述

將事先準備好的表格模板放在專案的public目錄下。

點選下載模板按鈕時直接呼叫以下方法即可,其中的saveAs是file-saver外掛中的方法,傳入路徑與檔名即可。

import { saveAs } from 'file-saver';
//下載模板
function downTemp() {
    let fileName = "人員模板.xlsx";//檔名
    let fileUrl = "./template/";//檔案路徑(路徑相對index.html)
    saveAs(fileUrl + fileName, fileName);
}

表格處理好,

點選匯入按鈕讀取表格資料時使用的是xlsx外掛,下面是讀取資料的方法。

import * as XLSX from "xlsx";
//匯入資料
function importData(e) {
    isLoading.value = true;
    let file = e.target.files[0]; //獲取事件中的file物件
    let fileReader = new FileReader(); //建立檔案讀取器
    fileReader.onload = (event) => {
        let result = event.target.result; //獲取讀取的結果
        let workBook = XLSX.read(result, { type: "binary" }); //XLSX讀取返回的結果
        let jsonData = XLSX.utils.sheet_to_json(
            workBook.Sheets[workBook.SheetNames[0]]
        ); //將讀取結果轉換為json
        tabData.value = [];
        jsonData.forEach((j) => {
            tabData.value.push({
                name: j.姓名,
                age: j.性別,
                department: j.部門,
            });
        }); //處理成需要的資料格式
        localStorage.setItem("tabData", JSON.stringify(tabData.value));//資料存入本地
        tabDataS.value = JSON.parse(localStorage.getItem("tabData"));//取出資料
        emits("getNameList", tabData);
        isLoading.value = false;
    };
    fileReader.readAsBinaryString(file); //開始讀取檔案
    ((document.getElementsByClassName("inp-xlsx")[0]).value = ""); //置空選中的檔案
};

結語

  • 專案很簡單,但給我的時間很少,很多最佳化的地方都沒做好,後面有時間了再最佳化下,順便適配下移動端。
  • 原文地址:https://xiblogs.top/?id=53

相關文章