Loading

云音乐播放器项目总结

1.创建项目

1.1引入Vue Cli脚手架

作用

Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。与此同时,它也为每个工具提供了调整配置的灵活性,无需 eject

安装

npm install -g@vue/cli

确认方式

vue --version

创建项目

1.创建项目

​ 生命新目录何文件结构,不嵌套在其他文件钟

2.输入命令

vue create 项目名

​ 2.1注意事项不要使用中文

​ 2.2cd切换项目目录

​ 2.3执行命令

npm run serve

Git

1.初始化本地仓库 git init

2.创建之后会有一个.gitinore,会写入git忽略的文件

	2.1.gitignore只能忽略原来没有被跟踪的文件,因此跟踪过的文件是无法被忽略的。因此在网页上可以看到target等目录的存在。

解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:

3.创建项目一般只有一次

1.2 创建的项目结构

1.2.1 目录结构

image-20210604151653337

1.2.2 main.js结构

// 导入Vue构造函数
import Vue from 'vue'
// 导入App.vue单文件组件
import App from './App.vue'
// Vue.config设置,productionTip生产提示
Vue.config.productionTip = false
// 实例化对象
new Vue({
//  渲染, 把App.vue这个组件解析为Vue实例的内部结构
	render:h=>h(App)
}).$mount('#app')

Vue渲染机制

image-20210607200449088

Vue响应式机制

image-20210607200421099

1.2.3 注意

在项目复制时,可以不复制module文件,通过package.json就可以安装下载

npm i 会自动下载根据,//dependencies:依赖,依靠

用到的依赖

image-20210607201254986

2.引入router管理器

Vue Router 是Vue.js官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得简单

路由概念:

​ 路由是指路由器从一个接口上收到数据包,根据数据包的目的地址进行定向并转发到另一个接口的过程。路由通常与桥接来对比,在粗心的人看来,它们似乎完成的是同样的事。它们的主要区别在于桥接发生在OSI参考模型的第二层(数据链路层),而路由发生在第三层(网络层)。这一区别使二者在传递信息的过程中使用不同的信息,从而以不同的方式来完成其任务。

路由工作包含两个基本的动作:

​ 1、确定最佳路径

​ 2、通过网络传输信息

在路由的过程中,后者也称为(数据)交换。交换相对来说比较简单,而选择路径很复杂

2.0单页应用

多页应用 单页应用
一个项目中有多个完整的的HTML文件 一个项目中只有一个完整的HTML页面(index.html)
可以使用超链接、js实现页面间的跳转 可以使用改进后的超链接、js实现模板页面间的切换
传统的页面跳转是同步请求:在服务器生成响应内容时,客户端是一片空白 模板页面间的切换属于经典的异步请求:直到下一个模板页面来到,前一个模板页面到来,前一个模板页面才从当前DOM树上删除
页面跳转时,前一个DOM树无用了,需要从浏览器中全部删除,然后等待下一个DOM树的到来 index.html到来时,浏览器创建一个DOM树。所有的请求都是xhr,到来时只需要作为一个片段挂载在当前DOM树——浏览器从始至终只有一个DOM树
当网速比较慢时(尤其是移动端应用中时),用户体验极为不好! 不会出现一片惨白的情形,浏览体验好。
页面切换时,DOM被完整的删除,不可能有过场动画! 页面切换的本质是DIV的轮换,可以很容易实现漂亮的过场动画。

2.1.使用

下包

npm install vue-router

导包

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

使用

将所有的routes参数配置给router实例化对象,从而让整个应用都有路由的功能

//使用模块化的编程,导入Vue和VueRouter,之后必须调用Vue.use(VueRouter)
//创建和挂载根实例
//引入组件home

import home from '../views/home.vue'

const routes = [
    {
    	//路径
    path: '/home',
        //名字
    name: 'home',
        //注册对应路径的组件,在App的<router-view/>处渲染
    component: home
  },
]
                
