微信小程序实战-音乐播放器

5,040 阅读4分钟

最近学习微信小程序,自己做了一个音乐播放器。整个过程学习下来感觉微信小程序对于前端的同学来说还是很容易掌握的,但是有一些知识点还是要记录一下。

演示

目录结构

发送网络请求需要在后台配置

我使用的是open api,主要用到的接口有:

发送网络请求时需要在微信小程序后台配置一下自己合法域名,要不然发网络请求的时候会报错。

进到小程序后台找到开发

二级选项卡选择开发设置

拉到下面有一个服务器域名,在request合法域名中配置自己的api路径。

另外在小程序里使用request方法不存在跨域的问题,因为微信小程序的做法是由他们的后台访问我们的后台,所以实际的“跨域问题”已经在我们的小程序与微信后台交流的时候解决了。

页面跳转时参数的传递和接收

传递参数的方式有两种:

  • 在wxml中使用navigator跳转url传递参数
  • 在wxml中绑定事件后,通过data-name="姓名"的方式传递

第一种方式

发送参数:

<navigator url="../../pages/user?name={{name}}"></navigator>

接收参数:

onLoad: function (options) {
    var name = options.name;
}

第二种方式

发送参数:

<view bindtap="click" data-name={{name}}"></view>

接收参数:

clickMe: function(event) {
    var name = event.currentTarget.dataset.name;
}

wxs模块

WXS 代码可以编写在 wxml 文件中的 标签内,或以 .wxs 为后缀名的文件内。

使用wxs的场景主要是对一些数据有一些复杂的处理时,例如我在写排行榜页面时有一个颜色值的处理,应为后端接口返回的是颜色值是 0xFFFFFF,所以我需要降这个值转化为#FFFFFF这种形式的,下面是我的wxs文件:

//hexColor.wxs
var hexColor = function(color) {
  return !!color && color.replace('0x', '#');
}
module.exports = hexColor;

使用也很简单

<wxs src="../../utils/hexColor.wxs" module="hexColor" />
<view  data-color="{{hexColor(item.bg_color)}}">
    ...
</view>

组件化开发

在小程序中也可以使用组件,组件的使用分三步:

第一步:创建组件

创建组件时最重要的一步就是在json文件中写明

{
    component: true
}

例如:

第二步:编写组件代码

这一步很简单,只需要按你的功能写代码就好了。

第三步:使用组件

使用组件时要在使用组件的那个页面的json配置文件里添加使用声明

{
  "usingComponents": {
    "component": "../component/component"
  }
}

然后直接使用就可以了。

全局变量

微信小程序的全局变量是写在app.js的globalData上的

使用时需要在页面中获取app实例

//引入app实例
const app = getApp();
//使用
app.globalData.playState,

开发者工具bug

我要实现的功能就是页面切换时同步播放器的状态。

pageLifetimes就是组件所在页面的生命周期。

但是我在开发过程中发现了一个开发者工具的bug,就是pageLifetimes在开发者工具中不会触发,但是在android真机调试的时候就会触发。

跨层级通信

这是我在开发中遇到的比较棘手的问题,就是一个列表页面点击了某首歌曲,这个时候我要通知播放器组件切换音乐,这就涉及到了跨层级通信,目前我的解决办法是利用发布-订阅模式来实现这个功能。

class PubSub{
  constructor(props){
    this.handlers = {};
    this.instance = undefined;
  }
  /**
   * 单例模式
   */
  static getInstance() {
    if (this.instance === undefined) {
      this.instance = new PubSub();
    }
    return this.instance;
  }
  /**
   * 订阅事件
   */
  on(eventType, handler) {
    //p判断事件名称是否在handler中,防止重复添加
    if (!(eventType in this.handlers)) {
      this.handlers[eventType] = [];
    }
    //将毁回调放到处理队列中
    this.handlers[eventType].push(handler);
    return this;
  }
  /** 
   * 触发事件(发布事件)
   */
  emit(eventType) {
    //取出传递过来的参数
    var handlerArgs = Array.prototype.slice.call(arguments, 1);
    //循环执行对应事件的处理函数
    for (var i = 0; i < this.handlers[eventType].length; i++) {
      this.handlers[eventType][i].apply(this, handlerArgs);
    }
    return this;
  }
  /**
   * 删除订阅事件
   */
  off(eventType, handler) {
    var currentEvent = this.handlers[eventType];
    var len = 0;
    if (currentEvent) {
      len = currentEvent.length;
      for (var i = len - 1; i >= 0; i--) {
        if (currentEvent[i] === handler) {
          currentEvent.splice(i, 1);
        }
      }
    }
    return this;
  }
}

export default PubSub.getInstance();

上面是我写的一个功能包,简单的实现了一个发布-订阅模式,实现思路就是维护一个handlers 对象,每次注册事件为对应的key注册一个数组,数组里面存放相应的钩子函数,注册和触发事件维护这个这个对象就可以了。

最后献上源码TinySQ

o(^@^)o