详细了解 Todo App Demo

概述

这里会通过Todo App Demo更加细致的了解小程序的实现原理。

全局配置

app.js 是小程序公共的逻辑脚本文件,在这个文件中可以监听小程序的生命周期,声明全局变量,调用框架提供的丰富 API,如以下所示的存储以及获取用户信息 API,更多 API 参见 API 文档.

  1. // 调用存储 api 获取已经存在的数据
  2. const todos = my.getStorageSync({key:'todos'}).data || [
  3. { text: 'Learning Javascript', completed: true },
  4. { text: 'Learning ES2016', completed: true },
  5. { text: 'Learning 支付宝小程序', completed: false },
  6. ];
  7. App({
  8. // 声明全局数据
  9. todos,
  10. userInfo: null,
  11. // 声明全局方法
  12. setTodos(todos) {
  13. this.todos = todos;
  14. // 调用存储 api 存储数据
  15. my.setStorageSync({key:'todos', data:todos});
  16. },
  17. getUserInfo() {
  18. return new Promise((resolve, reject) => {
  19. if (this.userInfo) resolve(this.userInfo);
  20. // 调用用户授权 api 获取用户信息
  21. my.getAuthCode({
  22. success: (authcode) => {
  23. console.info(authcode);
  24. my.getAuthUserInfo({
  25. scopes: ['auth_user'],
  26. success: (res) => {
  27. this.userInfo = res;
  28. resolve(this.userInfo);
  29. },
  30. fail: () => {
  31. reject({});
  32. },
  33. });
  34. },
  35. fail: () => {
  36. reject({});
  37. },
  38. });
  39. });
  40. },
  41. });

app.json 是属于小程序的全局配置,在这个 json 文件中可以记配置小程序的页面集合,通用的的状态栏、导航条、标题、窗口背景色等。更多配置参见 文档配置

  1. {
  2. "pages": [
  3. "pages/todos/todos",
  4. "pages/add-todo/add-todo"
  5. ],
  6. "window": {
  7. "defaultTitle": "Todo App"
  8. }
  9. }

app.acss 是小程序的公共样式,可以在页面的 axml 中直接使用 app.acss 定义的选择器,影响所有页面的样式。

  1. page {
  2. flex: 1;
  3. display: flex;
  4. }

上例中的 page 为框架支持的特殊选择器,会匹配框架提供的页面根节点容器。

小程序页面

在这个示例中,我们有两个页面,Todo List 页面和 Add Todo 页面,他们都在 pages 目录下。小程序的所有页面路径必须写在 app.json 中,路径从项目根目录开始且不能包括后缀名,pages 的第一个页面就是小程序的首页。

每一个 小程序页面 是由同路径下的四种类型文件组成,即.js 后缀的逻辑脚本文件,.json 后缀的配置文件, .acss 后缀的样式文件, .axml 后缀的模版文件。

Todo List 页面

todos.axml 为页面结构模版文件:

  1. <view class="page-todos">
  2. <view class="user">
  3. <image class="avatar" src="{{user.avatar}}" background-size="cover"></image>
  4. <view class="nickname">{{user.nickName}}'s Todo List</view>
  5. </view>
  6. <view class="todo-items">
  7. <checkbox-group class="todo-items-group" onChange="onTodoChanged">
  8. <label class="todo-item" a:for="{{todos}}">
  9. <checkbox value="{{item.text}}" checked="{{item.completed}}" />
  10. <text class="{{item.completed ? 'checked' : ''}}">{{item.text}}</text>
  11. </label>
  12. </checkbox-group>
  13. <view class="todo-item">
  14. <button onTap="addTodo">Add Todo</button>
  15. </view>
  16. </view>
  17. </view>

使用 <view/>,<image/>,<text/>,<button/>,<label/>,<checkbox/>,来搭建页面结构以及 a:for 绑定 todos 数据,并将 todos 数据循环展开节点。绑定数据可以查阅视图层文档,绑定事件可以查阅事件处理文档.

