WeScale 技术篇 —— mpvue 与微信小程序的火花

介绍

项目介绍

WeScale 定位为音乐训练小程序,初期规划了基础音阶的三个训练,以及他们的镜像模式。

  • 数字简谱
  • 字母简谱
  • 数字简谱对字母简谱

后期看情况更新追加其他训练。

产品展示

扫描下方小程序码或在微信小程序中搜索 WeScale,即可使用。

人员介绍

  • Myou Aki:明神,北漂前端,总有奇奇怪怪的想法想要实现,适合做产品的前端

  • Dr.Chan:老陈,后端、前端通吃,长得帅说话又好听的茂名吃货

  • Jackliu:大坚,产品、伪前端,不想做前端的产品不是好司机

缘起

明神每晚都要练着他的电吉他,敲着他的木鱼,突然一道光在脑海中闪过,机智的他迅速捕获到,当晚凌晨三点做完了这次小程序的原型。

之前和老陈搞了个 A股股票助手 — stock-helper ,这次有明神带路,我们都想积累点小程序开发的经验,于是我和老陈就上车了。(滴~~学生卡)

恰逢美团刚刚开源了 mpvue,短短几周就迅速获得几千个 star,在 mpvue 开源前,最流行的应该是 wepy 。据说用 mpvue,能够像德芙一样顺滑地使用 vue 写微信小程序,于是我们开始了踩坑之路。

项目统计

预计一周完成,毕竟是大家都有正经事要做,硬是拖到了两周才完成。四个分支,总计提交 51次,越到 deadline 提交越多,目前已发布 v1.0.0 版本,已审核上线。

踩到的坑

  • 微信小程序不能使用本地资源

这个坑很常见,微信小程序不支持本地引用图片、音频、视频,所以需要外链。对于图片还可以使用 Base64 编码,直接在 html 或 css 中引用。根据图片根据图片体积或者可维护性考虑,酌情使用外链或者Base64编码。

  • 新增页面需要 npm run dev

这个是 mpvue 的问题。常见问题可以发现。解决的方法就是手动 npm run dev 一下。

  • 生命周期问题

mpvue 是兼容微信小程序的生命周期与 vue 的生命周期,也就是 vue 实例会接管小程序 Page 实例的生命钩子,因此需要使用到小程序的生命周期钩子时,可将相应的钩子方法定义在 vue 实例中,如定义当前Page的分享标题内容图片:

new Vue({data () {return {score: ''}},onShareAppMessage (res) {return {title: '我获得 '   this.score   ' 分,快来一起掌握基础音阶知识吧!',path: '/pages/index/index',imageUrl: 'https://wechat.dddog.com.cn/static/wescale.jpg'}}
})

这个不知道如何描述,大致是非当前页面的 create() 会在当前页面执行,解决方法,用小程序的 onload()/ vue 的 mounted(),遇到问题看图就好:

lifecycle

  • Class 与 Style 绑定

不支持 vue 官方文档:Class 与 Style 绑定中的 classObject 和 styleObject 语法。 暂不支持在组件上使用 Class 与 Style 绑定

不支持就不用咯~

  • 没有 BOM/DOM 操作

mpvue 使得开发者可以使用标准 html、css 去编写小程序,当我们查看 mpvue 项目中的 dist 文件夹时可以发现,编写的 html、css 被解析成了小程序的 wxml、wxss ,固然小程序的运行环境也就是非标准的 WebView 了。因此我们web开发进行经常使用的 browser、navigator 实例自然是无法使用了,取而代之的是使用小程序浏览器提供的API —— wx实例去操作native元素。至于 DOM 操作,即使在vue中也是不建议使用的,还是用数据驱动去转化吧。也就是说所有关于 BOM / DOM 的操作都不行。用 vue 第三方 UI库时要注意, Dom 和 Bom 相关的 API 操作都无法实现。 解决方案: 这块主要是动画不能用,那就用 css3 咯~

  • 组件名不要和微信的组件名重名

