小程序升级WePY2踩坑记

小程序升级WePY2踩坑记

最近有个小程序项目需要迭代,但是迭代任务不多,时间比较充裕。而这个小程序最早是在18年的时候开发的,用的开发框架是 WePY 的 1.7.2 版本,去年也就是 19 年的时候 WePY 框架进行了升级,到了 2.0 版本。升级之后的 WePY,用 WePY 官方文档的话来说:通过优化细节,引入 Promise、Async Functions 等让开发小程序项目变得更加简单,高效。基于这些背景,我和小伙伴一拍即合,决定对我们的项目进行框架升级,体验下到底 WePY2 能给我们带来什么。

本文将以项目改动为出发点,基于当前这个项目的结构和编码方式来考虑到底升级 WePY2 后,哪里需要改,怎么改以及有哪些需要注意的地方,通过对比 2 个版本的写法差异这个思路来写,不会去太较真 WePY2 相对于 WePY1 实现或原理上的区别。下面我将一条一条的列出来需要改动的点。

❝本篇文章记录的是我和小伙伴这次升级框架遇到的需要改动的地方和坑,所使用的是 wepy 的 2.1.0 版本,后续如果版本升级后,本篇记录到的坑如果已经被修复了,请自行忽略本文所述的问题。另外下文中所说到的 2.x 版本都是指 wepy_v2.1.0。

1、初始化一个 WePY2 的 demo由于本地还有其他项目用的是 WePY_v1.7.2,所以我们不能把 WePY2 的 CLI 工具安装在全局环境中,只能安装在当前项目中。官方推荐是直接用 1.7.x 的 CLI 去初始化 2.0.x 的项目:

代码语言:javascript复制wepy init standard#2.0.x zzodr

这样就能够在本地初始化一个 wepy2 的项目模板,但是 @wepy/core 是 2.0.0-alpha.16 版本的,将它更新到最新的 2.1.0 版本,这里也一起更新下整个旧项目和新模板所用到的依赖,下面直接贴出来:

代码语言:javascript复制{

"dependencies": {

"@wepy/core": "^v2.1.0",

"@wepy/use-intercept": "^2.1.0",

"@wepy/use-promisify": "^2.1.0",

"@wepy/x": "^2.0.2",

"miniprogram-slide-view": "0.0.3"

},

"devDependencies": {

"@babel/core": "^7.1.0",

"@babel/preset-env": "^7.1.0",

"@wepy/babel-plugin-import-regenerator": "0.0.2",

"@wepy/cli": "^2.1.0",

"@wepy/compiler-babel": "^2.0.1",

"@wepy/compiler-sass": "^2.1.0",

"@wepy/plugin-define": "^2.1.0",

"babel-eslint": "^7.2.1",

"cross-env": "^5.1.3",

"eslint": "^3.18.0",

"eslint-config-standard": "^7.1.0",

"eslint-friendly-formatter": "^2.0.7",

"eslint-plugin-html": "^2.0.1",

"eslint-plugin-promise": "^3.5.0",

"eslint-plugin-standard": "^2.0.1",

"wepy-eslint": "^1.5.3"

}

}

接下来操作主要是删除模板里的代码,然后把项目的结构和代码搬过去。

2、wpy 文件代码结构调整WePy 单文件组件主要由

2.x 写法:

代码语言:javascript复制

{

navigationBarTitleText: '首页'

}

3、 程序/页面/组件注册方式调整注册方式将不再使用继承的方式,而是改成直接调用对应的实例方法。1.7.2 写法:

代码语言:javascript复制export default class APP extends wepy.app {} // 注册程序

export default class HOME extends wepy.page {} // 注册页面

export default class LIST extends wepy.component {} // 注册组件

2.x 写法:

代码语言:javascript复制wepy.app({}) // 注册程序

wepy.page({}) // 注册页面

wepy.component({}) // 注册组件

4、代码结构由类结构变成对象结构由于注册方式的改变,那么自然的代码结构也要有所调整。1.7.2 写法:

代码语言:javascript复制export default class HOME extends wepy.page {

data = {}

methods = {}

onLoad() {}

onShow() {}

}

2.x 写法:

代码语言:javascript复制wepy.page({

data: {},

methods: {},

onLoad() {},

onShow() {},

})

上面仅仅只是以页面做为例子,wepy.app() 和 wepy.component() 也要对应调整。

5、自定义方法和组件事件处理函数需要移到 methods 里在 WePY 1.7.2 中注册的页面或者组件函数有这么几种类型:

生命周期函数,比如 onLoad、onShow 等;wxml 事件处理函数,即在 wxml 中绑定的事件,这类函数需要定义在 methods,比如:bindtap、bindchange 等;组件间事件处理函数,响应组件之间通过 broadcast、emit、自定义函数,即用于被其他函数直接调用的函数,需要定义在和 methods 同级的位置。而在 WePY 2 中需要将组件处理函数和自定义函数都放到 methods 里。下面假设 HOME 页面有一个子组件 child,且子组件里会执行这句 this.$emit('updateList),基于这个背景看下 2 个版本下的写法差异:

1.7.2 写法:

代码语言:javascript复制

2.x 写法:

代码语言:javascript复制

6、组件引入方式变更在 2.x 版本中组件引入不再通过 import 进行导入,而是直接定义在页面的配置 中。1.7.2 写法:

代码语言:javascript复制

2.x 写法:

代码语言:javascript复制

{

usingComponents: {

'child': './components/child.wpy',

}

}

另外,2.x 中已经再不支持在 app.wpy 里定义全局组件,而 1.7.2 中是可以的。

7、生命周期函数调整在 2.x 中生命周期函数基本和原生保持一致,和 1.7.2 相比,只是需要把组件中的 onLoad 改成了 ready 即可,其他无需变动。

级别

1.7.2

2.x

app

onLaunch

onLaunch

app

onShow

onShow

page

onLoad

onLoad

page

onShow

onShow

page

onReady

onReady

component

-

created

component

-

attached

component

onLoad

ready

2.x 生命周期执行顺序:

app onLaunch -> app onShow -> component created -> component attached -> page onLoad -> page onShow -> component ready -> page onReady -> page onUnload -> component detached

❝page onHide 在当前页面通过 wx.navigateTo 打开新页面的时候会执行,而如果是在当前页面点击返回上一个页面或者 wx.redirectTo 并不会执行。

8、不再支持请求拦截器(坑)在 1.7.2 中可以在 wepy.app 的构造函数里通过配置拦截器可以对请求进行拦截,请求被拦截后可以加上更多的请求参数以及请求响应后可以进行统一的错误处理,功能还是挺好用的。但是在 2.x 中这个功能至少从文档上是没看到,虽然源码里提供了一个 use-intercept拦截器的包,但是经过我几番尝试之后还是报错,所以就打算弃用拦截器了,直接在请求里进行参数增加和错误处理。request.js 这里贴一份大概的代码:

代码语言:javascript复制import wepy from "@wepy/core";

import { HOST } from "./constants";

export default function(url, data, handler = toast, header = {}) {

// 头参数添加

header["Content-Type"] = "application/json";

header["cType"] = "WECHAT";

return wepy.wx.request({ // 这里 wepy.wx.request 这种写法,需要在app.wpy里配置promisify,

method: "POST",

data: data || {},

header,

url: `${HOST}${url}`,

}).then(data => {

// 请求成功处理代码放这儿

return Promise.reject(data)

}).catch(err => {

// 错误处理代码放这儿

return Promise.reject(err);

});

}

其中 wepy.wx.request 这种写法需要在 app.wpy 里配置 promisify,可以参考这里 use-promisify

9、标签属性的值必须被双引号包裹在 1.7.2 中对单引号和双引号没有强制要求,但是在 2.x 中必须是双引号,不然编译会报错。1.7.2 写法:

代码语言:javascript复制

2.x 写法:

代码语言:javascript复制

10、调用原生事件需要传入参数$wx小程序原生事件会传递一个 event 参数。而 WePY 的事件分发器在处理事件时会有一个 event 参数。event 参数是对 event 进行了一层包装,目地是为了无侵入地对齐 Web Event 标准属性。而其中 event.wx === event。因此,WePY 中响应事件获得的事件参数均是指 event。如果想拿到原生事件参数,请使用 event.

代码语言:javascript复制

2.x 写法,只需要将 bindinput="setInput" 改成 @input="setInput($wx)" 即可。

11、模板语法修改2.x 的模板语法继承了 WXML 的基本模板语法,并支持大部分 Vue 模板语法。对于标签:2.x 支持绝大部分的 HTML 标签,经过编译后会转成标准的 WXML 模板语法。但是对于 1.7.2 中的有一个标签 不再支持,需要将其替换成 并且用 v-for 进行循环渲染。

下面是一些常用的模板语法对于 2 个版本之间写法的对比:1.7.2 写法

代码语言:javascript复制

2.x 写法:

代码语言:javascript复制

对于 v-for 循环列表的时候这里有一个(坑)不得不提一下,github issues直接看下面的代码:

代码语言:javascript复制

{{ index }}

对于上面的代码,{{ index }} 可以正常显示索引值 index,但是 tapItem 传的参数却是 undefined,这所以我们需要显示的声明索引 v-for="(item, index) in array" 即可。

12、表单双向绑定调整2.x 中直接用 v-model 进行表单绑定,而不需要再定义一个函数对其进行赋值操作。1.7.2 写法:

代码语言:javascript复制

child.wpy:

代码语言:javascript复制

16、组件prop不再支持双向绑定在 1.7.2 中可以通过可以通过设置 prop 给子组件传参,如果设置的时候加上 .sync 那么当父组件参数更新的时候,传递给子组件的也会自动更新,而如果在子组件的 prop 里加上 twoWay: true 则子组件数据可以绑定到父组件。从而实现组件数据的双向绑定。功能还是挺好用的,但遗憾的是在 2.x 中已经不再支持通过 twoWay: true 的方式从子组件绑定数据到父组件,父到子是可以的,但是不再需要设置 sync。那子组件需要更新父组件的数据,只能通过自定义事件,然后在子组件通过 $emit 进行更新数据了。1.7.2 写法:父页面:

代码语言:javascript复制