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

小程序框架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>
// Script
class Foo extends wepy.page {
  data = {
    myName: 'WePY',
    greetings: 'Hello',
  }
}

1.4 操作方法用 @tap=function 的形式进行绑定。基本上所有微信原生的方法 bindFn=fn 都可以直接写成 @Fn=fn.

// Template
// 原生的 bindtap=fn
<view @tap="fn"></view>

// Script
class Foo extends wepy.page {
  methods = {
    fn: () => {},
  }
}

2. Methods & Computed

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

// Template
<view @tap="fn"></view>

// Script
class 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>
// Script
import 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.arrayBufferToBase64
wx.base64ToArrayBuffer

6. 其他,一点开发建议

6.1 小程序内部定义的实例API 都以 $ 开头,所以我们命名时也不应该以 $ 开头,以便区分。

6.2 同样的,如果用了Redux, 那么connect 进来的方法也会是通过 this.methods.fn() 的形式访问,建议也得区分开比较好,比如说页面及组件中的方法加bind 前缀。像这样:

// Redux Action
this.methods.function();

// Page Methods
this.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('&')
);
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容