网易云音乐小程序开发笔记
基础知识
setData同步异步问题
setData在逻辑层的操作是同步,因此this.data中的相关数据会立即更新;setData在视图层的操作是异步,因此页面渲染可能并不会立即发生。
之所以后者是异步,主要是考虑到将数据从逻辑层发送到视图层的过程中相比直接在逻辑层内操作会花费更多时间也会有更多不确定,于是为保证前端用户体验与减少系统开销,就索性异步了。
但是setData的设计也考虑到有些代码需要在确定setData引起的页面渲染完成后才执行,因此setData其实是有预留渲染完毕后的回调函数的:Page.prototype.setData(Object data, Function callback)。
比如下面这个代码片段,就是渲染完毕后才弹出提示对话框,以保证用户体验一致
1 | self.setData({ |
内网穿透
手机访问微信小程序,无法获取pc端的node服务器localhost:3000地址,因为是在内网,而不是公网。因此要想让手机能够访问微信小程序获取数据,需要使用内网穿透工具,推荐使用uTools。https://u.tools/
安装后按Alt+Space可以唤出utools,首先安装内网穿透插件,然后注册、登录。如下开启内网穿透
访问http://music163.cn.utools.club/banner 即可获取首页轮播图的数据
网络请求
wx.request()
报错

原因
- 协议必须是https
- 一个接口最多配置20个域名(网页端配置),配置http:localhost:3000不行,因为不支持http,同时也不支持localhost,网页端配置的必须是线上服务器地址
- 并发限制上限为10个
- 开发过程中需要在详情中如下设置不校验域名
请求统一封装
1 | const BASE_URL = 'http://localhost:3000' |
数据驱动样式Demo
页面的js代码都在Page函数中,Page函数中的对象类似于rn中类组件的this,使用箭头函数避免this作用域问题
1 | import { WxRequest } from "../../utils/request" |
设置小程序底部tab栏
app.json中配置即可
1 | "tabBar": { |
事件绑定
事件绑定传参数
1 | <input id="phone" data-type="phone" bindinput="handleInput" class="inputText" placeholder="请输入手机号码" value="{{phone}}"/> |
1 | /** |
- 注意:方法之间的公共变量定义在page函数外面
- bind:tap等同于bindtap
1 | <view |
1 | // pages/personal/personal.js |
toast
自定义提示方法
1 | /** |
在封装发送请求时,可以在请求发送前显示loading,请求发送后关闭loading,防止用户网络不好等待时间太长或者重复点击
1 | import { showToastAsync, showLoadingAsync, hideLoadingAsync } from "../toast/toast" |
转发分享
实现
1 | /** |
title:转发标题
path:转发的页面地址,默认使用当前页面
imageUrl:默认使用当前页面的截图,如果设置,则使用设置的图片
分享到朋友圈
前提:页面js中onShareAppMessage和onShareTimeline回调均存在
可以在onShareTimeline中设置分享到朋友圈的内容
数据缓存封装
微信小程序缓存支持Object类型,也支持数组
1 | import { showToastAsync } from "../toast/toast" |
小程序中使用npm
1、项目根目录下执行npm init -y初始化package.json
2、开发者工具设置使用npm模块
3、下载npm包
npm install 包名
例如 pubsub-js包 ,可以实现页面与页面之间的通信。它是通过自定义事件(订阅与发布)的方式进行的。引入包:import PubSub from ‘pubsub-js’,订阅方:PubSub.subscribe(事件名,事件回调),发布方:PubSub.publish(事件名,提供的数据)
4、构建npm
开发工具 –》 工具 –》 构建npm
会将 node_modules 中的包打包到 miniprogram_npm 中
注意:执行之后引入的第三方包就会到 miniprogram_npm 中找,如果没找到就会按相对路径查找,没找到就会报错
单例模式
问题:多个视频同时播放
需求:
1、在点击播放的事件中需要找到上一个播放的视频
2、在播放新的视频之前暂停上一个正在播放的视频
实现:
单例模式:需要创建多个对象的场景下,通过一个变量接收,始终保持只有同一个对象,节省内存空间
1 | handlePlay:function(e){ |
自定义模板
杂七杂八
navigationBarTextStyle属性只支持hex,不支持red white等字符形式的颜色,color和background-color等一般属性都只是字符串形式的颜色
微信小程序background-image属性不支持本地图片,支持线上地址或者base64
和rn不同,小程序颜色会继承
js 7/2结果是小数,不会自动取整
js字符串padStart和padEnd方法可用于格式化时间字符串
小程序的里面不允许写js代码(三元表达式除外),只允许写一个this.data中的变量名,和rn不同
小程序颜色如何设置透明度,使用hex透明度,如background-color:#0000005a
推荐使用类选择器
WXML中的属性是大小写敏感的
currentTarget为当前事件所绑定的组件,而target则是触发该事件的源头组件。
小程序一般使用rpx作为相对屏幕尺寸,类似rn中的pxToDp方法,所有的机型宽度都为750rpx,1px=2rpx
wx.showToast()弹出提示框,
和rn中类组件一下,可以使用this.变量名 = 值 给this对象上挂上属性,方便全局共享
页面中可以直接调用,函数中不可以,需要解构this.data
小程序的100vh不包括最下面的tabbar的高度和自身的margin高度, calc函数可以动态计算css的宽高,运算符两次必须加空格,否则无法计算
moment-js库可以用来处理时间和日期转换
less中如何使用calc函数,https://blog.csdn.net/baidu_39305094/article/details/93178381
文本溢出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//单行文本溢出
text{
display:block //text是内联元素,overflow:hidden会失效,将其转为块元素
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap
}
//多行文本溢出
text{
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-box-orient:vertical; //设置对其模式:垂直对齐
-webkit-line-clamp:2; //2行,超出2行则用省略号代替
}
模板
wx:for
1 | <view |
wx:if
1 | //如果数组有值才会显示播放记录 |
路由
wx.switchTab
跳转到tabBar页面,并关闭其他所有非tabBar页面
wx.reLaunch
关闭所有页面,打开到应用内的某个页面
wx.redirectTo
关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
wx.navigateTo
保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面
wx.navigateBack
关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层
如何返回上一级页面并刷新
如何返回上一级页面-并刷新页面
在使用wx.navigateTo()API 进行跳转时,在子页面中可以通过wx.navigateBack()返回上一级页面的
这个场景在日常开发中,就有不少的
例如:写完微博,发完微博成功后,自动要返回到首页,申请退款时,跳转到申清退款页面等等的
1 | const pages = getCurrentPages(); // 可以获取当前页面栈,上一个页面以及当前页面栈信息 |
这个方法非常厉害,而且很有用,当你通过wx.navigateTo(),一层一层跳转到子页面时,使用getCurrentPages方法就可以找到上级,上上级的页面栈信息
它是通过获取到其他页面的原型对象,然后通过小程序原型下的setData方法,对当前对象管理的数据data进行修改
这个方法getCurrentPage方法可以操作页面堆栈页面的数据和方法,可以做到对子(后一)页面对父(上一)页面的数据管理
提示
getCurrentPages()用于获取当前页面栈,数组中第一个元素为首页,最后一个元素为当前页面
不要尝试修改页面栈,会导致路由以及页面状态错误(不要依赖这个方法)
不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成
路由传参的几种方法
详见链接:https://blog.csdn.net/wzc_coder/article/details/109634775
页面间通过
url方式传递数据url的方式适合页面间跳转携带参数,多个参数之间使用&符号拼接- 此方法有一定的局限性,不适宜传入复杂的数据,例如:数组,对象
- 适合参数比较少的情况
- 一般打开新页面在navigateTo方法中使用,如果使用navigateBack,那么在onLoad函数中无法接收到该函数,因为页面已经被打开,onLoad生命周期已经过去,可以用onShow生命周期
wx.navigateBack()方法结合getCurrentPages()方法更新数据
使用全局
app页面定义的变量实现数据的传递//app.js中onLaunch中定义 App({ onLaunch: function() { // 定义的全局变量,如token,某些状态等,放在globalData下 this.globalData = { token: 'token', url: 'http://coder.itclan.cn/', userInfo: 'itclanCoder', }; }, }); //使用页面 const app = getApp(); // 在另一页面想要使用全局变量处,调用getApp() Page({ // 页面初始化的数据 data: { token: '', url: '', userInfo: '', }, // 生命周期函数 onLoad: function(options) {}, onGetGlobal() { // 获取全局变量 const { token, url, userInfo } = app.globalData; console.log(token, url, userInfo); this.setData({ token, url, userInfo, }); }, });1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
* 使用本地缓存,跳转路由前一般使用`wx.setStorageSync`:同步设置本地存储某个指定的`key`数据,跳转路由后`wx.getStorageSync`:同步获取本地存储某个指定`key`的数据,数据使用完毕后可以使用wx.removeStorageSync`:从本地存储中同步移除指定的key`
* 除非用户主动删除或因存储空间原因被系统清理,否则数据都一直可用。单个 `key` 允许存储的最大数据长度为 1MB,所有数据存储上限为 `10MB`,一般可以作为缓存临时一些小的数据,比如用户登录信息之类的
* 本地缓存的清理时机跟代码包一样,只有在代码包被清理的时候本地缓存才会被清理
* 使用`eventChannel`向被打开页面传送数据(`wx.navigateTo`高级用法),订阅模式。
### 路由触发生命周期
对于路由的触发方式以及页面生命周期函数如下:
| 路由方式 | 触发时机 | 路由前页面 | 路由后页面 |
| :--------- | :----------------------------------------------------------- | :--------- | :----------------- |
| 初始化 | 小程序打开的第一个页面 | | onLoad, onShow |
| 打开新页面 | 调用 API [wx.navigateTo](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html) 使用组件 [``](https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html) | onHide | onLoad, onShow |
| 页面重定向 | 调用 API [wx.redirectTo](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.redirectTo.html) 使用组件 [``](https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html) | onUnload | onLoad, onShow |
| 页面返回 | 调用 API [wx.navigateBack](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateBack.html) 使用组件[``](https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html) 用户按左上角返回按钮 | onUnload | onShow |
| Tab 切换 | 调用 API [wx.switchTab](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.switchTab.html) 使用组件 [``](https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html) 用户切换 Tab | | 各种情况请参考下表 |
| 重启动 | 调用 API [wx.reLaunch](https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.reLaunch.html) 使用组件 [``](https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html) | onUnload | onLoad, onShow |
Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):
| 当前页面 | 路由后页面 | 触发的生命周期(按顺序) |
| :-------------- | :------------ | :------------------------------------------------- |
| A | A | Nothing happend |
| A | B | A.onHide(), B.onLoad(), B.onShow() |
| A | B(再次打开) | A.onHide(), B.onShow() |
| C | A | C.onUnload(), A.onShow() |
| C | B | C.onUnload(), B.onLoad(), B.onShow() |
| D | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
| D(从转发进入) | A | D.onUnload(), A.onLoad(), A.onShow() |
| D(从转发进入) | B | D.onUnload(), B.onLoad(), B.onShow() |
**Tips**:
- `navigateTo`, `redirectTo` 只能打开非 tabBar 页面。
- `switchTab` 只能打开 tabBar 页面。
- `reLaunch` 可以打开任意页面。
- 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
- 调用页面路由带的参数可以在目标页面的`onLoad`中获取。
## 组件介绍
### 自定义组件components
<img src="https://gitee.com/chen_hexi/image-source/raw/master/img/20210514151331.png" alt="image-20210330100132753" style="zoom: 50%;" />
组件属性定义
<img src="https://gitee.com/chen_hexi/image-source/raw/master/img/20210514151335.png" alt="image-20210330104740293" style="zoom:50%;" />
组件html中使用属性
<img src="https://gitee.com/chen_hexi/image-source/raw/master/img/20210514151340.png" alt="image-20210330105056696" style="zoom:50%;" />
**在要使用这个组件的page的json文件中**
<img src="https://gitee.com/chen_hexi/image-source/raw/master/img/20210514151343.png" alt="image-20210330104939679" style="zoom:50%;" />
在page中使用

### view
类似div和rn中的View,占位标签
类似于rn中view和scrllview容器集合,小程序中垂直方向内容溢出会自动出现滚动条
### text
文本标签,包裹文字,不是必须要有
rn中不允许文字单独显示,必须要包裹在Text标签中,微信小程序中不是必须要有text标签包裹
注意:text标签中换行将被显示在界面上
### swiper
indicator-dots 是否显示底部圆点
indicator-color 圆点未被选中的颜色
indicator-active-color 圆点选中的颜色
next-margin 设置是否让下一个轮播的区域在屏幕中提前显示,提醒用户该组件可以轮播
```html
<!-- 轮播图区域 -->
<swiper class="swiperContainer" indicator-dots="true" indicator-color="#ffffff" indicator-active-color="#ea4a2b">
<swiper-item>
<image src="../../static/images/nvsheng.jpg" />
</swiper-item>
<swiper-item>
<image src="../../static/images/nvsheng.jpg" />
</swiper-item>
<swiper-item>
<image src="../../static/images/nvsheng.jpg" />
</swiper-item>
<swiper-item>
<image src="../../static/images/nvsheng.jpg" />
</swiper-item>
<swiper-item>
<image src="../../static/images/nvsheng.jpg" />
</swiper-item>
</swiper>
image
<image src="../../static/images/nvsheng.jpg" />
scroll-view
可滚动视图区域,使用竖向滚动时,需要给它设置一个固定高度,通过WXSS设置height,组件属性的长度单位默认为px
| 属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
|---|---|---|---|---|---|
| scroll-into-view | string | 否 | 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 | 1.0.0 | |
| scroll-with-animation | boolean | false | 否 | 在设置滚动条位置时使用动画过渡 | 1.0.0 |
| scroll-x | boolean | false | 否 | 允许横向滚动 | 1.0.0 |
| scroll-y | boolean | false | 否 | 允许纵向滚动 | 1.0.0 |
| enable-flex | boolean | false | 否 | 启用 flexbox 布局。开启后,当前节点声明了 display: flex 就会成为 flex container,并作用于其孩子节点。 |
2.7.3 |
| refresher-enabled | boolean | false | 否 | 开启自定义下拉刷新 | 2.10.1 |
| refresher-triggered | boolean | false | 否 | 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 | 2.10.1 |
| bindrefresherrefresh | eventhandle | 否 | 自定义下拉刷新被触发 | 2.10.1 |
如何设置横向滚动,并且不设置高度,那么它的高度会很高,默认时内部元素竖向排列的高度,给scroll-view设置一个高度即可
scroll-into-view结合scroll-with-animation可以实现点击tab永远在最前并且移动过渡效果,注意scroll-into-view应该为某子元素id,不能以数字开头
refresher-enabled结合refresher-triggered和bindrefresherrefresh属性可以实现scroll-view下拉刷新
注意区分滚动条上拉加载、下拉刷新与页面的下拉onPullDownRefresh和上拉触底onReachBottom的区别,同时,要触发onPullDownRefresh,必须在配置项中设置enablePullDownRefresh为true
video
1 | <video |
button
open-type属性可用来实现特殊的功能,例如转发分享等
input
placeholder-class和placeholder-style可以用来设置placeholder的样式
注意区分input的change和input事件区别
对于用户的操作及时响应是非常优秀的体验,有时候在点击button按钮处理更耗时的操作时,我们也会使用button组件的loading属性,在按钮的文字前边出现一个Loading,让用户明确的感觉到,这个操作会比较耗时,需要等待一小段时间。
showModal弹出模态框
showToast 弹出提示框
showLoading 弹出加载框
其他
vscode环境搭建
- 打开微信开发者工具,设置预编译窗口悬浮

- vscode安装插件支持微信小程序开发 wxml minapp、wechat-snippet EasyWXLESS(支持将微信LESS文件自动转换为WXSS微信样式文件),同时EasyLess要在当前工作区(小程序环境)内禁用,这样省得一个less编译出css和wxss两种文件,小程序开发只要一种wxss就好
引入iconfont
在官网图标选择图标添加到项目,然后选择fontclass,生成在线代码,但是这个是css格式的,小程序不支持css,需要将这个代码打开,复制css代码并保存到项目中新建的iconfont.wxss文件中,可以理解为存储的是选择图标的离线数据。如果在线项目图标库更新,需要重新生成css代码并拷贝到iconfont.wxss文件中



