Vue.js 超实用项目:从零搭建音乐榜单投票系统,全流程教学 初学者友好:Vue.js 实现投票系统(附完整代码和功能解析) 前端新手必看!用 Vue.js 实现动态音乐榜单投票功能 实战 Vue.

效果图

在这里插入图片描述

Vue.js 音乐榜单投票系统:详细实现与代码解析

目录
  1. 引言
  2. 项目概述
  3. 步骤一:项目环境准备
  4. 步骤二:页面布局与样式
  5. 步骤三:实现艺人数据动态显示
  6. 步骤四:实现投票功能与次数限制
  7. 步骤五:显示投票占比与限制剩余投票次数
  8. 附加功能:投票按钮动画与提示
  9. 完整代码
  10. 总结

引言

在本教程中,我们将使用 Vue.js 构建一个音乐榜单投票页面。用户可以为艺人投票,且每个用户有 5 次投票的总次数限制。我们将逐步解析代码的每一部分,并最终构建一个带有动态投票排名、投票次数限制的页面。


项目概述

这个投票系统展示了多个艺人的排名。每个艺人都显示有票数、投票按钮和投票百分比。每个用户最多只能为每个艺人投一次票,且总共只能投票 5 次。


步骤一:项目环境准备

  1. 引入 Vue.js:
    通过在线 CDN 的方式加载 Vue.js,无需复杂的安装过程。
<script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
  1. 基础 HTML 结构:
    在 HTML 中,创建一个 div,用来作为 Vue.js 管理的挂载点。
<div id="app"></div>

步骤二:页面布局与样式

我们先定义页面的基本布局和样式。布局将包括一个标题、艺人列表、投票按钮等。

<style>
    body {
      
      
        font-family: Arial, sans-serif;
        margin: 0;
        padding: 0;
        background-color: #000;
        color: #fff;
        text-align: center;
    }

    #app {
      
      
        max-width: 900px;
        margin: 0 auto;
        padding: 20px;
    }

    h1 {
      
      
        font-size: 24px;
        margin-bottom: 30px;
    }

    .artist-list {
      
      
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        gap: 20px;
    }

    .artist {
      
      
        background-color: #222;
        padding: 20px;
        border-radius: 10px;
        text-align: center;
    }

    .avatar {
      
      
        width: 100px;
        height: 100px;
        background-color: #666;
        border-radius: 50%;
        margin-bottom: 15px;
        line-height: 100px;
        color: white;
        font-size: 20px;
    }

    .artist button {
      
      
        background-color: #ffcc00;
        color: black;
        padding: 10px 20px;
        border-radius: 5px;
        cursor: pointer;
        transition: transform 0.2s ease;
    }

    .artist button:hover {
      
      
        background-color: #ffaa00;
    }
</style>
代码解释:
  • artist-list:艺人列表的布局使用了 CSS 的 grid 布局,方便控制每行艺人卡片的显示。
  • .avatar:为艺人的头像设置圆形背景色块,使用 CSS 的 border-radius: 50% 实现。
  • .artist button:设置投票按钮的样式,并添加了一些 hover 效果和点击动画。

步骤三:实现艺人数据动态显示

接下来,我们在 Vue.js 的 data 中定义艺人的数据,并通过 v-for 指令动态渲染这些艺人。

new Vue({
    
    
  el: '#app',
  data: {
    
    
    artists: [
      {
    
     name: '周深', votes: 4312456 },
      {
    
     name: '华晨宇', votes: 3303502 },
      {
    
     name: '薛之谦', votes: 457070 },
      {
    
     name: '毛不易', votes: 166685 },
      {
    
     name: '汪苏泷', votes: 85262 },
      {
    
     name: '许嵩', votes: 56455 }
    ]
  }
});

在 HTML 中,使用 v-for 循环生成每个艺人的卡片。

<div class="artist-list">
    <div v-for="(artist, index) in artists" :key="index" class="artist">
        <div class="avatar">{
   
   { artist.name.charAt(0) }}</div>
        <h2>{
   
   { artist.name }}</h2>
        <p>{
   
   { artist.votes }} 票</p>
        <button>投票</button>
    </div>
</div>
代码解释:
  • v-for:用于循环渲染艺人列表,artist.name.charAt(0) 获取艺人名字的首字母来代替头像。

步骤四:实现投票功能与次数限制

我们将为投票按钮添加点击事件,每个用户最多只能投 5 次票,并且每个艺人只能投一次票。

data: {
    
    
    totalVotesLeft: 5,
    artists: [
      {
    
     name: '周深', votes: 4312456, voted: false },
      {
    
     name: '华晨宇', votes: 3303502, voted: false },
      {
    
     name: '薛之谦', votes: 457070, voted: false },
      // 更多艺人
    ]
},
methods: {
    
    
    vote(index) {
    
    
      if (this.artists[index].voted) {
    
    
        alert(`你已经为 ${
      
      this.artists[index].name} 投过票了!`);
      } else if (this.totalVotesLeft > 0) {
    
    
        this.artists[index].votes += 1;
        this.artists[index].voted = true;
        this.totalVotesLeft -= 1;
        alert(`你为 ${
      
      this.artists[index].name} 投了一票!`);
      } else {
    
    
        alert('你已没有剩余投票次数。');
      }
    }
}

步骤五:显示投票占比与限制剩余投票次数

为每个艺人的票数计算占比,并展示剩余的投票次数。

<p class="percentage">占比: {
   
   { ((artist.votes / totalVotes) * 100).toFixed(2) }}%</p>
