微信小程序框架WePy学习笔记

上次体验了一下小程序开发,用的是小程序原生语法来开发。虽然体验了一把原汁原味的小程序开发,但是发现现在版本的小程序原生语法还是比较繁杂的,不够灵活。比如单单页面就由 4 个文件组成,还有组件上不支持脚本等等。在现在 MVVM 框架盛行的年代

目录
  1. 前言
  2. 选择框架
  3. 主要特点
  4. 使用流程
  5. 项目结构解析
  6. wpy 文件解析
  7. 异同点
  8. 注意事项
  9. 总结

前言#

上次体验了一下小程序开发,用的是小程序原生语法来开发。虽然体验了一把原汁原味的小程序开发,但是发现现在版本的小程序原生语法还是比较繁杂的,不够灵活。比如单单页面就由 4 个文件组成,还有组件上不支持脚本等等。在现在 MVVM 框架盛行的年代,可以使用尝试使用框架来开发小程序。

本篇文章基于 WePy v1.7.2-alpha1

补充说明:原生小程序开发并不会比使用框架开发效率低,而且原生开发没有那么多的 BUG,这个主要看开发者的熟练水平!

选择框架#

网上查了下,微信小程序现在已经有不少开发框架,比如 WePy,Tina,MpVue 等等。选择哪个比较好呢?

最后我选择的是 WePy! 为什么呢?

  1. WePy 是微信官方腾讯公司的前端团队开发的一款小程序开发框架,应该会和小程序开发很搭配(后来才发现主力开发也就是一个人,一开始不是他并不是 Tencent 团队的,后面被招进来了)。
  2. WePy 在小程序公测的时候就开源了,现在已经到 1.7.1 版本了,听说马上出 2.0 版本了,算是比较成熟稳定的框架了。(其实比起原生, BUG 还是挺多的)
  3. WePy 借鉴了三大前端 MVVM 框架 Vue 的语法分格和功能特性,正好我也比较熟悉 Vue。(后来发现还不如直接使用 Vue 语法)

所以,没错!就是 WePy 了。

主要特点#

看了 WePy 的文档,发现 WePy 还是很强大的,和 Vue 的语法风格和功能特性,非常适合 Vue 开发者。 其中,有几个特性个人非常喜欢。

  1. 和 Vue 一样的语法风格和功能特性,更贴近 MVVM 架构模式。
  2. 支持 Sass/Scss,Less,Stylus 等 CSS 预处理器。(个人比较喜欢简洁风格的 Stylus 预处理器)。
  3. 单文件模式,和 Vue 的.vue文件一样,把结构、样式、脚本都放在一个.wpy 文件里,使得目录结构非常清晰、简便。
  4. 支持加载外部的 NPM 包,也就是说可以使用第三方库了。
  5. 支持 ES6/7 的新特性,比如PromiseAsync/Await,处理异步很方便。
  6. 支持页面和组件间通信,不但数据可以双向传值,还可以进行事件派发。

其实,WePy 还有很多好的特性,比如支持 ESLink 规则等等, 详见WePy 官方文档。总之,WePy 对 Vue 开发者真的是非常友好。

使用流程#

  • 安装 WePy 命令行工具
npm install wepy-cli -g
  • 创建项目
wepy init standard wepy-demo
  • 安装依赖
cd wepy-demo
npm install
  • 开启实时编译
wepy build --watch
  • 如果使用 Stylus 预处理器,需要配置 Stylus 编译(默认已经配置好了 Less 和 Sass/Scss 预处理器)
npm install wepy-compiler-stylus --save-dev
// wepy.config.js
module.exports = {
  compilers: {
    stylus: {
      compress: true,
    },
  },
};

项目结构解析#

主要分析其中四个部分

  1. dist:小程序运行目录,由 WePy 框架编译源文件生成,不要直接修改这个目录的代码。

  2. src:代码源文件,自动生成分为三个部分:pages 目录、components 目录、app.js

    • pages 目录:小程序的页面目录,存放小程序的页面,继承wepy.page类。
    • components 目录: 小程序的组件目录,存放小程序的组件,继承wepy.component类。
    • app.js:小程序的配置文件,比如全局变量,全局样式,声明钩子等,继承的是wepy.app类。
    • 其他的自定义目录。比如存在工具类方法的 utils,混合 mixins,存放图片文件的目录 images 等。

3.package.json:项目的 package 管理文件。 4.wepy.config.js:框架的配置文件,比如配置 Stylus 编译就在这里配置。

wpy 文件解析#

.wpy文件结构和.vue文件一样,分为三个部分,主要由三个标签组成,分别是templatestylescript