试着写一个 swicth 的组件,发现渲染结果不对,查了原因才发现,微信小程序也有个 switch 的组件。 解决方案: 改名字啊。命名规范!

  • 微信小程序多声道

按正常的套路去使用小程序的 api —— wx.createInnerAudioContext() 是无法创建多声道的。本次技术的难点也在于如何创建微信小程序的多声道。查了一圈的资料,关于这点的资料甚少。查到一篇博客,通过创建多个 innerAudioContext 实例化对象,轮流调用的方式。对于原作者说小程序只能同时存在5个音频实例这一定,不敢苟同。毕竟我直接创建了 30个都没问题,哈哈

const audioContextNum = 30
let globalAudioContext = Array.from({ length: audioContextNum },(v, k) => wx.createInnerAudioContext())

如何寻找当前可用的声道,也是个难点,大致的思想是,把正在播放的实例封锁,待实例的 onEnded() 回调执行时取消封锁,使用时需要遍历所有实例,寻找当前可用的实例,看实例代码(与实际代码有删改):

// 自动寻找一个当前可用的 audioContext 实例
export function playedMusic (url) {let contextList = store.getters.globalAudioContextwhile (contextList !== store.getters.audioContextStatus.map(item => item === false).length) {let audioContextStatus = store.getters.audioContextStatuslet index = store.getters.currentAudioIndex// 如果当前可用,封锁if (audioContextStatus[index]) {store.commit('setAudioContextStatus', {index, status: false})break} else {// 否则   indexstore.commit('setCurrentAudioIndex',   index)}}const resultPromise = new Promise((resolve, reject) => {contextList[index].onPlay(() => {})contextList[index].onError((res) => {reject(res)})contextList[index].onEnded((res) => {reset(resolve)})})return resultPromise
}
  • 微信小程序的缓存

实际开发过程中发现。如果不预先对音频进行缓存,实际播放时会有一定的延迟,视网络情况。解决方案是先预加载,然后存在小程序的缓存中,官网介绍缓存有 10 M,足够用了。 首先是下载文件 wx.downloadFile(),得到 tempFilePath,再把临时文件保存为本地文件 wx.saveFile(),得到 savedFilePath,再将本地文件的的路径保存在缓存中 wx.setStorage()。这么多异步操作,当然用 Promise 再封装一下啦。

多文件的下载、保存、缓存, 回调、递归的思想:

  // 加载资源, 加载完隐藏loading_load(0, () => {// 更改Audio.js的config对象属性。config.musicUrl = JSON.parse(musicUrlTemp)const temp = JSON.parse(musicUrlTemp)temp.tempVerison = tempVerisonwx.setStorage({key: 'musicUrl', data: temp})wx.hideLoading()})function _load (index, callback) {if (!musicUrlArr[index]) {callback()} else {downloadFile(musicUrlArr[index]).then((tempFilePath) => {saveFile(tempFilePath).then((savedFilePath) => {musicUrlTemp = musicUrlTemp.replace(musicUrlArr[index],savedFilePath)index  _load(index, callback)})})}}

缓存是否存在及缓存版本的判断:

  // 判断是否已有缓存且缓存版本正确if (temp && temp.tempVerison === tempVerison) {return false}
  • 全局变量

遇到很多需要全局变量,特别是状态的,最好统一管理。vue 的 vuex 是专为 Vue.js 应用程序开发的状态管理模式。使用过程遇到的坑是无法使用它的辅助函数 mapState、 mapGetters、 mapActions、 mapMutations 等。看下 mpvue 的 issue 感觉是 mpvue 的问题。 解决方案: 用最原始的 store.commit()、 store.getter

  • 数据分析及合法域名

调用微信小程序的网络请求 wx.request()、 wx.downloadFile() 之类 都需要 https 协议。 调微信的数据分析还要隔两个小时获取 access_token, 这些就是要服务器端的配置了。

条件: 域名及域名证书、服务器

获取 token 及 服务器写接口返回静态文件及微信的数据分析接口 可以参考这个, node.js 写的,写的很随意,随便看看。

  • ES6 的模块动态引用

参考博客:

  1. ES6 模块中的值属于【动态只读引用】。只说明一下复杂数据类型。
  2. 对于只读来说,即不允许修改引入变量的值, import 的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到 import 命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
  3. 对于动态来说,原始值发生变化, import 加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
// b.js
export let counter = {count: 1
}
setTimeout(() => {console.log('b.js-1', counter.count)
}, 1000)// a.js
import { counter } from './b.js'
counter = {}
console.log('a.js-1', counter)// Syntax Error: "counter" is read-only

虽然不能将 counter 重新赋值一个新的对象,但是可以给对象添加属性和方法。此时不会报错。这种行为类型与关键字 const 的用法。

// a.js
import { counter } from './b.js'
counter.count  
console.log(counter)// 2

致谢

致谢所有参与产品、开发、测试,贡献出创意想法与建议的小伙伴。

我们有个小团队,自嘲为“咸鱼科技”,谁说咸鱼不能有梦想,哈哈。我们还需要 UI、运营等,如果你有想法、有创意、有技能可以加入我们的小团队!2333~




更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/366485.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Maven程序集创建漏洞评估工件

本文将讨论如何使用Maven程序集创建可提供给第三方漏洞评估站点(例如Veracode )进行审查的工件。 错误的静态分析与漏洞评估 在这一点上,每个人都知道findbug并虔诚地使用它,对吗? 对? Findbugs使用静态…

洛谷 P3835: 【模板】可持久化平衡树

题目传送门:洛谷P3835。 题意简述: 题面说的很清楚了。 题解: 考虑建立一棵每个节点都表示一个版本的树。 以初始版本 \(0\) 为根。对于第 \(i\) 个操作,从 \(v_i\) 向 \(i\) 连一条边,而边权则是 \(opt_i\) 和 \(x_i\…

自动论文生成器 python_Python生成器常见问题及解决方案

在Python中,生成器和函数很像,都是在运行的过程中才会去确定各种变量的值,所以在很多情况下,会导致各种各样的问题。def generator_test1():# 0...9 generatorx (i for i in range(10))# 5..9 generatorx_filter filter(lambda …

025 SSM简单搭建

参考了同事的文档,自己也写一篇文档。 同时,补充了一下,程序是如何运行的。 一:SSM框架 1.说明 SSM(SpringSpringMVCMyBatis)框架集由Spring、SpringMVC、MyBatis三个开源框架整合而成,常作为数…

让Vue也可以使用Redux

上周末看Vuex源码,突发灵感,为什么都是Vuex啊。 于是蛋疼一下午写了一个插件来帮助Vue可以使用Redux Gayhub Url Vue-with-Redux 这是一个用于帮助Vue使用Redux管理状态的插件。Redux是一个非常流行的状态管理工具。vue-with-redux为大家提供一个可以…

Apache Camel –从头开始开发应用程序(第2部分/第2部分)

这是本教程的第二部分,我们将使用Apache Camel创建发票处理应用程序。 如果您错过了它,一定要看一下第一部分 。 以前,我们已经定义了系统的功能要求,创建了网关,分离器,过滤器和基于内容的路由器组件。 让…

上升沿_PLC上升沿,下降沿的理解

有网友留言说:上升沿就是在信号从断开到接通的那一瞬间接通,下降沿就是在信号从接通到断开的那一瞬间接通。但是现在的问题它的实际用处是用在哪一些情况。我身边也有PLC可以做个什么实验来体验一下呢?虽然说LD X0 PLS M0与LDP X0 out Y0…

内存的页面置换算法

在进程运行过程中,若其所要访问的页面不在内存而需把它们调入内存,但内存中已无空闲空间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据到磁盘的对换区中。但应将哪个页面调出,需根据一定的算法来实…

A - 装箱问题

Problem Description 一个工厂生产的产品形状都是长方体,高度都是h,主要有1*1,2*2,3*3,4*4,5*5,6*6等6种。这些产品在邮寄时被包装在一个6*6*h的长方体包裹中。由于邮费很贵,工厂希望…

非阻塞式异步Java 8和Scala的Try / Success / Failure

受Heinz Kabutz最近的时事通讯以及我在最近的书中研究的Scala的期货的启发,我着手使用Java 8编写了一个示例,该示例如何将工作提交给执行服务并异步地响应其结果,并使用了回调。无需阻止任何线程等待执行服务的结果。 理论认为,调…

中找不到iedis_CAD图纸中缺少的字体实在找不到怎么办呢?

在使用浩辰CAD软件打开图纸文件的时候经常提示缺少字体这是什么原因呢?怎么解决这个问题呢?其实打开CAD图纸时提示缺少字体是比较常见的情况,但是很多常见的字体也提示缺失是为什么呢?因为这些字体很显然是被人改过名字了&#xf…

Xamarin Essentials教程使用指南针Compass

Xamarin Essentials教程使用指南针Compass指南针是一种确定地理方向的工具。在手机应用程序中,指南针通过手机的磁力计确定磁北极,提供手机方向信息。在Xamarin中,开发者可以使用Xamarin.Essentials中的静态类 Compass,获取方向信…

Java 8中的instanceof运算符和访客模式替换

我有一个梦想,不再需要操作员和垂头丧气的instanceof ,却没有访客模式的笨拙和冗长。 所以我想出了以下DSL语法: Object msg //...whenTypeOf(msg).is(Date.class). then(date -> println(date.getTime())).is(String.class). then(…

1023 Have Fun with Numbers

因为最多有20个字符&#xff0c;int和long long都不行&#xff0c;所以只能用字符串操作。水题~ #include<iostream> #include<algorithm> #include<string.h> #define maxn 25 using namespace std; typedef long long ll; char s1[maxn]; int s2[maxn]; in…

前端生态混乱,AMPMIP在努力做标准化工作

作者 | Brilliant Open Web团队breezet 移动时代的前端似乎越来越混乱了&#xff0c;各种技术方案层出不穷&#xff0c;令开发者们目不暇接&#xff0c;不知如何选择。然而&#xff0c;生态越是混乱&#xff0c;对标准的呼唤就越强&#xff0c;因为只有标准化才能使得整个生态…

python逆向什么意思_如何理解python逆向切片

str 0123456789(推荐教程&#xff1a;python基础教程)如上,我们有一个数值型字符串,接下来我们分别从正向和逆向两个维度截取数据。str[start:end:step]start表示起始下标end表示结束下标step表示步长下面这个图,表示了正向和逆向下标的值首先我们要说一下方向的事情&#xff…

调试工具gdb

1.1 gdb符号调试器简介 gdb是一个用来调试C和C程序的功能强大的调试器&#xff0c;它能在程序运行时观察程序的内部结构和内存的使用情况。 gdb主要提供以下几种功能&#xff1a; 监视程序中变量值的变化设置断点&#xff0c;使程序在指定的代码行上暂停执行&#xff0c;便于观…

Apache Camel –从头开始开发应用程序(第1部分/第2部分)

开始之前 前一段时间&#xff0c;我写了一篇关于Spring Integration的教程&#xff0c;以演示如何在受现实发票处理系统启发的示例应用程序中使用Spring Integration。 我对此非常满意&#xff0c;因此我决定向您展示如何使用Apache Camel&#xff08;Spring Integration的最大…

Bourbon: 让你的sass更简洁

Bourbon是什么 bourbon是一个轻量级的Sass mixin和函数库&#xff0c;可以帮助我们快速开发样式. 官方文档 以下用webpack3.10.0( vue)为示例简述Bourbon的使用 安装配置 npm install bourbon -S 把bourbon添加到node-sass的includePaths中// webpack.config.js module.expor…

nat的地址映射 华为_华为PAT端口地址映射配置详解(一)

众所周知&#xff0c;PAT,&#xff0c;Port Address Translation&#xff0c;即网络地址转换。PAT有以下作用&#xff1a;1.改变数据包的ip地址和端口号&#xff1b;2.能够大量节约公网IP地址。PAT的类型有以下&#xff1a;1.动态PAT&#xff0c;包括NAPT和Easy IP&#xff1b;…