const router = new VueRouter({
  routes//routes:routes
}).$mount('#app')

export default router

将暴露的router对象引入到main.js上

image-20210607205420976

将引入的router添加到main.js页面的Vue构造函数上,挂载到app上,让整个app都可以使用router路由

image-20210607205512657

注:render函数是vue通过js渲染dom结构的函数createElement,约定可以简写为h

$mount()手动挂载:

这里创建的vue实例没有el属性,而是在实例后面添加了一个$mount(’#app’)方法。$mount(’#app’) :手动挂载到id为app的dom中的意思.当Vue实例没有el属性时,则该实例就没有挂载到某个dom中. 假如需要延迟挂载,可以在之后手动调用vm.$mount()方法来挂载。

2.1组件的安装方式

一种是将这个插件的逻辑封装成一个对象最后将最后在install编写业务代码暴露给Vue对象。这样做的好处是可以添加任意参数在这个对象上方便将install函数封装得更加精简,可拓展性也比较高,比如Vue-Router。
还有一种则是将所有逻辑都编写成一个函数暴露给Vue,不需要使用Vue.use(),直接引入就可以比如axios。
其实两种方法原理都一样,无非第二种就是将这个插件直接当成install函数来处理。

1.对应关系

image-20210604161305664

2.作用

​ 超链接标签

​ 实现跳转

2.3.router-view

1.作用

​ 匹配到的注册的组件,直接传递到对应的渲染的位置

2.查看高亮类名

​ 查看元素

3.通过$0可以复制审查元素

image-20210607212443535

4.由路由管理的页面一般要放在views当中进行管理

​ 那些是路由管理的页面?

//在router中import导入的组件都是被管理的页面,比如在router的index.js中
import home from '../views/home.vue'
import find from '../views/find.vue'
import play from '../views/play.vue'

2.4.路由传参的两种方式

1.1 url携带:get传参

路由地址?key=value&key2=value2

1.2 编程式导航,query对象传参

//分开写,编程 /地址?key=value
this.$router.push({path:'路由地址',query:{key:'value'}    })
this.$router.push({path:'路由地址?key=value&key2=value2'})

注意:

this.$router,可以跳转

this.$route,可以获取参数

3.引入Vant组件

传送门:vant-gitee主页

下包

# Vue 2 项目,安装 Vant 2:
npm i vant -S

# Vue 3 项目,安装 Vant 3:
npm i vant@next -S

导包

方式三. 导入所有组件
Vant 支持一次性导入所有组件,引入所有组件会增加代码包体积,因此不推荐这种做法。

import Vue from 'vue';
import Vant from 'vant';
import 'vant/lib/index.css';

Vue.use(Vant);

注意事项

使用事项:

1.在文档拷贝HTML之外还要拷贝逻辑

​ 结构中用到的东西再script中得定义

2.通过基本实例找到需要的效果,整合进来

3.组件库的样式整合

4.引入axios组件

4.1什么是axios

`特征和作用`
制作的XMLHttpRequest从浏览器
让HTTP从node.js的请求
支持Promise API
拦截请求和响应
转换请求和响应数据
取消请求
JSON 数据的自动转换
客户端支持防止XSRF

4.2使用axios

设置默认的基地址

axios.defaults.baseURL = 'https://api.example.com';

示例代码

<template>
  <div></div>
</template>

<script>
import axios from 'axios'
axios.defaults.baseURL = 'https://autumnfish.cn/api'
export default {
  created () {
   //设置了基地址直接写后面就行

    axios({
      url: '/joke/list',
      params: {
        num: 3
      },
      method: 'get'
    }).then(res => {
      console.log('笑话接口')
      console.log('res:', res)
    })
  }
}
</script>

<style></style>

4.2.1-- axios挂载

为了方便多个页面使用axios,每个页面导入一次太繁琐,我们可以直接把axios丢到原型上

TP--组件基础

通过构造函数的prototype访问,设置给原型的属性,方法,所有的实例化对象

为了区别与Vue上的原型,约定用$加以区分

注意点

1.常规访问原型是通过构造函数.prototype

​ 1.实例化对象.__proto__也可以访问

2.原型让所有的实例化对象都公用对象上的属性和方法

4.3整合axios(与末尾整合不同,整合--1)

1.下包

npm i axios

2.导包

main.js文件导入

设置基地址

添加到原型

image-20210605105911453

3.为什么建议用$开头?

  1. 官方文档也是这么玩的

  2. 比如$route$router都是丢在了原型上

  3. 区别于Vue原型上的属性

5.首页

5.1首页底部导航区域

vant -- tabbar

结构

    <!-- 地址--组件渲染的位置 -->
    <router-view/>
    <!-- 底部的tabbar -->
        //设置绑定的数据
    <van-tabbar v-model = "active" route active-color = "#ee0a24" placeholder>
        //跳转到home
      <van-tabbar-item to = "/home" icon = "home-o">首页</van-tabbar-item>
		//跳转到find
      <van-tabbar-item to = "/find" icon = "search">搜索</van-tabbar-item>
    </van-tabbar>

逻辑

export default {
  data() {
    return {
      active: 0,
    };
  },
};

active是默认选中的导航标签的索引,这里只有0和1

设置了routes参数(在router文件的index.js上)

在APP.vue页面内部需要设置to属性才可以保证正常的切换效果

const routes = [
  {
    path: '/home',
    name: 'home',
    component: home
  }]

5.2整合三个组件页面和路由

页面:

  1. find:搜索
  2. home:首页
  3. play:播放

静态资源:assets

路由:vue add router

整理后的项目文件

image-20210605115825436

路由和组件的关系--1

image-20210605144232661

路由和组件的挂载渲染--2

image-20210605144521938

5.2首页轮播图

vant - 轮播图组件

<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
  <van-swipe-item>1</van-swipe-item>
  <van-swipe-item>2</van-swipe-item>
  <van-swipe-item>3</van-swipe-item>
  <van-swipe-item>4</van-swipe-item>
</van-swipe>

使用vant轮播图组件

1.使用v-for循环获取数据并添加

​ 1.设置给遍历数据唯一的key

​ 2.设置基地址在main.js

2.created钩子函数是在实例创建完成后被立即调用,方便键返回数据的banners在渲染之前添加到轮播数据的数组banners当中,播放页面所有的数据请求都放在created钩子函数当中!!!

实现逻辑

1.在data函数声明一个存放轮播图数据的空数组

2.通过挂载的$axios发起banner请求

3.请求成功之后通过then方法添加到banners数组

image-20210605151810796

实现结构

1.v-for遍历存放数据的每个元素item中有唯一的id设置给 :key

2.v-for遍历存放数据的每个元素item的picURL绑定给对应的img属性

image-20210605151815388

5.3首页推荐歌单

实现逻辑

1.在data函数声明一个推荐歌单的songList空数组

2.通过挂载的$axios发起请求

3.请求成功的数据res添加到songList数组中

image-20210605160200285

实现结构

1.v-for循环遍历songList数组

2.将遍历元素的唯一id设置给key

3.将遍历元素的唯一图片地址bind到img标签

4.将遍历元素的name添加到p标签

image-20210605160205320

注意事项:

1.冒号不能露

2.返回的数据名,设置的属性名

5.4首页推荐新音乐

实现逻辑

1.在data函数声明一个hotList空数组

2.通过原型挂载$axios发起请求

3.请求成功以后将返回的数据保存到数组

实现结构

1.通过cell组件设置多行的效果如下

​ 1.注意自定的结构一般都是插槽

​ 具名插槽:有名字的插槽

image-20210609171011604

2.在van-cell组件的标签上循环遍历数组hotList

3.遍历到的唯一id设置给key

4.遍历到的name绑定给title,同时在name之外返回的数据可能还有别名,放在alias数组当中通过三元表达式进行判断添加

image-20210609172151207

标题的数据渲染逻辑

image-20210609172216658

5.将遍历的元素item中的歌手名数据渲染给lable属性

代码整合

image-20210605162736108

5.5首页跳转--play

跳转携带歌曲的参数

代码跳转通过编程式导航

​ 1.携带歌曲的id

​ 2.通过编程式导航跳转

1.给跳转的按钮添加点击事件,在点击事件触发的时候调用方法

 <div class = "song-list">
      <van-cell
		//推荐新歌的数组循环,van-cell之内
        v-for = "item in hotSongs"
        :key = "item.id"
        :title = "
          item.name +
            (item.song.alias.length === 0 ? '' : `(${item.song.alias[0]})`)
        "
        size = "large"
        :label = "item.song.artists[0].name"
      >
        <template #right-icon>
          <!-- 播放按钮 -->
          <van-icon
            name = "play-circle-o"
            class = "play-icon"
            @click = "toPlay(item.id)"
          />
        </template>
      </van-cell>
    </div>

2.定义toplay方法跳转页面携带id

toPlay (id) {
      // console.log('id:', id)
    //通过router的push方法添加跳转的路径和携带的数据,ES6对象的简写{id:id}
      this.$router.push({
        path: '/play',
        query: { id }
      })
}

6.播放页

6.1接收数据

1.接受首页推荐新音乐跳转过来携带的参数

 data () {
    return {
      // 定义一个数据保存歌曲的id
      id: 0, 
    }
  },
  created () {
    // 通过 this.$route.query获取到跳转携带的数据
    this.id = this.$route.query.id
   
  },

query查询到的数据

$route.query

  • 类型: Object

    一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。

6.2播放歌曲

1.点击播放歌曲

		1.将获取的参数通过模板字符串传递给src属性对应的位置

​ 2.将src绑定data中的数据

image-20210605173459627

2.播放状态的切换

​ 1.定义一个播放状态isPlay

​ 2.定义一个切换播放状态的方法togglePlay

<div class = "start-box">
        <span class = "song-start" @click =      			"togglePlay">
        </span>
 </div>

​ 3.点击时

togglePlay () {
      // 暂停->播放
      if (this.isPlay === false) {
          //通过$refs获取到audio标签,调用自带的play方法播放
        this.$refs.audio.play()
      } else {
        // 播放->暂停
          //通过$refs获取到audio标签,调用自带的pause方法播放
        this.$refs.audio.pause()
      }
      // 取反
      this.isPlay = !this.isPlay
    }
		//$refs取到所有的ref属性的标签再点一下具体的标签

6.3播放器动画效果

CSS代码

.song-wrapper {
  position: fixed;
  width: 247px;
  height: 247px;
  left: 50%;
  top: 50px;
  transform: translateX(-50%);
  z-index: 10001;

  &.play {
    .needle {
      transform: rotate(-7deg);
    }

    .song-turn {
      animation-play-state: running;
    }
  }
}

.song-turn {
  width: 100%;
  height: 100%;
  background: url('../assets/bg.png') no-repeat;
  background-size: 100%;
}

.start-box {
  position: absolute;
  width: 156px;
  height: 156px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
}

.song-start {
  width: 56px;
  height: 56px;
  background: url('../assets/start.png');
  background-size: 100%;
}

.needle {
  position: absolute;
  transform-origin: left top;
  background: url('../assets/needle-ab.png') no-repeat;
  background-size: contain;
  width: 73px;
  height: 118px;
  top: -40px;
  left: 112px;
  transition: all 0.6s;
  transform: rotate(-38deg);
}

.song-img {
  width: 154px;
  height: 154px;
  position: absolute;
  left: 50%;
  top: 50%;
  overflow: hidden;
  border-radius: 50%;
  transform: translate(-50%, -50%);
}

动画实现结构

 <!-- 播放页内容容器 -->
    <div class = "song-wrapper" :class = "{ play: isPlay }">
      <div class = "song-turn ani">
        <div class = "song-img">
          <!-- 封面 -->
          <img
            style = "width: 100%"
            :src = "songInfo.al && songInfo.al.picUrl"
            alt = ""
          />
        </div>
      </div>
      <!-- 播放盒子 -->
      <div class = "start-box">
        <span class = "song-start" @click = "togglePlay"></span>
      </div>
        
        
        
         <!-- 操作杆css容器 -->
    <div class = "needle"></div>
    </div>

动画实现效果

音乐播放器动画

6.4 router.go

返回上一页

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似

1.给返回上一页的箭头添加点击事件

<van-icon
        name = "arrow-left"
        size = "20"
        class = "left-incon"
        @click = "goBack"
/>

2.调用返回上一页的方法

 goBack () {
      // 从哪来 回哪去
      this.$router.go(-1)
}

7.搜索页

7.1搜索页搜索

引入search组件

<van-search
  shape="round"
  v-model="value"
  show-action
  @search="onSearch"
  @cancel="onCancel"
  placeholder="请输入搜索关键词"
/>

组件的说明

  1. v-model数据绑定
  2. show-action显示右侧的取消
  3. @search:点击回车或者小键盘右下角,触发的逻辑
  4. @cancel,点击取消触发

实现效果

image-20210610214934402

7.2显示搜索结果(清空热词)和取消搜索结果(保留热词)

实现逻辑

搜索的逻辑

​ 1.在data中定义一个数组保存搜索的结果,如果有搜索结果就取消热词的显示

​ 2.定义一个serach方法,在组建的search事件调用

​ 1.发起请求,添加搜索的参数

​ 2.在参数内添加一个戳避免缓存

​ 3.在参数内将请求的关键字value赋值给keywords,这个键名是后台命名的

​ 4.请求成功后在then方法中将数组的数组添加给定义的空数组

​ 3.定义一个跳转的方法,toPlay接受遍历到的id

​ 4.定义一个取消方法onCancel()

image-20210607094432347

实现结构

​ 5.将search组件通过v-model双向绑定value搜索关键词,关联第三条

​ 6.绑定搜索事件的方法,和取消事件的方法

​ 7.绑定跳转事件,在点击右侧image-20210610234829219之后携带id跳转到播放页面

​ 8.遍历van-cell,将获得元素item.id绑定到:key上

image-20210607094548874

9.图片中少写了携带id跳转播放,对应的是toPlay方法其接受了来自searchRes循环元素的id值

![img](C:/Users/ENG.J/Desktop/Vue%20origin/image.namedq.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg

7.3点击热词

需求

  1. 渲染热词
  2. 点击热词,搜索对应内容
  3. 搜索出结果显示热词,反之隐藏热词

显示搜索结果(清空热词)和取消搜索结果(保留热词)

步骤:

  1. created中调用热词接口,获取并渲染
    1. 为热词绑定点击事件
    2. 设置输入框的内容,并搜索
  2. v-if判断数组的长度
    1. 0:显示热词
    2. 不为0:显示搜索结果
  3. 取消的事件中清空数组即可

实现逻辑

image-20210607100803217

热词方法接受model传来的参数hot = item.first,并且将item.first渲染到对应的搜索框内{{item.first}}

实现结构

image-20210607100807384

通过hots数组将返回的数据添加到指定位置,

注意

​ 要对搜索的数据长度进行判断,如果没有数据也就是说数组为空的情况下

8.整合优化

8.1抽取api

image-20210607110708642

image-20210607110712757

image-20210607110717877

posted @ 2021-06-14 12:00  Mzs-Qsy  阅读(52)  评论(0编辑  收藏  举报