<style lang="stylus" src="page1.styl">
  /* 编写样式, 对应原生的.wxss, 支持lang和src属性, lang默认为css,支持less,sass,stylus, postcss */
</style>
<template>
  <!--编写结构, 对应原生的.wxml文件, 支持lang和src属性, lang默认为wxml,支持xml,pug -->
</template>
<script>
  // 编写脚本, 对应原生的.js文件和json文件, 支持lang和src属性, lang默认为babel,支持TypeScript
</script>

其中,在script可以配置对应原生小程序的 json 文件,在script标签里面继承的类的config属性中配置,其他的代码为 js 文件的逻辑部分。

export default class Index extends wepy.page {
  config = {
    navigationBarTitleText: "小小休闲",
    navigationBarBackgroundColor: "#b3d4db",
  };
  methods = {
    onTap() {
      wepy.switchTab({
        url: "../../pages/posts/posts",
      });
    },
  };
}

异同点#

在这里,只列举自己使用时遇到的部分异同点,分别和小程序原生语法和 Vue 语法进行比较,这部分应该不全,详情请查看官方文档

  1. 事件绑定

    1. 原生:bindtap。WePy:@tap。 Vue:@click
    2. 原生:catchtap。 WePy:@tap.stop。 Vue:@click.stop
  2. 循环渲染

    • 原生
    <block wx:for="{{list}}" wx:for-item="itemName" wx:key="keyName"></block>
    • WePy
    <repeat for="/{{list}}/" item="itemName" key="keyName"></repeat>
    • Vue
    <div v-for="itemName in list" :key="keyName"></div>
  3. 页面和组件传值:

    • 原生:data属性。
    • WePy:props,动态传值需要加上.sync后缀,支持双向传值, 组件可以改变页面的值。
    • Vue:Props,2.3 以后重新支持双向传值。
  4. 组件向页面派发事件:

    • 原生:不支持。
    • WePy:this.$emit(),传递的事件需要加上.user后缀。
    • Vue:this.$emit(),不需要加后缀。
  5. 调用全局 api:

    • 原生:wx:xxx
    • WePy:wepy:xxx & this.$xxxthis.xxx
    • Vue:Vue.xxx & this.$xxx
  6. 指令

    • 原生:wx:xxx
    • WePy:wx:xxx部分省略wx, 比如在<repeat>循环标签时使用for不是wx:for
    • Vue:v-xxx部分省略v-, 比如ref等。
  7. 方法

    • 原生:放在page里面。
    • WePy:放在继承的Page类里面,特定的方法必须放在methods属性里面,即methods={method}。比如页面接收的派发事件,组件的事件绑定等。
    • Vue:方法全部放在methods里面。
  8. 存取 data 属性

    • 原生
    // 保存 data 数据
    this.setData({
      title: "home",
    });
     
    // 获取 data 数据
    const title = this.data.title;
    • WePy
    // 保存 data 数据
    this.title = "home";
     
    // 获取 data 数据
    const title = this.title;
    • Vue
    // 保存 data 数据
    this.title = "home";
     
    // 获取 data 数据
    const title = this.title;
  9. 存取全局变量

    • 原生
    // 保存全局变量
    const app = getApp();
    app.globalData.isPlaying = true;
     
    // 获取全局变量
    const isPlaying = app.globalData.isPlaying;
    • WePy
    // 保存全局变量
    this.$parent.globalData.isPlaying = true;
     
    // 获取全局变量
    const isPlaying = this.$parent.globalData.isPlaying;
    • Vue:自定义全局变量或者使用 Vuex 状态管理器。

注意事项#

  1. 使用 WePy 框架开发小程序时,需要关闭开发者工具中的“ES6 转 ES5”、“上传代码是样式自动补全”、“上传代码时自动压缩”这几个选项。或者在project.config.json设置成false也可以,不然会莫名其妙的报错。

  2. 开发中遇到的一个 BUG:就是用<repeat>循环传入子组件的值,无法再传入给孙组件。从 Issue 中查了下,很多人都遇到了这个问题,维护人员说 2.0 版本才会解决这个 Bug,现在版本解决的办法是下载最新的 v1.7.2-alpha1 版本,然后导入组件时再变量上加@,再用原生的<block>wx:for来传值,不过试了下,貌似没有效果。

总结#

代码可参考:

  • Github 仓库的原生小程序代码:mp-demo
  • WePy 框架编写的小程序代码:wepy-demo

第一次使用 WePy 框架开发小程序难免会出现很多问题,文章中不足之处还请见谅。