小程序的核心是一个响应式的数据绑定系统,逻辑上分为视图层和逻辑层。这两层始终保持同步,只要在逻辑层修改数据,视图层就会相应的更新。

小程序遵守Convention Over Configuration的原则,没有留给开发者自由选择的余地。

支付宝小程序和微信小程序的开发框架几乎一模一样,以下代码以微信小程序为例。

包管理

微信小程序使用bower做模块管理,支付宝小程序使用npm

bower.json

{
  "dependencies": {
    "zan": "git@gitlab.qima-inc.com:weapp/zui.git#v2.0.1"
  }
}

运行代码之前需要先把通过包管理工具把远程依赖拉取到本地。

bower init

APP

调用构造函数——App可以生成一个APP实例,它除了管理所有的页面和全局数据,还提供生命周期回调函数。

APP入口一般包含三个文件:

  1. app.js
  2. app.json
  3. app.wxss(支付宝是app.acss)

三个文件的作用域是全局,可以在Page中直接访问。

一个APP有且只能有一个app.js文件。

页面

调用构造函数——Page可以生成一个页面实例,页面通过wxml(支付宝是axml)展示数据或提供交互, 数据保存在Pagedata属性中。

const app = getApp(); // 获取app实例
Page({
  data: {
    userInfo: {},
    phoneNumber: '',
  },

  // other properties
});

所有的页面位于pages目录,一个页面对应一个子目录。

页面 address 的目录结构如下所示:

├── pages
│   ├── address
│   │   ├── addressList
│   │   │   ├── index.js
│   │   │   ├── index.json
│   │   │   ├── index.wxml
│   │   │   └── index.wxss
│   │   └── editAddress
│   │       ├── index.js
│   │       ├── index.json
│   │       ├── index.wxml
│   │       └── index.wxss
  • js封装了业务逻辑
  • json配置了页面属性
  • wxml展示页面元素

数据绑定

数据绑定使用Mustache语法(双大括号)将Pagedata变量包起来绑定(双向)到wxml元素。

<view>  </view>

通过Page#setData可以自动触发界面数据更新:

onPhoneNumberCleared(e) {
  this.setData({
    phoneNumber: '',
  });
}

直接修改this.data无效,无法改变页面的状态,还会造成数据不一致

组件

组件是一个可复用的单元,它可以对外提供js、wxml、wxss

wxml格式如下:

<template name="zan_account">
  <view class='container__input--disabled'></view>
</template>

在Page中使用组件时,需要分别引入对应的文件。

js@page

const ZanAccount = require('../../../components/zan_account/index')

require要使用相对路径

wxml@page

<import src="/components/zan_account/index.wxml" />

<!-- other elements -->

<template is="zan_account" data="" />

wxss@page

@import "/components/zan_account/index.wxss";

最佳实践

wxsswxml通过import最终会和page页面合为一个整体。

template会被导入到pagewxml中,所以它用到的变量只会与pagedata进行绑定(例如上例中的phoneNumber)。

为了把组件封装得比较完整,我们需要在组件的js文件中定义好data以及event,然后导入到page的js文件中。

先封装一个合并对象数据的工具函数——extend

extend.js

var extend = function(obj) {
  ([].slice.call(arguments, 1) || []).forEach(function(source) {
    if (source) {
      for(var prop in source) {
        obj[prop] = source[prop];
      }
    }
  });
  return obj;
};

module.exports = extend;

通过extend函数就可以把多个对象合并成一个Page对象:

var ZanAccount = require('../../../components/zan_account/index')

Page(extend({}, ZanAccount, {
  data: {
  }
  
  // methods
});

那么组件应该如何定义呢?

因为组件的数据和方法会被合并到Page对象中,因此我们可以把组件分为三个部分:

  • data - 数据
  • handle - 事件回调
  • method - 其他方法
let data = {
  zanaccount: {
    phoneNumber: '',
    name: '',
  },
};

let handle = {
  onRegister() {
  },
}

let method = {
  checkPassword(password) {
  },
}

利用Object.assign函数把属性合并之后导出:

module.exports = Object.assign({}, handle, method);

CSS

CSS命名规范使用Block Element Modifier。

BEM — Block Element Modifier is a methodology that helps you to create reusable components and code sharing in front-end development

对比Android

  • App => Application
  • Page => Activity
  • getApp => getApplication in activity
  • 数据绑定 => Data Binding

参考资料

更新时间:

留下评论