<div class="limit-info">
    剩余投票次数:{
   
   { totalVotesLeft }}/5
</div>
代码解释:
  • ((artist.votes / totalVotes) * 100).toFixed(2):通过公式计算艺人票数占比,保留两位小数。
  • totalVotesLeft:显示剩余的总投票次数。

附加功能:投票按钮动画与提示

为按钮添加点击时的动画效果,提升用户体验。通过 transform 来实现按下按钮时的缩放效果。

.artist button:active {
    
    
    transform: scale(0.95);
}

完整代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>音乐榜单投票 - Vue.js 实现</title>
    <script src="https://cdn.staticfile.net/vue/2.7.0/vue.min.js"></script>
    <style>
        body {
      
      
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #000;
            color: #fff;
            text-align: center;
        }

        #app {
      
      
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
        }

        h1 {
      
      
            font-size: 24px;
            margin-bottom: 30px;
        }

        .artist-list {
      
      
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 20px;
        }

        .artist {
      
      
            background-color: #222;
            padding: 20px;
            border-radius: 10px;
            box-shadow: 0 4px 8px rgba(255, 255, 255, 0.1);
            text-align: center;
            position: relative;
        }

        .artist .avatar {
      
      
            width: 100px;
            height: 100px;
            background-color: #666;
            border-radius: 50%;
            margin-bottom: 15px;
            display: inline-block;
            line-height: 100px;
            color: #fff;
            font-size: 20px;
        }

        .artist h2 {
      
      
            font-size: 20px;
            margin: 10px 0;
        }

        .artist p {
      
      
            font-size: 16px;
            margin: 5px 0;
        }

        .artist button {
      
      
            background-color: #ffcc00;
            border: none;
            color: black;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            transition: transform 0.2s ease;
        }

        .artist button:hover {
      
      
            background-color: #ffaa00;
        }

        .artist button:active {
      
      
            transform: scale(0.95);
        }

        .percentage {
      
      
            margin-top: 10px;
            font-size: 14px;
            color: #ddd;
        }

        .limit-info {
      
      
            margin-top: 20px;
            font-size: 16px;
            color: #ff6600;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>华语艺人 / 团体 投票榜单</h1>

    <!-- 总票数展示 -->
    <p>总票数:{
   
   { totalVotes }}</p>
    <div class="artist-list">
        <div v-for="(artist, index) in sortedArtists" :key="index" class="artist">
            <div class="avatar">{
   
   { artist.name.charAt(0) }}</div>
            <h2>{
   
   { index + 1 }}. {
   
   { artist.name }}</h2>
            <p>{
   
   { artist.votes }} 票</p>
            <p class="percentage">占比: {
   
   { ((artist.votes / totalVotes) * 100).toFixed(2) }}%</p>
            <button @click="vote(index)">
                投票
            </button>
        </div>
    </div>

    <!-- 投票限制信息 -->
    <div class="limit-info">
        剩余投票次数:{
   
   { totalVotesLeft }}/5
    </div>
</div>

<script>
new Vue({
      
      
  el: '#app',
  data: {
      
      
    totalVotes: 0, // 总票数
    totalVotesLeft: 5, // 剩余投票次数限制
    artists: [
      {
      
       name: '周深', votes: 4312456, voted: false },
      {
      
       name: '华晨宇', votes: 3303502, voted: false },
      {
      
       name: '薛之谦', votes: 457070, voted: false },
      {
      
       name: '毛不易', votes: 166685, voted: false },
      {
      
       name: '汪苏泷', votes: 85262, voted: false },
      {
      
       name: '许嵩', votes: 56455, voted: false },
      {
      
       name: '张杰', votes: 32887, voted: false },
      {
      
       name: '陈奕迅', votes: 31789, voted: false },
      {
      
       name: '林俊杰', votes: 30176, voted: false },
      {
      
       name: '田馥甄', votes: 30176, voted: false },
      {
      
       name: 'NINEONE#', votes: 30176, voted: false },
      {
      
       name: 'G.E.M.邓紫棋', votes: 30176, voted: false }
    ]
  },
  computed: {
      
      
    // 计算已排序的艺人列表
    sortedArtists() {
      
      
      return this.artists.slice().sort((a, b) => b.votes - a.votes);
    }
  },
  methods: {
      
      
    vote(index) {
      
      
      if (this.artists[index].voted) {
      
      
        alert(`你已经为 ${ 
        this.artists[index].name} 投过票了!`);
      } else if (this.totalVotesLeft > 0) {
      
      
        this.artists[index].votes += 1;
        this.artists[index].voted = true;
        this.totalVotes += 1;
        this.totalVotesLeft -= 1;
        alert(`你为 ${ 
        this.artists[index].name} 投了一票!`);
      } else {
      
      
        alert('你已没有剩余投票次数。');
      }
    }
  },
  mounted() {
      
      
    this.totalVotes = this.artists.reduce((sum, artist) => sum + artist.votes, 0);
  }
});
</script>
</body>
</html>


总结

在本教程中,我们使用 Vue.js 构建了一个音乐榜单投票系统,涵盖了页面布局、投票逻辑、投票次数限制等功能,并为投票按钮添加了简单的交互动画。这个项目是前端开发的一个实用练习,适合初学者熟悉 Vue.js 的基本操作。


希望这篇详细的教程能够帮助你顺利完成投票系统的开发。如果你对前端开发感兴趣,请记得订阅我的博客,获取更多实用项目的源码与教程!

猜你喜欢

转载自blog.csdn.net/qq_22182989/article/details/143175424