您好,欢迎来到百家汽车网。
搜索
您的当前位置:首页Vue3项目自学训练------音乐播放器(开源项目)(二)

Vue3项目自学训练------音乐播放器(开源项目)(二)

来源:百家汽车网


一、安装axios

npm install axios --save

二、请求数据(封装)

在src下创建service文件夹下的base.js用于封装axios

// 导入
import axios from 'axios'
// url路径地址  params可选参数
export function get(url, params) {
    return axios.get(url, {
        params
    }).then(res => {
        return res.data // 返回响应的data数据
    }).catch(err => {
        throw err
    })
}

三、自定义轮播组件

1、推荐页

recommend.js

// 推荐页相关的数据
import { get } from './base'

//请求轮播数据
export function getRecommend() {
    // 直接定义接口
    return get('/banner', {
        type: 2
    })
}

Recommend.vue(记得异步要加async await)

<script setup>
import { getRecommend } from "@/service/recommend";
import { onMounted, ref } from "vue";
import MySlider from "@/components/base/Slider"

onMounted(() => {
    // 调用接口地址
    const result = getRecommend();
    console.log(result);
})


const sliders = ref([])

onMounted(async () => {
    // 调用接口地址
    const result = await getRecommend();
    console.log(result);
    sliders.value = result.banners;
});
</script>

打印结果

 安装better-scroll

> npm install @better-scroll/core --save
> npm install @better-scroll/slide --save

 抽离组件功能

在components下面创建base文件夹下面Slider.vue

<template>
  <!-- // 封装轮播组件 -->
  <div class="slider" ref="rootRef">
    <div class="slider-group">
      <div class="slider-page" v-for="(item, index) in sliders" :key="index">
        <img :src="item.pic" alt="" />
      </div>
    </div>
    <div class="dots-wrapper">
      <span
        class="dot"
        v-for="(item, index) in sliders"
        :key="index"
        :class="{ active: index === currentIndex }"
      ></span>
    </div>
  </div>
</template>

<script setup>
import { useSlider } from "@/assets/js/useSlider";

const props = defineProps({
  sliders: {
    type: Array,
    require: true,
  },
}); //Recommend组件传来的数据

const { rootRef, currentIndex } = useSlider();
</script>

<style lang="scss" scoped>
.slider {
  min-height: 1px;
  font-size: 0;
  // 启用单手垂直移动
  touch-action: pan-y;
  position: relative;
  .slider-group {
    position: relative;
    overflow: hidden;
    white-space: nowrap;
    .slider-page {
      display: inline-block;
      transform: translate3d(0, 0, 0);
      backface-visibility: hidden;
      img {
        display: block;
        width: 100%;
      }
    }
  }
  .dots-wrapper {
    position: absolute;
    left: 50%;
    bottom: 12px;
    line-height: 12px;
    transform: translateX(-50%);
    .dot {
      display: inline-block;
      margin: 0 4px;
      width: 8px;
      height: 8px;
      transform: translateZ(1px);
      border-radius: 50%;
      background-color: $color-text-l;
      &.active {
        width: 20px;
        border-radius: 5px;
        background: $color-text-ll;
      }
    }
  }
}
</style>

在assets下创建js文件夹下useSlider.js

import BScroll from "@better-scroll/core";
import Slide from "@better-scroll/slide";
import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from "vue";

BScroll.use(Slide)

// 第一个参数元素节点,第二个参数配置项
export function useSlider() {
    // 创建slider对象
    const slider = ref(null)
    const rootRef = ref(null)
    const currentIndex = ref(0)

    onMounted(() => {
        // new BScroll(需要挂载的DOM,配置对象:支持的功能)
        slider.value = new BScroll(rootRef.value, {
            slide: true,//插件激活
            click: true,//允许点击
            scrollX: true,//横向滚动
            scrollY: false,//不允许纵向滚动
            momentum: false,//不根据滑动的距离和时间计算生成滚动动画
            bounce: false,//不需要回弹动画
            probeType: 2,//派发scroll事件的频率,仅当手指按在滚动区域上,一直派发scroll事件
        })
        // 页面页码发生变化时触发这个事件
        slider.value.on('slideWillChange', (page) => {
            currentIndex.value = page.pageX
        })
    })

    // 销毁时
    onUnmounted(() => {
        slider.value.destroy()
    })
    // 激活时
    onActivated(() => {
        slider.value.enable//恢复功能
        slider.value.refresh//刷新一下
    })
    // 失活时
    onDeactivated(() => {
        slider.value.enable//恢复功能
    })


    return {
        rootRef,
        currentIndex
    }
}

