Vue3.0项目——打造企业级音乐App(一)Tab栏、轮播图、歌单列表、滚动组件

news2025/1/24 22:47:35

系列文章目录

内容参考链接
Vue3.0 项目启动Vue3.0 项目启动(打造企业级音乐App)
Vue3.0项目——打造企业级音乐App(一)Tab栏、轮播图、歌单列表、滚动组件
Vue3.0项目——打造企业级音乐App(二)图片懒加载、v-loading指令的开发和优化

文章目录

  • 系列文章目录
    • 项目演示
    • 设置移动端限制
    • 引入全局样式文件
    • Tab 组件实现
    • 获取轮播图接口数据
    • 推荐页轮播图
    • 歌单列表实现 & 滚动组件(可回弹)


项目演示

vue3.0-music

设置移动端限制

该项目为移动端的项目,我们要设置缩放比例为 1,并且禁止用户双击缩放。

在这里插入图片描述

引入全局样式文件

在 main.js 中引入样式文件

import '@/assets/scss/index.scss'

Tab 组件实现

总体效果图:

在这里插入图片描述

header.vue 组件

  • 设置头部组件的内容,样式
  • 两个 icon,一个名字
<template>
  <div class="header">
    <span class="icon"></span>
    <h1 class="text">Joyful Music</h1>
    <router-link class="mine" to="/user">
      <i class="icon-mine"></i>
    </router-link>
  </div>
</template>

<script>
  export default {
    name: 'm-header'
  }
</script>

<style lang="scss" scoped>...</style>

在这里插入图片描述

tab 组件

<template>
  <div class="tab">
    <router-link
      class="tab-item"
      v-for="tab in tabs"
      :key="tab.path"
      :to="tab.path"
    >
      <span class="tab-link">
        {{tab.name}}
      </span>
    </router-link>
  </div>
</template>

<script>
  export default {
    name: 'tab',
    data() {
      return {
        tabs: [
          {
            name: '推荐',
            path: '/recommend'
          },
          {
            name: '歌手',
            path: '/singer'
          },
          {
            name: '排行',
            path: '/top-list'
          },
          {
            name: '搜索',
            path: '/search'
          }
        ]
      }
    }
  }
</script>

<style lang="scss" scoped>...</style>

在这里插入图片描述

App.vue 组件

<template>
  <m-header></m-header>
  <tab></tab>
  <router-view></router-view>
</template>

<script>
import Header from '@/components/header/header.vue'
import Tab from '@/components/tab/tab.vue'

export default {
  components: {
    MHeader: Header,
    Tab
  }
}
</script>

<style lang="scss"></style>

./router/index.js 文件

import { createRouter, createWebHashHistory } from 'vue-router'
import Recommend from '@/views/recommend'
import Singer from '@/views/singer'
import TopList from '@/views/top-list'
import Search from '@/views/search'