todos.js 是页面的逻辑脚本文件:

  1. // 获取全局 app 实例
  2. const app = getApp();
  3. Page({
  4. data: {},
  5. onLoad() {
  6. // 获取用户信息并渲染
  7. app.getUserInfo().then(
  8. user => this.setData({
  9. user,
  10. }),
  11. );
  12. },
  13. // 监听生命周期
  14. onShow() {
  15. // 渲染全局数据到当前页面
  16. this.setData({ todos: app.todos });
  17. },
  18. // 事件处理函数
  19. onTodoChanged(e) {
  20. // 修改全局数据并重新渲染
  21. const checkedTodos = e.detail.value;
  22. app.setTodos(app.todos.map(todo => ({
  23. ...todo,
  24. completed: checkedTodos.indexOf(todo.text) > -1,
  25. })));
  26. this.setData({ todos: app.todos });
  27. },
  28. addTodo() {
  29. // 调用页面跳转 API 实现页面跳转
  30. my.navigateTo({ url: '../add-todo/add-todo' });
  31. },
  32. });

在这个文件中可以:

  • 监听并处理页面的生命周期函数 (onHide, onShow, onLoad, onUnload, onReady)。
  • 获取小程序实例以及其他页面实例 (getApp, getCurrentPages)。
  • 声明并处理数据 (data)。
  • 响应页面交互事件,调用 API 等。
  • 这里需要注意的是app.todos是来自app.js中全局的变量定义
    todos.acss 是页面的样式文件:
  1. .page-todos {
  2. flex: 1;
  3. display: flex;
  4. flex-direction: column;
  5. }
  6. .user {
  7. display: flex;
  8. padding: 30px 30px 0 30px;
  9. }
  10. .avatar {
  11. width: 128rpx;
  12. height: 128rpx;
  13. margin-right: 40rpx;
  14. border-radius: 50%;
  15. }
  16. .nickname {
  17. display: flex;
  18. flex-direction: column;
  19. justify-content: center;
  20. font-size: 40rpx;
  21. }
  22. .todo-items {
  23. padding: 80rpx;
  24. }
  25. .todo-items-group {
  26. display: flex;
  27. flex-direction: column;
  28. }
  29. .checked {
  30. color: #d9d9d9;
  31. text-decoration: line-through;
  32. }
  33. .todo-item {
  34. margin-bottom: 15px;
  35. }

acss 文件不是必须的。语法可以查阅 样式 文档。当有页面样式表时,页面的样式表中的样式规则会层叠覆盖 app.acss 中的样式规则。如果不指定页面的样式表,也可以在页面的结构文件中直接使用 app.acss 中指定的样式规则。

todos.json 是页面的配置文件,这里是一个空文件。

配置文件不是必须的。当有页面的配置文件时,配置项在该页面会覆盖 app.json 的 window 中相同的配置项。如果没有指定的页面配置文件,则在该页面直接使用 app.json 中的默认配置。因此 index 页面的标题为 app.json 中指定的 Todo App

Add Todo 页面

add-todo.axml 为页面结构模版文件:

  1. <view class="page-add-todo">
  2. <view class="add-todo">
  3. <input
  4. class="add-todo-input"
  5. placeholder="What needs to be done?"
  6. onBlur="onBlur"
  7. value="{{inputValue}}"
  8. />
  9. </view>
  10. <view class="todo-footer">
  11. <add-button text="Add Todo" onClickMe="add" ></add-button>
  12. </view>
  13. </view>

在这个页面中有两个核心知识点:

  • 使用<input/> 组件来接受用户输入。
  • <add-button>是一个自定义组件,我们可以将一些功能完整的代码封装为自定义组件,便于其他地方复用。
    add-todo.js 页面逻辑代码:
  1. const app = getApp();
  2. Page({
  3. data: {
  4. inputValue: '',
  5. },
  6. onBlur(e) {
  7. this.setData({
  8. inputValue: e.detail.value,
  9. });
  10. },
  11. add() {
  12. app.todos = app.todos.concat([
  13. {
  14. text: this.data.inputValue,
  15. compeleted: false,
  16. },
  17. ]);
  18. my.navigateBack();
  19. },
  20. });

add-todo.acss 同 todo list 页面用法基本一致。

add-todo.json 由于引用了自定义组件,所以需要在json中进行声明,否则会报错:

  1. "usingComponents": {
  2. "add-button": "/components/add-button/add-button"
  3. }

接下来我们看看如何将小程序发布上线。

原文: https://docs.alipay.com/mini/developer/todo-demo-detail