# 小程序模仿——网易云音乐
## 初窥
![](https://www.writebug.com/myres/static/uploads/2021/12/5/eac0fe123c158c43b3b7a3f13ba5834f.writebug)
todo:
- [ ] 添加音乐到收藏(最近)列表
- [ ] 歌词滚动
## 从一个 hello world 开始
微信开发者工具生成 目录如下:
```
.
|-- app.js
|-- app.json
|-- app.wxss
|-- pages
| |-- index # 主页
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| `-- log # 日志页面
| | |-- log.js
| | |-- log.json
| | |-- log.wxml
| | `-- log.wxss
`-- utils # 工具
`-- util.js
```
大体为:
每一个 page 即是一个页面文件 ,每个页面有一个 js/wxml/wxss/json 文件 规定:描述页面的这四个文件必须具有相同的路径与文件名。<br>
全局下同路,为公共的逻辑,样式,配置<br>
与 HTML 不同:用 `view text navigator` 代替 `div span a`
## 开发者文档走马观花
app.json: 注册 pages window tabBar networkTimeout<br>
[组件说明](https://mp.weixin.qq.com/debug/wxadoc/dev/component/)<br>
.js: 作为逻辑层 与 wxml 交互 有着丰富的
网络,
媒体,
文件,
数据缓存,
位置,
设备,
界面...的 API<br>
[官方文档](https://mp.weixin.qq.com/debug/wxadoc/dev/api/)<br>
.wxml: 数据驱动的视图层 + 微信提供了大量的组件 表单 导航 媒体 ...
## 官方组件不够,weui 来凑
weui 为小程序提供了 weui.wxcss 但大多是造官方组件的轮子<br>
这里精选,也算是补充两个常用组件<br>
对于小程序没有 DOM 操作 不熟悉 mvvm 思想的同学 是个很好的入门
1. navbar<br>
![](https://www.writebug.com/myres/static/uploads/2021/12/5/44c9282ec01b0fdfa70124a823c250ed.writebug)
```html
<!-- wxml -->
<view class="weui-tab">
<view class="weui-navbar">
<block wx:for="{{tabs}}" wx:key="*this">
<view id="{{index}}" class="weui-navbar__item {{activeIndex == index ? 'weui-bar__item_on' : ''}}" bindtap="tabClick">
<view class="weui-navbar__title">{{item}}</view>
</view>
</block>
<view class="weui-navbar__slider" style="left: {{sliderLeft}}px; transform: translateX({{sliderOffset}}px); -webkit-transform: translateX({{sliderOffset}}px);"></view>
</view>
<view class="weui-tab__panel">
<view class="weui-tab__content" hidden="{{activeIndex != 0}}">选项一的内容</view>
<view class="weui-tab__content" hidden="{{activeIndex != 1}}">选项二的内容</view>
<view class="weui-tab__content" hidden="{{activeIndex != 2}}">选项三的内容</view>
</view>
</view>
```
block 渲染 data 里面的四个 tabs,slider 为激活 tab 选项时候的表现,panel 为内容面板
```js
//js
var sliderWidth = 96; // 需要设置slider的宽度,用于计算中间位置
Page({
data: {
tabs: ["选项一", "选项二", "选项三"],
activeIndex: 1,
sliderOffset: 0,
sliderLeft: 0
},
onLoad: function () {
var that = this;
wx.getSystemInfo({
success: function(res) {
that.setData({
sliderLeft: (res.windowWidth / that.data.tabs.length - sliderWidth) / 2,
sliderOffset: res.windowWidth / that.data.tabs.length * that.data.activeIndex
});
}
});
},
tabClick: function (e) {
this.setData({
sliderOffset: e.currentTarget.offsetLeft,
activeIndex: e.currentTarget.id
});
}
});
```
了解 mvvm 思想的同学不难看出 通过 tabs 数组渲染出来选项后每次点击获取 id 然后通过设置 hidden 显示或隐藏
2. searchbar<br>
![](https://www.writebug.com/myres/static/uploads/2021/12/5/bc23e9c653b6d1a78181c2f6f1ba590b.writebug)
```html
<view class="weui-search-bar">
<view class="weui-search-bar__form">
<view class="weui-search-bar__box">
<icon class="weui-icon-search_in-box" type="search" size="14"></icon>
<input type="text" class="weui-search-bar__input" placeholder="搜索" value="{{inputVal}}" focus="{{inputShowed}}" bindinput="inputTyping" />
<view class="weui-icon-clear" wx:if="{{inputVal.length > 0}}" bindtap="clearInput">
<icon type="clear" size="14"></icon>
</view>
</view>
<label class="weui-search-bar__label" hidden="{{inputShowed}}" bindtap="showInput">
<icon class="weui-icon-search" type="search" size="14"></icon>
<view class="weui-search-bar__text">搜索</view>
</label>
</view>
<view class="weui-search-bar__cancel-btn" hidden="{{!inputShowed}}" bindtap="hideInput">取消</view>
</view>
<view class="weui-cells searchbar-result" wx:if="{{inputVal.length > 0}}">
<navigator url="" class="weui-cell" hover-class="weui-cell_active">
<view class="weui-cell__bd">
<view>实时搜索文本</view>
</view>
</navigator>
</view>
```
一个 input 输入框 + 一个搜索 label+ 一个清楚内容的 icon + 取消按钮
```js
Page({
data: {
inputShowed: false,
inputVal: ""
},
showInput: function () {
this.setData({
inputShowed: true
});
},
hideInput: function () {
this.setData({
inputVal: "",
inputShowed: false
});
},
clearInput: function () {
this.setData({
inputVal: ""
});
},
inputTyping: function (e) {
this.setData({
inputVal: e.detail.value
});
}
});
```
input 上面有一层 label 通过 Page 里面状态的改变而操作其 wxml 状态的改变<br>
不难体会到:小程序和 Vue 的思想还是挺接近的
## 站在巨人的肩膀上为大佬们提供云音乐 API
```
---获取云音乐api
```
> [巨人的源 github 项目](https://github.com/Binaryify/NeteaseCloudMusicApi)<br>
在此我将他部署到 leancloud 上<br>
即可在线访问,免去烦人的本地 localhost 启动,在线 url<br>
[http://neteasemusic.leanapp.cn](http://neteasemusic.leanapp.cn)<br>
调用例子:<br>
[http://neteasemusic.leanapp.cn/search?keywords](http://neteasemusic.leanapp.cn/search?keywords)=海阔天空<br>
[http://neteasemusic.leanapp.cn/lyric?id=347230](http://neteasemusic.leanapp.cn/lyric?id=347230)<br>
![](https://www.writebug.com/myres/static/uploads/2021/12/5/5df67bd8d64a9ea9faec269899d73d5f.writebug)
具体参考 API<br>
> [详细文档](https://binaryify.github.io/NeteaseCloudMusicApi/#/?id=neteasecloudmusicapi)<br>
## 一切具备 只欠东风
生成目录
```
.
|-- app.js
|-- app.json
|-- app.wxss
|-- common.js #公用js
|-- images #存放项目图片
|-- style
| |-- weui.wxss # 引入weui样式 万一你自己不想写css样式呢
|-- pages
| |-- find # 发现音乐
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| |--my # 我的音乐
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| |--now # 正在播放
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| |--account # 账号
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| |-- index # 主页
| | |-- index.js
| | |-- index.json
| | |-- index.wxml
| | `-- index.wxss
| `-- log # 日志页面
`-- utils # 工具
`-- util.js
```
请先在在 app.json 中注册页面,设置 navigation,配置 tabbar<br>
```js
{
"pages":[
"pages/find/index",
"pages/my/index",
"pages/now/index",
"pages/a