小程序框架WePY 从入门到放弃踩坑合集

一点点介绍WePY

因为小程序的语法设计略迷,
所以x1 模块化起来并不不便,
所以x2 各厂就出了不少的框架用以不便小程序的开发,
腾讯看到他人家都出了框架了那看来我的小程序可能真的不太不便开发咯,那我也出一个吧
所以x3 WePY 就这么横空出世了。

那小鹅鹅 你早干嘛去了啊,为什么不把小程序设计的好用一点点!程序员好好玩是吧!

同样是仿原生利用你就不能学学人家Electron 把界面交给网页原生HTML 去解决么,搞一堆贼没用组件各种奇奇怪怪的问题。。

程序员何苦尴尬程序猿啊

不好意思冲动了

下面 都是我吹的其实WePY 是最早的小程序框架之一

WePY 是一个开发格调相似Vue.js, 反对相似Props, Mixin, Computed, Slot 等个性的格调开发,
反对组件化/模块化,NPM 依赖,Promise/Async, ESnext, Less/Sass/Styus, Babel/Typescript 的一个小程序开发框架。

语法上相似Vue.js 多一点,作为一个React 党我并没有很喜爱,但可能Vue 党也不肯定就喜爱。
毕竟它只是像,并没有很一样,开发起来跟做连连看似的跟Vue.js 各种行为不统一。。

闲话就说到这了,开始说闲事。

那些要留神的点

此节内容参考 <u>小色小魔</u> 于 <u>2018-03-20</u> 公布在 Segmentfault 的文章 Wepy-小程序踩坑记

ALL CREDIT GOES TO HIM THANKS ALOT

首先是文档类:

WePY首页

WePY官网文档

小程序官网文档

WePY Github Issues

而后是一些要点:

1. Data 及数据绑定

1.1 对于可能用到的所有数据要事后给值,即要先在data 中初始化;否则之后更新数据时将不会触发脏数据查看流程,也就不会触发页面重渲染。

1.2 更新数据时能够间接用 this.foo = bar, 不必微信原生的 this.setData 办法。

