博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用vue.js做一个网易云音乐
阅读量:4085 次
发布时间:2019-05-25

本文共 7687 字,大约阅读时间需要 25 分钟。

前言:自己学习VUEJS也一段时间,但一直没有做出来一东西。我自己一直喜欢用网易云音乐app,于是乎就做了这个app。

技术栈

  • vue全家桶 (vue vue-router vuex)

  • axios

  • Muse-UI(一个基于Vue2.x的material design 风格UI框架)

功能与思路分析

我之前学习JS的时候对Html5 audio研究过,也写过一些例子,那时的功能并不是很全面。在写这个程序之前,我好好的查阅了当前的HTML5中的audio标签,发现园子上一位园友总结的很不错()。于是就先把网易云音乐最基本的功能实现,歌单部分(这也是我喜欢网易云音乐的原因这一),然后实现音乐的上一曲、下一曲,播放、暂停。列表功能。

后台

后台采用.net做为后台提供系统请求所用的API(),原理很简单就是用.net伪装成一个客户端去访问网易云音乐的API然后,把返回的json数据转发出来。同时服务端做下跨域处理。

核心代码:

/// /// 请求网易云音乐接口/// /// 
要请求的接口类型
/// 要请求的接口类型的对象///
请求结果(JSON)
public static string Request
(T config) where T : RequestData, new(){ // 请求URL string requestURL = config.Url; // 将数据包对象转换成QueryString形式的字符串 string @params = config.FormData.ParseQueryString(); bool isPost = config.Method.Equals("post", StringComparison.CurrentCultureIgnoreCase); if (!isPost) { // get方式 拼接请求url string sep = requestURL.Contains('?') ? "&" : "?"; requestURL += sep + @params; } HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requestURL); req.Accept = "*/*"; req.Headers.Add("Accept-Language", "zh-CN,zh;q=0.8,gl;q=0.6,zh-TW;q=0.4"); // 如果服务端启用了GZIP,那么下面必须解压,否则一直乱码。 // 参见:http://www.crifan.com/set_accept_encoding_header_to_gzip_deflate_return_messy_code/ req.Headers.Add("Accept-Encoding", "gzip,deflate,sdch"); req.ContentType = "application/x-www-form-urlencoded"; req.KeepAlive = true; req.Host = "music.163.com"; req.Referer = "http://music.163.com/search/"; req.UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537"; // 设置cookies req.Headers["Cookie"] = "appver=1.5.2"; req.Method = config.Method; req.AutomaticDecompression = DecompressionMethods.GZip; if (isPost) { // 写入post请求包 byte[] formData = Encoding.UTF8.GetBytes(@params); // 设置HTTP请求头 参考:https://github.com/darknessomi/musicbox/blob/master/NEMbox/api.py req.GetRequestStream().Write(formData, 0, formData.Length); } // 发送http请求 并读取响应内容返回 return new StreamReader(req.GetResponse().GetResponseStream(), Encoding.GetEncoding("UTF-8")).ReadToEnd();}

vuejs部分

项目结构

├── index.html├── main.js├── api│   └── ... # 抽取出API请求├── components│   ├── playBar.vue│   └── ...└── store│    └── index.js        # 整个项目的vuex部分└── router│   └── router.js        # 整个项目的路由└── utils                # 一些工具类模块│└── views                # 项目中的一些route-view

说项目的路由之前,先来看一张效果图

对于整个项目来说:视图区别在于顶部导航,下面的bar的是否出来取决于,当前系统列表中是否有歌曲,如果有就会出现。

router.js核心部分

const router = new VueRouter({  mode: 'history',  routes: [{    path: '/index',    component: require('../views/index'),    children: [      {        path: 'rage',        component: require('../views/rage')      },      {        path: 'songList',        component: require('../views/songList')      },      {        path: 'leaderBoard',        component: require('../views/leaderBoard')      },      {        path: 'hotSinger',        component: require('../views/hotSinger')      }    ]  }, {    name: 'playerDetail',    path: '/playerDetail/:id',    component: require('../views/playerDetail')  }, {    path: '/playListDetail/:id',    name: 'playListDetail',    component: require('../views/playListDetail')  }, {    path: '*', redirect: '/index/rage'  }],  // 让每个页面都滚动到顶部,改变模式为mode: history  scrollBehavior (to, from, savedPosition) {    if (savedPosition) {      return savedPosition    } else {      return { x: 0, y: 0 }    }  }})

vuex部分

这部分,主要是歌曲这一块,因为不同的页面有不同的使用到了歌曲信息,把把这部分数据放到vuex中做统一的数据处理!sotre/index.js

const store = new Vuex.Store({  state: {    audio: {      'id': 0,      'name': '歌曲名称',      'singer': '演唱者',      'albumPic': '/static/player-bar.png',      'location': '',      'album': ''    },    lyric: '正在加载中。。',    currentIndex: 0, // 当前播放的歌曲位置    playing: false, // 是否正在播放    loading: false, // 是否正在加载中    showDetail: false,    songList: [],    // 播放列表    currentTime: 0,    tmpCurrentTime: 0,    durationTime: 0,    bufferedTime: 0,    change: false   // 判断是更改的时间还是播放的时间  },  getters: {    audio: state => state.audio,    playing: state => state.playing,    loading: state => state.loading,    showDetail: state => state.showDetail,    durationTime: state => state.durationTime,    currentIndex: state => state.currentIndex,    bufferedTime: state => state.bufferedTime,    tmpCurrentTime: state => state.tmpCurrentTime,    songList: state => state.songList,    change: state => state.change,    currentTime: state => state.currentTime,    prCurrentTime: state => {      return state.currentTime / state.durationTime * 100    },    prBufferedTime: state => {      return state.bufferedTime / state.durationTime * 100    }  },  mutations: {    play (state) {      state.playing = true    },    pause (state) {      state.playing = false    },    toggleDetail (state) {      state.showDetail = !state.showDetail    },    setAudio (state) {      state.audio = state.songList[state.currentIndex - 1]    },    setAudioIndex (state, index) {      state.audio = state.songList[index]      state.currentIndex = index + 1    },    removeAudio (state, index) {      state.songList.splice(index, 1)      state.audio = state.songList[index - 1]      state.currentIndex = state.currentIndex - 1      if (state.songList.length === 0) {        state.audio = {          'id': 0,          'name': '歌曲名称',          'singer': '演唱者',          'albumPic': '/static/player-bar.png',          'location': '',          'album': ''        }        state.playing = false      }    },    setChange (state, flag) {      state.change = flag    },    setLocation (state, location) {      state.audio.location = location    },    updateCurrentTime (state, time) {      state.currentTime = time    },    updateDurationTime (state, time) {      state.durationTime = time    },    updateBufferedTime (state, time) {      state.bufferedTime = time    },    changeTime (state, time) {      state.tmpCurrentTime = time    },    openLoading (state) {      state.loading = true    },    closeLoading (state) {      state.loading = false    },    resetAudio (state) {      state.currentTime = 0    },    playNext (state) { // 播放下一曲      state.currentIndex++      if (state.currentIndex > state.songList.length) {        state.currentIndex = 1      }      state.audio = state.songList[state.currentIndex - 1]    },    playPrev (state) { // 播放上一曲      state.currentIndex--      if (state.currentIndex < 1) {        state.currentIndex = state.songList.length      }      state.audio = state.songList[state.currentIndex - 1]    },    addToList (state, item) {      var flag = false      state.songList.forEach(function (element, index) { // 检测歌曲重复        if (element.id === item.id) {          flag = true          state.currentIndex = index + 1        }      })      if (!flag) {        state.songList.push(item)        state.currentIndex = state.songList.length      }    },    setLrc (state, lrc) {      state.lyric = lrc    }  },  // 异步的数据操作  actions: {    getSong ({commit, state}, id) {      commit('openLoading')      Axios.get(api.getSong(id)).then(res => {        // 统一数据模型,方便后台接口的改变        var url = res.data.data[0].url        commit('setAudio')        commit('setLocation', url)      })    },    getLrc ({commit, state}, id) {      commit('setLrc', '[txt](加载中。。。')      Axios.get(api.getLrc(id)).then(res => {        // 1、先判断是否有歌词        if (res.data.nolyric) {          commit('setLrc', '[txt](⊙0⊙) 暂无歌词')        } else {          console.log(res.data.lrc.lyric)          commit('setLrc', res.data.lrc.lyric)        }      })    }  }})

最后上点项目截图

github项目地址:

https://github.com/javaSwing

目前只完成app歌单部分,也是最核心的部分。这个项目会一直更新!如果觉的不错就给个star吧

转载地址:http://vmhni.baihongyu.com/

你可能感兴趣的文章
Java生成随机不重复推广码邀请码
查看>>
Java8 Lambda表达式介绍
查看>>
【JAVA数据结构】双向链表
查看>>
【JAVA数据结构】先进先出队列
查看>>
String类的intern方法随笔
查看>>
【泛型】一个简易的对象间转换的工具类(DO转VO)
查看>>
1.随机函数,计算机运行的基石
查看>>
MouseEvent的e.stageX是Number型,可见as3作者的考虑
查看>>
在mc中直接加aswing组件,该组件还需最后用validate()方法
查看>>
移植Vim配色方案到Eclipse
查看>>
从超链接调用ActionScript
查看>>
谈谈加密和混淆吧[转]
查看>>
TCP的几个状态对于我们分析所起的作用SYN, FIN, ACK, PSH,
查看>>
网络游戏客户端的日志输出
查看>>
关于按钮的mouseOver和rollOver
查看>>
《多线程服务器的适用场合》例释与答疑
查看>>
Netty框架
查看>>
Socket经验记录
查看>>
对RTMP视频流进行BitmapData.draw()出错的解决办法
查看>>
FMS 客户端带宽计算、带宽限制
查看>>