2、热门歌单推荐

recommend.js

// 推荐页相关的数据接口
import { get } from './base'


//请求热门歌单推荐数据
export function getRecommendAlbum() {
    // 直接定义接口
    return get('/top/playlist', {
        limit: 30
    })
}

 Recommend.vue

<template>
  <div class="recommend">
    <my-scroll class="recommend-content">
      <div>
        <!-- 轮播 -->
        <div class="slider-wrapper">
          <div class="slider-content">
            <my-slider v-if="sliders.length" :sliders="sliders"></my-slider>
          </div>
        </div>
        <!-- 热门歌单推荐 -->
        <div class="recommend-list">
          <h2 class="list-title">热门歌单推荐</h2>
          <ul>
            <li
              class="recommend-item"
              v-for="(item, index) in albums"
              :key="item.id"
            >
              <div class="icon">
                <img :src="item.coverImgUrl" width="60" height="60" alt="" />
              </div>
              <div class="text">
                <p class="name">{{ item.name }}</p>
                <p class="description">{{ item.description }}</p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </my-scroll>
  </div>
</template>

<script setup>
import { getRecommend, getRecommendAlbum } from "@/service/recommend";
import { onMounted, ref } from "vue";
import MySlider from "@/components/base/Slider";
import MyScroll from "@/components/base/Scroll";

const sliders = ref([]);
const albums = ref([]);

onMounted(async () => {
  // 获取轮播数据
  // 调用接口地址
  const result = await getRecommend();
  // console.log(result);
  sliders.value = result.banners;
  // 获取热门歌单推荐数据
  const albumResult = await getRecommendAlbum();
  // console.log(albumResult);
  albums.value = albumResult.playlists;
});
</script>

<style lang="scss" scoped>
.recommend {
  position: fixed;
  width: 100%;
  top: 88px;
  bottom: 0;
  overflow: scroll;
  .recommend-content {
    height: 100%;
    overflow: hidden;
    .recommend-list {
      .list-title {
        height: 65px;
        line-height: 65px;
        text-align: center;
        font-size: $font-size-medium;
        color: $color-theme;
      }
      .recommend-item {
        display: flex;
        box-sizing: border-box;
        align-items: center;
        padding: 0 20px 20px 20px;
        .icon {
          flex: 0 0 60px;
          width: 60px;
          padding-right: 20px;
        }
        .text {
          display: flex;
          flex-direction: column;
          justify-content: center;
          flex: 1;
          line-height: 20px;
          overflow: hidden;
          font-size: $font-size-medium;
        }
        .name {
          margin-bottom: 10px;
          color: $color-text-ll;
        }
        .description {
          @include no-wrap();
          color: $color-text-d;
        }
      }
    }
  }
}
</style>

安装回弹效果并封装

> npm install @better-scroll/observe-dom --save

在assets下js文件夹中创建useScroll.js

import BScroll from '@better-scroll/core'
import ObserveDOM from '@better-scroll/observe-dom'
import { onActivated, onDeactivated, onMounted, onUnmounted, ref } from 'vue'
BScroll.use(ObserveDOM)

export function useScroll(props) {
    const rootRef = ref(null)
    const scroll = ref(null)

    onMounted(() => {
        scroll.value = new BScroll(rootRef.value, {
            observeDOM: true, //开启observe-dom插件,深度监听
            ...props
        })
        // 获取实时滚动距离
        // if(props.probType > 0) {
        //     // 外层时betterscroll对象,自带的
        //     scroll.value.on('scroll', (pos) => {
        //         // 触发父组件内的scroll自定义事件
        //         defineEmits('scroll', pos)
        //     })
        // }
    })
    onUnmounted(() => {
        // 销毁
        scroll.value.destroy()
    })
    onActivated(() => {
        // 恢复功能 
        scroll.value.enable()
        // 刷新
        scroll.value.refresh()
    })
    onDeactivated(() => {
        // 失去功能
        scroll.value.disable()
    })

    return {
        rootRef
    }
}

在components下base文件夹中创建Scroll.vue

<template>
  <div class="" ref="rootRef">
    <slot></slot>
  </div>
</template>

<script setup>
import { useScroll } from "@/assets/js/useScroll";
const props = defineProps({
  probeType: {
    type: Number,
    default: 1,
  },
});
const { rootRef } = useScroll(props);
</script>

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

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- baijiahaobaidu.com 版权所有 湘ICP备2023023988号-9

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务