zoukankan      html  css  js  c++  java
  • VUEJS

    用VUEJS做一个网易云音乐

     

    前言:自己学习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数据转发出来。同时服务端做下跨域处理。

    核心代码:

    /// <summary> /// 请求网易云音乐接口 /// </summary> /// <typeparam name="T">要请求的接口类型</typeparam> /// <param name="config">要请求的接口类型的对象</param> /// <returns>请求结果(JSON)</returns> public static string Request<T>(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'componentrequire('../views/index')children: [ path'rage'componentrequire('../views/rage') }, path'songList'componentrequire('../views/songList') }, path'leaderBoard'componentrequire('../views/leaderBoard') }, path'hotSinger'componentrequire('../views/hotSinger') } ] }, name'playerDetail'path'/playerDetail/:id'componentrequire('../views/playerDetail') }, path'/playListDetail/:id'name'playListDetail'componentrequire('../views/playListDetail') }, path'*'redirect'/index/rage' }]// 让每个页面都滚动到顶部,改变模式为mode: history scrollBehavior (tofrom, savedPosition) if (savedPosition) return savedPosition else return x0y})

    vuex部分

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

    const store new Vuex.Store(stateaudio'id'0'name''歌曲名称''singer''演唱者''albumPic''/static/player-bar.png''location''''album''' }, lyric'正在加载中。。'currentIndex0// 当前播放的歌曲位置 playingfalse// 是否正在播放 loadingfalse// 是否正在加载中 showDetailfalsesongList: []// 播放列表 currentTime0tmpCurrentTime0durationTime0bufferedTime0changefalse // 判断是更改的时间还是播放的时间 }, gettersaudio: state => state.audioplaying: state => state.playingloading: state => state.loadingshowDetail: state => state.showDetaildurationTime: state => state.durationTimecurrentIndex: state => state.currentIndexbufferedTime: state => state.bufferedTimetmpCurrentTime: state => state.tmpCurrentTimesongList: state => state.songListchange: state => state.changecurrentTime: state => state.currentTimeprCurrentTime: state => return state.currentTime / state.durationTime 100 }, prBufferedTime: state => return state.bufferedTime / state.durationTime 100 }, mutationsplay (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 }, removeAudio (state, index) state.songList.splice(index1) state.audio state.songList[index 1] state.currentIndex state.currentIndex 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 }, playNext (state) // 播放下一曲 state.currentIndex++ if (state.currentIndex state.songList.length) state.currentIndex 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 }) if (!flag) state.songList.push(item) state.currentIndex state.songList.length }, setLrc (state, lrc) state.lyric = lrc }, // 异步的数据操作 actionsgetSong ({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/NeteaseCloudWebApp

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

  • 相关阅读:
    HTTP深入浅出 http请求
    ASP.NET MVC 4
    ASP.NET MVC 4 (十三) 基于表单的身份验证
    ASP.NET MVC 4 (十二) Web API
    ASP.NET MVC 4 (十一) Bundles和显示模式
    ASP.NET MVC 4 (十) 模型验证
    ASP.NET MVC 4 (九) 模型绑定
    ASP.NET MVC 4 (八) URL链接和Ajax帮助函数
    ASP.NET MVC 4 (七) 模板帮助函数
    ASP.NET MVC 4 (六) 帮助函数
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6423817.html
Copyright © 2011-2022 走看看