-
Notifications
You must be signed in to change notification settings - Fork 251
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c51726e
Showing
98 changed files
with
7,431 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"presets": [ | ||
["env", { | ||
"modules": false, | ||
"targets": { | ||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"] | ||
} | ||
}], | ||
"stage-2" | ||
], | ||
"plugins": ["transform-runtime"], | ||
"env": { | ||
"test": { | ||
"presets": ["env", "stage-2"], | ||
"plugins": ["istanbul"] | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
root = true | ||
|
||
[*] | ||
charset = utf-8 | ||
indent_style = space | ||
indent_size = 2 | ||
end_of_line = lf | ||
insert_final_newline = true | ||
trim_trailing_whitespace = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
build/*.js | ||
config/*.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// http://eslint.org/docs/user-guide/configuring | ||
|
||
module.exports = { | ||
root: true, | ||
parser: 'babel-eslint', | ||
parserOptions: { | ||
sourceType: 'module' | ||
}, | ||
env: { | ||
browser: true, | ||
}, | ||
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style | ||
extends: 'standard', | ||
// required to lint *.vue files | ||
plugins: [ | ||
'html' | ||
], | ||
// add your custom rules here | ||
'rules': { | ||
// allow paren-less arrow functions | ||
'arrow-parens': 0, | ||
// allow async-await | ||
'generator-star-spacing': 0, | ||
// allow debugger during development | ||
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, | ||
'space-before-function-paren': 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
.DS_Store | ||
node_modules/ | ||
dist/ | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# Editor directories and files | ||
.idea | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
{ | ||
// Enforcing options | ||
// http://jshint.com/docs/options/#enforcing-options | ||
|
||
"node": true, // Enable globals available when code is running inside of the NodeJS runtime environment. | ||
"browser": true, // Standard browser globals e.g. `window`, `document`. | ||
// "es5": true, // Allow EcmaScript 5 syntax. | ||
// "esnext": true, // Allow ES.next specific features such as `const` and `let`. | ||
"esversion": 6, | ||
"bitwise": false, // Prohibit bitwise operators (&, |, ^, etc.). | ||
"camelcase": false, // Permit only camelcase for `var` and `object indexes`. | ||
"curly": false, // Require {} for every new block or scope. | ||
"eqeqeq": true, // Require triple equals i.e. `===`. | ||
"immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` | ||
"latedef": true, // Prohibit variable use before definition. | ||
"newcap": true, // Require capitalization of all constructor functions e.g. `new F()`. | ||
"noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`. | ||
"quotmark": "single", // Define quotes to string values. | ||
"regexp": true, // Prohibit `.` and `[^...]` in regular expressions. | ||
"undef": true, // Require all non-global variables be declared before they are used. | ||
"unused": false, // Warn unused variables. | ||
"strict": false, // Require `use strict` pragma in every file. | ||
"trailing": true, // Prohibit trailing whitespaces. | ||
"smarttabs": false, // Suppresses warnings about mixed tabs and spaces | ||
"globals": { // Globals variables. | ||
"jQuery": true, | ||
"requirejs": true, | ||
"next": true, | ||
"angular": true, | ||
"node": true, | ||
"$": true | ||
}, | ||
"predef": [ // Extra globals. | ||
"define", | ||
"require", | ||
"exports", | ||
"module", | ||
"describe", | ||
"before", | ||
"beforeEach", | ||
"after", | ||
"afterEach", | ||
"it" | ||
], | ||
"asi": true, | ||
"indent": 4, // Specify indentation spacing | ||
"maxlen": 3020, // Max line lenght | ||
"devel": false, // Allow development statements e.g. `console.log();`. | ||
"noempty": true // Prohibit use of empty blocks. | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// https://github.com/michael-ciniawsky/postcss-load-config | ||
|
||
module.exports = { | ||
"plugins": { | ||
// to edit target browsers: use "browserslist" field in package.json | ||
"autoprefixer": {} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,196 @@ | ||
|
||
# 移动端音乐 WebApp | ||
|
||
👉 GitHub: https://github.com/bxm0927/vue-music-webapp | ||
|
||
👉 项目演示地址: https://github.com/bxm0927/vue-music-webapp (*在 GitHub Pages 中,通过 jsonp 请求的数据会被正常渲染,而由于无 node 服务,通过 axios 请求的数据不会被正常渲染*) | ||
|
||
基于 **Vue 全家桶 (2.x)** 制作的移动端音乐 WebApp ,一个媲美原生的移动端音乐 App,项目完整、功能完备、UI美观、交互一流。 | ||
|
||
<!-- more --> | ||
|
||
 | ||
|
||
|
||
## 技术栈 | ||
|
||
【前端】 | ||
|
||
- `Vue.js`:MVVM 框架 | ||
- `vue-router`:为单页面应用提供的路由系统,项目上线前使用了 `Lazy Loading Routes` 技术来实现异步加载优化性能 | ||
- `vuex`:Vue.js 集中状态管理,类 Flux 的状态管理架构 | ||
- `vue-lazyload`:第三方图片懒加载库,优化页面加载速度 | ||
- `better-scroll`:iscroll 的优化版,使移动端滑动体验更加流畅 | ||
- `Sass(Scss)`:css 预编译处理器 | ||
- `ES6`:ECMAScript 新一代语法,模块化、解构赋值、Promise、Class 等方法非常好用 | ||
|
||
【后端】 | ||
|
||
- `Node.js`:利用 Express 起一个本地测试服务器 | ||
- `jsonp`:抓取 QQ音乐(移动端)数据 | ||
- `axios`:结合 Node.js 代理后端请求,抓取 QQ音乐(PC端)数据 | ||
|
||
【自动化构建及其他工具】 | ||
|
||
- `vue-cli`:vue 脚手架工具,快速初始化项目代码 | ||
- `eslint`:代码风格检查工具,规范代码书写 | ||
- `vConsole`:移动端调试工具,在移动端输出日志 | ||
|
||
|
||
## 收获 | ||
|
||
1. 总结了一套 Vue 通用组件,可以在其它项目中复用的 10+ 个基础组件、15+ 个业务组件 | ||
1. 总结了一套常用的 SCSS mixin 库 | ||
1. 总结了一套常用的 JS 工具函数库 | ||
1. 体会到组件化、模块化开发带来的便捷 | ||
1. 体会到将对象封装成类(ES6 class) 的便捷性,以及利用工厂方式初始化类实例 | ||
|
||
|
||
## TODO | ||
|
||
1. | ||
2. | ||
3. | ||
|
||
|
||
## 目录结构 | ||
|
||
``` | ||
bootstrap/ | ||
├── css/ | ||
│ ├── bootstrap.css | ||
│ ├── bootstrap-theme.css | ||
├── js/ | ||
│ ├── bootstrap.js | ||
│ └── bootstrap.min.js | ||
└── fonts/ | ||
├── glyphicons-regular.ttf | ||
├── glyphicons-regular.woff | ||
└── glyphicons-regular.woff2 | ||
``` | ||
|
||
|
||
## 实现细节 | ||
|
||
主要页面:播放器内核页、推荐页、歌单详情页、歌手页、歌手详情页、排行页、搜索页、添加歌曲页、个人中心页等。 | ||
|
||
核心页面:播放器内核页 | ||
|
||
**组件树** | ||
|
||
``` | ||
<app> ................... 根组件 | ||
<my-player> ........... 全局的播放器内核组件 | ||
<my-header> ........... 头部组件 | ||
<my-tab> .............. 导航栏组件 | ||
<router-view> ......... 路由 | ||
<recommend> ......... 推荐页 | ||
<singer> ............ 歌手页 | ||
<rank> .............. 排行页 | ||
<search> ............ 搜索页 | ||
``` | ||
|
||
**推荐页** | ||
|
||
上部分是一个轮播图组件,使用第三方库 `better-scroll` 辅助实现,使用 `jsonp` 抓取 QQ音乐(移动端)数据 | ||
|
||
下部分是一个歌单推荐列表,使用 `axios + Node.js` 代理后端请求,绕过主机限制 (伪造 headers),抓取 QQ音乐(PC端)数据 | ||
|
||
歌单推荐列表图片,使用图片懒加载技术 `vue-lazyload`,优化页面加载速度 | ||
|
||
为了更好的用户体验,当数据未请求到时,显示 `loading` 组件 | ||
|
||
**推荐页 -> 歌单详情页** | ||
|
||
由于歌手的状态多且杂,这里使用 `vuex` 集中管理歌手状态 | ||
|
||
这个组件更加注重 UX,做了很多类原生 APP 动画,如下拉图片放大、跟随推动、ios 渐进增强的高斯模糊效果 `backdrop-filter` 等 | ||
|
||
**歌手页** | ||
|
||
左右联动是这个组件的难点 | ||
|
||
左侧是一个歌手列表,使用 `jsonp` 抓取 QQ音乐(PC端)歌手数据并重组 JSON 数据结构 | ||
|
||
列表图片使用懒加载技术 `vue-lazyload`,优化页面加载速度 | ||
|
||
右侧是一个字母列表,与左侧歌手列表联动,滚动固定标题实现 | ||
|
||
**歌手页 -> 歌手详情页** | ||
|
||
复用歌单详情页,只改变传入的参数,数据同样爬取自 QQ音乐 | ||
|
||
**播放器内核页** | ||
|
||
核心组件。用 `vuex` 管理各种播放时状态,播放、暂停等功能调用 [audio API](http://www.w3school.com.cn/tags/html_ref_audio_video_dom.asp) | ||
|
||
播放器可以最大化和最小化 | ||
|
||
中部唱片动画使用第三方 JS 动画库 `create-keyframe-animation` 实现 | ||
|
||
底部操作区图标使用 `iconfonts`。 | ||
|
||
抽象了一个横向进度条组件和一个圆形进度条组件,横向进度条可以拖动小球和点击进度条来改变播放进度,圆形进度条组件使用 SVG `<circle>` 元素 | ||
|
||
播放模式有:顺序播放、单曲循环、随机播放,原理是调整歌单列表数组 | ||
|
||
歌词的爬取利用 `axios` 代理后端请求,伪造 `headers` 来实现,先将歌词 jsonp 格式转换为 json 格式,再使用第三方库 [`js-base64`](https://github.com/dankogai/js-base64) 进行 Base64 解码操作,最后再使用第三方库 [`lyric-parser`](https://github.com/ustbhuangyi/lyric-parser)对歌词进行格式化 | ||
|
||
实现了侧滑显示歌词、歌词跟随进度条高亮等交互效果 | ||
|
||
增加了当前播放列表组件,可在其中加入/删除歌曲 | ||
|
||
**排行页** | ||
|
||
普通组件,没什么好说的 | ||
|
||
**排行页 -> 歌单详情页** | ||
|
||
复用歌单详情页,没什么好说的 | ||
|
||
**搜索页** | ||
|
||
抓数据,写组件,另外,根据抓取的数据特征,做了上拉刷新的功能 | ||
|
||
考虑到数据量大且频繁的问题,对请求做了节流处理 | ||
|
||
考虑到移动端键盘占屏的问题,对滚动前的 `input` 做了 `blur()` 操作 | ||
|
||
对搜索历史进行了 `localstorage` 缓存,清空搜索历史时使用了改装过的 `confirm` 组件 | ||
|
||
支持将搜索的歌曲添加到播放列表 | ||
|
||
**个人中心** | ||
|
||
将 `localstorage` 中 “我的收藏” 和 “最近播放” 反映到界面上 | ||
|
||
**其他** | ||
|
||
此应用的全部数据来自 QQ音乐,推荐页的歌单列表及歌词是利用 `axios` 结合 `node.js` 代理后端请求抓取的。 | ||
|
||
全局通用的应用级状态使用 `vuex` 集中管理 | ||
|
||
全局引入 `fastclick` 库,消除 click 移动浏览器300ms延迟 | ||
|
||
页面是响应式的,适配常见的移动端屏幕,采用 `flex` 布局 | ||
|
||
## Build Setup | ||
|
||
``` bash | ||
# clone the repo into your disk. | ||
$ git clone https://github.com/bxm0927/music-app.git | ||
|
||
# install dependencies | ||
$ npm install | ||
|
||
# serve with hot reload at localhost:8080 | ||
$ npm run dev | ||
|
||
# build for production with minification | ||
$ npm run build | ||
``` | ||
|
||
|
||
## License | ||
|
||
The code is available under the [MIT license](https://opensource.org/licenses/MIT). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
require('./check-versions')() | ||
|
||
process.env.NODE_ENV = 'production' | ||
|
||
var ora = require('ora') | ||
var rm = require('rimraf') | ||
var path = require('path') | ||
var chalk = require('chalk') | ||
var webpack = require('webpack') | ||
var config = require('../config') | ||
var webpackConfig = require('./webpack.prod.conf') | ||
|
||
var spinner = ora('building for production...') | ||
spinner.start() | ||
|
||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { | ||
if (err) throw err | ||
webpack(webpackConfig, function (err, stats) { | ||
spinner.stop() | ||
if (err) throw err | ||
process.stdout.write(stats.toString({ | ||
colors: true, | ||
modules: false, | ||
children: false, | ||
chunks: false, | ||
chunkModules: false | ||
}) + '\n\n') | ||
|
||
console.log(chalk.cyan(' Build complete.\n')) | ||
console.log(chalk.yellow( | ||
' Tip: built files are meant to be served over an HTTP server.\n' + | ||
' Opening index.html over file:// won\'t work.\n' | ||
)) | ||
}) | ||
}) |
Oops, something went wrong.