const routes = [
  {
    path: '/',
    redirect: '/recommend' // 重定向
  },
  {
    path: '/recommend',
    component: Recommend
  },
  {
    path: '/singer',
    component: Singer
  },
  {
    path: '/top-list',
    component: TopList
  },
  {
    path: '/search',
    component: Search
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

获取轮播图接口数据

./server/base.js 文件

  • 封装 axios
import axios from 'axios'

const ERR_OK = 0
// 开发环境下这样定义baseURL
const baseURL = '/'

axios.defaults.baseURL = baseURL

export function get(url, params) {
    return axios.get(url, {
        params
    }).then((res) => {
        const serverData = res.data
        if (serverData.code === ERR_OK) {
            return serverData.result
        }
    }).catch((e) => {
        console.log(e)
    })
}

./server/recommend.js 文件

  • 获取轮播图接口
  • ./base 里面是后端的一些配置
import { get } from './base'

export function getRecommend() {
    return get('/api/getRecommend')
}

recommend.vue 组件

  • 把刚刚的轮播图文件导入进来
  • async await 异步处理,打印获取的结果
<template>
  <div class="recommend">
    推荐页面
  </div>
</template>

<script>
  import { getRecommend } from '@/service/recommend'
  export default {
    name: 'recommend',
    async created() {
      const result = await getRecommend()
      console.log(result)
    }
  }
</script>

在这里插入图片描述

推荐页轮播图

轮播图效果使用的是 BetterScroll 2.0 参考链接

在这里插入图片描述

./base/slider/use-slider.js 文件

  • 导入轮播图核心滚动和滑动栏
  • 定义滑动栏和当前页
  • new BScroll() 可以接收多个参数,第二个参数可以是对象的形式,里面添加多个参数
import BScroll from '@better-scroll/core'
import Slide from '@better-scroll/slide'

import { onMounted, onUnmounted, ref } from 'vue'

BScroll.use(Slide)

export default function useSlider(wrapperRef) {
    const slider = ref(null)
    const currentPageIndex = ref(0)
    onMounted(() => {
        const sliderVal = slider.value = new BScroll(wrapperRef.value, {
            click: true,
            scrollX: true, // 横向滚动
            scrollY: false,
            momentum: false, // 避免惯性动画带来的快速滚动时的闪烁的问题和快速滑动时一次滚动多页的问题
            bounce: false, // 避免在循环衔接的时候出现闪烁
            probeType: 2, // 在用户拖动 slide 时,实时获取到 slide 的 PageIndex 的改变,需要设置为 2 or 3
            slide: true
        })

        sliderVal.on('slideWillChange', (page) => {
            currentPageIndex.value = page.pageX
        })
    })

    // 销毁
    onUnmounted(() => {
        slider.value.destroy()
    })

    return {
        slider,
        currentPageIndex
    }
}

./component/base/slider/slider.vue 组件

  • 渲染图片和滚动条
<template>
  <div class="slider" ref="rootRef">
    <div class="slider-group">
      <div
        class="slider-page"
        v-for="item in sliders"
        :key="item.id"
      >
        <a :href="item.link">
          <img :src="item.pic"/>
        </a>
      </div>
    </div>
    <div class="dots-wrapper">
      <span
        class="dot"
        v-for="(item, index) in sliders"
        :key="item.id"
        :class="{'active': currentPageIndex === index}">
      </span>
    </div>
  </div>
</template>

<script>
  import { ref } from 'vue'
  import useSlider from './use-slider'

  export default {
    name: 'slider',
    props: {
      sliders: {
        type: Array,
        default() {
          return []
        }
      }
    },
    setup() {
      const rootRef = ref(null)
      const { currentPageIndex } = useSlider(rootRef)
      useSlider(rootRef)
      return {
        rootRef,
        currentPageIndex
      }
    }
  }
</script>

<style lang="scss" scoped>...</style>

./views/recommend.vue 组件

  • 获取数据,绑定到推荐页面上
<template>
  <div class="recommend">
    <div class="slider-warpper">
      <div class="slider-content">
        <slider v-if="sliders.length" :sliders="sliders"></slider>
      </div>
    </div>
  </div>
</template>

<script>
  import { getRecommend } from '@/service/recommend'
  import Slider from '@/components/base/slider/slider'
  export default {
    name: 'recommend',
    components: {
      Slider
    },
    data() {
      return {
        sliders: []
      }
    },
    async created() {
      const result = await getRecommend()
      // 拿到数据
      this.sliders = result.sliders
    }
  }
</script>

歌单列表实现 & 滚动组件(可回弹)

效果图如下:

在这里插入图片描述

./components/scroll/use-scroll.js 文件

observe-dom 插件特性:

  • 针对改变频繁的 CSS 属性,增加 debounce
  • 如果改变发生在 scroll 动画过程中,则不会触发 refresh
import BScroll from '@better-scroll/core'
import ObserveDOM from '@better-scroll/observe-dom'
import { onMounted, onUnmounted, ref } from 'vue'

BScroll.use(ObserveDOM)

export default function useScroll(warpperRef, options) {
    const scroll = ref(null)

    onMounted(() => {
        scroll.value = new BScroll(warpperRef.value, {
            observeDOM: true,
            ...options
        })
    })

    onUnmounted(() => {
        scroll.value.destroy()
    })
}

./component/scroll/scroll.vue 组件

  • 滚动组件使用封装的 js 文件
  • 给 setup 传入默认行为
<template>
  <div ref="rootRef">
    <slot></slot>
  </div>
</template>

<script>
  import useScroll from './use-scroll'
  import { ref } from 'vue'

  export default {
    name: 'scroll',
    // 组件的默认行为
    props: {
      click: {
        type: Boolean,
        default: true
      }
    },
    setup(props) {
      const rootRef = ref(null)
      useScroll(rootRef, props)

      return {
        rootRef
      }
    }
  }
</script>

./views/recommend.vue 组件

<template>
  <div class="recommend">
    <scroll class="recommend-content">
      <div>
        <div class="slider-wrapper">
          <div class="slider-content">
            <slider v-if="sliders.length" :sliders="sliders"></slider>
          </div>
        </div>
        <div class="recommend-list">
          <h1 class="list-title">热门歌单推荐</h1>
          <ul>
            <li
              v-for="item in albums"
              class="item"
              :key="item.id"
            >
              <div class="icon">
                <img width="60" height="60" :src="item.pic">
              </div>
              <div class="text">
                <h2 class="name">
                  {{ item.username }}
                </h2>
                <p class="title">
                  {{item.title}}
                </p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </scroll>
  </div>
</template>

<script>
  import { getRecommend } from '@/service/recommend'
  import Slider from '@/components/base/slider/slider'
  import Scroll from '@/components/base/scroll/scroll'

  export default {
    name: 'recommend',
    components: {
    Slider,
    Scroll
},
    data() {
      return {
        sliders: [],
        albums: []
      }
    },
    async created () {
      const result = await getRecommend()
      this.sliders = result.sliders
      this.albums = result.albums
    }
  }
</script>

不积跬步无以至千里 不积小流无以成江海

点个关注不迷路,持续更新中…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/407865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

路由守卫的详解

路由守卫总共有7个 全局路由守卫: beforeEach 前置守卫 affterEach 后置守卫 beforeResolve 解析守卫 路由的守卫 beforeRouterEnter 进入组件之前触发,在Created前面 beforeRouterUpdated 路由更新但是内容不会改变 beforeRouterLeave 离开之前触发,在beforeDestory之前…

vue3 - ref和reactive的区别

文章搬运自wx60d4764eb475e 的vue3中ref和reactive的区别&#xff08;系列六&#xff09; 1. ref和reactive区别: 如果在template里使用的是ref类型的数据, 那么Vue会自动帮我们添加.value 如果在template里使用的是reactive类型的数据, 那么Vue不会自动帮我们添加.val…

ErrorCaptureStackTrace(err); Error [ERR_MODULE_NOT_FOUND]: Cannot find module

目录结构 main.js import { Name, say, Person } from ./testconsole.log(Name)test.js const Name life function say() {console.log(Mine) } let Person { name: good }export { Name, say, Person }问题分析 步骤有点啰嗦&#xff0c;犯错的原因其实就很简单&#xff…

Vue自定义指令原来这么简单

本篇学习目标 能够了解组件进阶知识能够掌握自定义指令创建和使用能够完成tabbar案例的开发 1. 组件进阶 1.0 组件进阶 - 动态组件 目标: 多个组件使用同一个挂载点&#xff0c;并动态切换&#xff0c;这就是动态组件 需求: 完成一个注册功能页面, 2个按钮切换, 一个填写注册…

微信小程序(四)--- 自定义组件详解(properties,数据监听器,纯数据字段,插槽,父子间通信,behaviors)

目录 一、创建组件 二、引用组件 1、局部引用 2、全局引用 三、组件和页面的区别 四、组件样式隔离 1、注意点 2、修改组件的样式隔离选项 五、数据、方法、属性 1、data数据 2、methods方法 3、properties属性 4、data和properties的区别 5、使用setData修改proper…

AndroidStudio网格布局(制作计算机界面)

目录 网格布局特点&#xff08;类似于表格&#xff09; 常用属性&#xff1a; 针对布局的属性 针对子控件的属性 实例演示 创建一个安卓应用插入一张背景图片&#xff08;可以不加&#xff09; 打开字符串资源文件 strings.xml改应用标题名字&#xff08;可不改&#xf…

uniapp微信公众号h5微信授权登录

前言 在微信客户端中访问第三方网页&#xff0c;公众号可通过微信网页授权机制&#xff0c;来获取用户基本信息&#xff0c;进而实现业务逻辑。 关于公众号网页授权前期准备&#xff1a; 1.微信公众号开发&#xff0c;首先要搞一个公众号&#xff0c;开发阶段可以申请一个公众…

element ui+vue实现导航栏菜单以及页面跳转

关于博主&#xff1a; 不知道算不算的上入门&#xff0c;就是刚刚学习vue框架&#xff0c;断断续续的学习&#xff0c;所以有些地方讲的不正确也欢迎大家批评斧正&#xff0c;希望与大家共同进步 问题描述 对于初学前端的我们来说搭建一个路由导航界面还是比较困难的&#xf…

Web基础知识

1&#xff0c;Web基本概念和常识 ①web应用&#xff1a;网站&#xff08;广义上的PC&#xff0c;手机app&#xff09; ②浏览器&#xff08;Browser&#xff09;&#xff1a;也称用户代理&#xff0c;web客户端&#xff0c;主要有IE、Edge、Chrome、Firefox、腾讯浏览器&#x…

nvm 安装使用及配置淘宝下载镜像

NVM介绍 NVM全称node.js version management &#xff0c;专门针对node版本进行管理的工具&#xff0c;通过它可以安装和切换不同版本的node.js。 MVM下载 githhub下载地址&#xff0c;选择nvm-setup.zip&#xff1a;安装版&#xff0c;推荐使用 https://github.com/coreyb…

Antv X6 动态连线

这是我实际开发项目中&#xff0c;利用 X6 开发的一个关系图。具备连线功能。这里我尽可能全的记录整个开发思路和部分编码&#xff0c;如果你也用了 X6 希望对你有帮助。 创建画布 代码有删减&#xff0c;以下展示的代码全都有删减 index.vue <template><div id&q…

React组件化的额外知识补充

文章目录React的额外补充Portals的使用Fragment的使用严格模式StrictModeReact的额外补充 Portals的使用 某些情况下&#xff0c;我们希望渲染的内容独立于父组件&#xff0c;甚至是独立于当前挂载到的DOM元素中(默认都是挂载到id为root的DOM 元素上的)。 Portal 提供了一种…

【vue】 vue-router安装和配置方法

vue-router 是 vue.js 官方的路由插件&#xff0c;里面组件和 URL 的映射关系由 vue-route 帮我们管理。 在 vue-router 的单页面应用中&#xff0c;页面的路径的改变就是组件的切换。 第一步&#xff1a; 1.正常初始化项目的时候&#xff0c;会有个 vue-router 供我们选择。…

在VSCode中配置代码自动 eslint 格式化(修改eslint规则、eslint忽略文件)

一、Eslint Eslint 是用来检测和规范代码格式的工具&#xff0c;应用在工程化项目中&#xff0c;可以保证项目代码格式的一致性和规范性&#xff0c;大大提升了代码的可读性。 二、配置过程 本博客是讲述对一个已经引用 eslint 依赖Nuxt项目&#xff08;vue项目应该相同&…

vue-cli脚手架的下载安装(靠谱)

找了半天才找到一个靠谱的安装教程&#xff0c;分享给你们。 1. 先下载node.js&#xff0c;下载地址&#xff1a;Download | Node.jsNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/en/download/直接进入下载电脑对应的版本&…

vue-cli创建vue项目详细步骤

一、安装node环境&#xff08;建议使用LTS&#xff09; Download | Node.js 二、下载vue和vue-cli脚手架 命令&#xff1a;npm i -g vue ; npm i -g vue/cli 三、在想要创建的位置路径下打开cmd&#xff08;直接点击路径输入cmd即可打开当前位置的终端&#xff09; 四、创建v…

Vue使用Element-UI的table组件和后端接口进行数据交互(包含前后端代码)

前言 本次用element-ui的table组件&#xff0c;简单案例演示下前后端数据交互。 前提声明&#xff1a;如果不知道如何在vue中引入element-ui&#xff0c;可以先看下这篇文章:Vue引入并使用Element-UI组件库的两种方式 静态页面 首先先写一个静态页面吧&#xff0c;数据都是…

Vue3的vue-router路由详解

这篇文章是接着【三分钟快速搭建Vue3webpack项目】的内容做的开发&#xff0c;有基础的可以跳过 【三分钟快速搭建Vue3webpack项目】&#xff0c;直接看以下的内容。 Vue3的vue-router路由详解&#xff1a; 首先安装路由依赖模块&#xff1a; npm install vue-router4 所需…

618快到了送上自制前端小项目(html css js)

目录 &#x1f6a9;.自定义播放器 &#x1f3e0;.图片自动消失 ✨.小轮播图 &#x1f383;.旋转音乐盒 前言&#xff1a;这些小项目全都是自创的。 如果需要应用&#xff0c;或则转发的话请与 博主联系&#xff0c;感谢你们的理解&#xff0c; 1.自定义播放器 在页面中放置…

云化Web IDE,在线开发新模式

目录 前言 一、初识云IDE 二、CSDN 云IDE 1、如何使用云IDE 2、使用云IDE 三、云IDE的使用感受 四、总结 前言 工欲善其事必先利其器&#xff0c;作为程序员&#xff0c;我们在编写代码的时候&#xff0c;一定会选用一款得心应手的工具。就像行走江湖的侠客&#xff0c;手…