class Fn extends wepy.page {  data = {    foo: 1,    // bar: 2, 此处不申明 bar  }  someFunction() {    // 页面更新    this.foo = 10;    // 这不失效    this.bar = 20;  }}

1.3 数据在模板中进行绑定时能够用 :foo=bar 的模式进行绑定。留神非字符类型的(比如说布尔值)及变量要加双大括号,否则当成字符串解决。其余的非绑定的,要间接显示的内容可间接用双大括号包住即可。双大括号内可进行简略的运算,但不反对JS 模板字符串或其余办法运算。

// Template<component :name="{{myName}}">  // 绑定数据  // 失常:渲染内容  {{Greeting}}  // 失常:渲染内容  {{Greeting + 'World!'}}  // 报错:不反对 JS模板字符串  {{`${Greeting} World!`}}  // 报错:不反对 JS 办法调用  {{String(Greeting).trim()}}</component>
// Scriptclass Foo extends wepy.page {  data = {    myName: 'WePY',    greetings: 'Hello',  }}

1.4 操作方法用 @tap=function 的模式进行绑定。基本上所有微信原生的办法 bindFn=fn 都能够间接写成 @Fn=fn.

// Template// 原生的 bindtap=fn<view @tap="fn"></view>// Scriptclass Foo extends wepy.page {  methods = {    fn: () => {},  }}

2. Methods & Computed

2.1 class 中的methods 中只蕴含模板用的事件办法,其余的自定义办法应该与methods 自身平级,处于顶层。

// Template<view @tap="fn"></view>// Scriptclass Foo extends wepy.page {  methods = {    fn: () => {      this.doSomeThing();    },  }  doSomeThing: () => {}}

2.2 模板事件提供了“办法后缀”作为语法糖以代替原生写法,有.default, .stop.user 后缀,比拟罕用的是 .stop,相当于原生的 catch.

// Template// .default 可不写<view @tap="fn"></view>// .stop 相当于 catch, 点击事件到此结束,不会向下层组件冒泡<view @tap.stop="fn"></view>

2.3 此外还提供了computed 及watcher 根本与Vue.js 相似,就不介绍了~

3. Mixin & Components

3.1 Mixin 有后端编程的小伙伴应该会比拟相熟一点,能够将通用办法提供给不同中央应用。在这里它能间接读取共有的数据(比如说从Redux 里读取的内容等)但应用时要留神当Mixin 中用到了来自Redux 中的数据时,数据自身的connect 要在其具体援用到的页面外面定义,貌似Mixin 自身并不能将Redux 中的数据connect 进来。

3.2 Mixin 中的methods 中不能间接应用 this.foo = bar 去设置页面中的值,因为上下文不统一了不会失效。

3.3 Mixin 中的执行程序与Vue.js 中的相同。Vue.js 中是先执行Mixin 中的函数, 再执行组件自身的函数。这里执行程序相同。

补充:Vue.js 中对于钩子函数,会先执行Mixin 中的,再执行组件本身的;
Vue.js 中methods 如果和Mixin 同名,那么只会执行本身的办法。

3.4 组件在 import 时不要带后缀名:

// Good ;-)import Xxx from '../xx';// Damned :-(import Xxx from '../xx.wpy';

3.5 最让人烦恼的货色来了—— WePY 中的组件。它是组件全是“单例”的,这意味着当你在同一个页面中去使同一个组件屡次时,显示进去的那“多”个组件它绑定的内容都会被更新成最初一个,你不能给他们绑定到不同的内容上,你用组件时只能享受到款式上的劣势,齐全不知所想何物♂️

// Template<view wx:for="{{list}}">  <comp :number.sync="{{item}}"></comp>  // 你也不能这样做,因为它不承受变量</view>
// Scriptimport Comp from '../Comp';class Foo extends wepy.page {  data = {    list: [1, 2, 3, 4],  }  components = {    comp: Comp,  }}

好受 = =||

3.6 对于原生及非原生组件,它的模板逻辑也总是“看上去不那么固定”的,比如说:

// 正确 - 省略为 true<scroll-view scroll-y></scroll-view>// 谬误 - 布尔值不能带括号<scroll-view scroll-y="{{true}}"></scroll-view>// 正确 - 预计这里实际上可能 "true" 是被忽略了的<scroll-view scroll-y="true"></scroll-view>// 正确 - 但此时这个办法承受到的第一个参数为以后Class的实例,坑爹啊<view @tap="toggleSomeThing"></view>// 谬误 - 布尔值要带括号<view @tap="toggleSomeThing(true)"></view>// 正确<view @tap="toggleSomeThing({{true}})"></view>

3.7 还有一个偶发的状况是 wx:if 时,class 等其余属性偶发会被“疏忽掉”。

// 失常<view wx:if="{{something === 'foo'}}" class="foo">// 偶然会不失常,class 被疏忽掉了<view class="bar" wx:if="{{something === 'bar'}}">

所以总体上比拟倡议将条件先写进去,前面再加其余属性,或者间接用 block 标签去作为条件判断。

3.8 Page 继承自Component, 但Page 扩大了页面所特有的 config 配置以及特有的页面生命周期函数等;所以Component 和Page 之间根本一样,但Component 没有 onLoad 等生命周期。

4. This 及内定办法

4.1 更新数据时能够间接用 this.foo = bar, 不必微信原生的 this.setData 办法。

4.2 所有可能产生异步的中央批改数据后要手动促发脏数据查看流程,否则不会促发页面重渲染。
常见的中央有申请后更新,setTimeOut, getStorageSync 等等~

5. canvas & base64

Canvas 的相干操作和微信原生一样,参照 这里 即可:

ArrayBuffer 和 Base64 互转:

v1.1.0 (2017.03.31) 版本就有这两个 API 了,能够间接用:

wx.arrayBufferToBase64wx.base64ToArrayBuffer

6. 其余,一点开发倡议

6.1 小程序外部定义的实例API 都以 $ 结尾,所以咱们命名时也不应该以 $ 结尾,以便辨别。

6.2 同样的,如果用了Redux, 那么connect 进来的办法也会是通过 this.methods.fn() 的模式拜访,倡议也得辨别开比拟好,比如说页面及组件中的办法加bind 前缀。像这样:

// Redux Actionthis.methods.function();// Page Methodsthis.methods.bindFunction();

开发中写的一些有用的 Snippets

跨页面通信

这是小程序原生的代码,用于更新前一个页面中的Data 值

利用场景比如说有一个表单类的页面,其中的某个字段能够点到另外一个全屏的界面去编辑

改完了保留后会回到以后的页面中持续编辑其余的字段

// 获取以后页面栈的实例 <Array>let crtPage = getCurrentPages();// 失去上一个页面实例 <Object>let prevPage = crtPage[crtPage.length - 2];// 设置前一个页面中的数据prevPage.setData({note: this.value});/* * 这个做法能够失常设置前一个页面中的Data 的值, * 但如果那个页面中的那个Data 是用作Props 传给组件的话 * 组件中的值并不会跟着更新成新的值 */

正则解析城市字符串,用于微信原生省市抉择组件

因为有个我的项目的后端是保留的相似 "上海市上海市徐汇区" 的值

但微信的组件应用的value 却是相似 ['上海市', '上海市', '徐汇区'] 这样的数组

为了保障批改时能正确显示上次设置的内容所以就有了这么一个货色

/*  * Parse String to Wechat City Array  *  * @param:  *  city <String>: '上海市上海市徐汇区'  *  * @return:  *  <Array> ['上海市', '上海市', '徐汇区']  */const parseRegion = (city) => {  let str = city;  let region = [];  let reg = [    /\S[^省|市|区]+[省|市|区]/,    /\S[^市|区]+[市|区]/,    /\S[^市|区|县]+[市|区|县]/,  ];  for (let r of reg) {    const rs = r.exec(str);    if (rs !== null) {      region.push(rs[0]);      str = str.replace(rs[0], '');    }  }  return region;};

URL 参数序列化

用处:当小程序须要栏截操作时,长期保留传入的参数

// onLoad(op) { this.op = op; }// reLaunch 时 url = some-url + '?' + this.serializer(this.op)serializer = (data = {}) => (  Object.entries(data).map(    ([key, value]) => (      value !== undefined        ? `${key}=${encodeURIComponent(value)}`        : ''    )  )  .filter((item) => (item))  .join('&'));