# 小程序页面

小程序页面函数为 Page(Object params)，本文介绍该函数的参数说明，以及如何使用该函数注册页面。

## Page(Object params) 的参数说明

Page(Object params) 是在进入小程序某个页面时，会执行的页面入口函数。其中的 `params` 是一个 Object 类型的参数，用于定义页面初始数据、生命周期钩子函数、事件处理函数等。

属性 | 类型 | 描述
---|---|---
data | Object | 页面的初始数据。
onLoad | function | 生命周期函数，监听页面加载。
onReady | function | 生命周期函数，监听页面初次渲染完成。
onShow | function | 生命周期函数，监听页面显示。
onHide | function | 生命周期函数，监听页面隐藏。
onUnload | function | 生命周期函数，监听页面卸载。
onPullDownRefresh | function | 页面相关事件处理函数，监听用户下拉动作。
onReachBottom | function | 页面上拉触底事件的处理函数。
onPageScroll | function | 页面滚动触发事件的处理函数。
onTabItemTap | function | 当前是 tab 页时，点击 tab 时触发。
onTabbarDoubleTap | function | 当前是 tab 页时，双击 tab 时触发。
onShareAppMessage | function | 点击页面内转发按钮或者右上角菜单里的分享。
onSelectionChange | function | 当页面组件触发选中事件时，例如 text。该参数需要飞书版本 ≥ v4.2。
其他 | any | 你可以添加任意的函数或数据到 object 参数中，在页面的函数中用 this 可以访问。

## 注册页面

对于小程序中的每个页面，都需要在页面对应的 js 文件中进行注册，在注册时指定页面的初始数据、生命周期回调、事件处理函数等。本章节主要介绍如何使用 Page 函数注册页面，以及注册过程中在 Page 函数内支持的操作。

### 使用 Page 构造器注册页面

使用 Page() 进行构造，示例代码如下所示。

```javascript
// index.js
Page({
  data: {
    text: "This is page data."
  },
  onLoad: function(options) {
    // 页面创建时执行
  },
  onReady: function() {
    // 页面初次渲染完毕时执行
  },
  onShow: function() {
    // 页面出现在前台时执行
  },
  onHide: function() {
    // 页面从前台变为后台时执行
  },
  onUnload: function() {
    // 页面卸载时执行
  },
  onPullDownRefresh: function() {
    // 触发下拉刷新时执行
  },
  onReachBottom: function() {
    // 页面触底时执行
  },
  onShareAppMessage: function () {
    // 页面被用户分享时执行
   return {
      title: 'share title',
      imageUrl: '',
      path: ''
    }
  },
  onPageScroll: function() {
    // 页面滚动时执行
  },
  onTabItemTap(item) {
    // 当前是 tab 页时，点击 tab 时执行
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  onTabbarDoubleTap(item) {
    // 当前是 tab 页时，双击 tab 时执行
    console.log(item.index)
    console.log(item.pagePath)
    console.log(item.text)
  },
  // 事件响应函数
  viewTap: function() {
    this.setData({
      text: 'Set some data for updating view.'
    }, function() {
      // setData 的回调
    })
  },
  customData: {
    foo: 'bar'
  }
})
```

### data

`data` 数据是页面第一次渲染使用的初始数据。页面加载时，`data` 会以 JSON 的形式由逻辑层传至渲染层，因此 `data` 数据必须是可以转成 JSON 格式的数据，例如：字符串、数字、布尔值、对象、数组。后续渲染层可以通过 TTML 对数据进行绑定。示例代码如下：

- index.ttml 中的配置

```html
<view>{{text}}</view>
<view>{{array[0].msg}}</view>
```

- index.js 中的配置

```javascript
// index.js
Page({ 
  data: { 
    text: 'init data', 
    array: [{msg: '1'}, {msg: '2'}] 
  } 
})
```

### 处理页面事件

Page 中支持定义一些特殊的函数：事件处理函数。在渲染层的组件中可以加入事件绑定，当事件被触发时，系统会执行 Page 中定义的事件处理函数。示例代码如下所示。

- index.ttml 中的配置

```html
<view bindtap="viewTap"> click me </view>
```

- index.js 中的配置

```javascript
// index.js
Page({ 
  viewTap: function() { 
    console.log('view tap') 
  } 
})
```

### 更新页面渲染

setData(Object data, Function callback) 用于更新页面渲染，setData 将数据从逻辑层发送到视图层（异步），同时改变对应的 `this.data` 的值（同步）。

setData 参数说明如下：

字段 | 类型 | 是否必填 | 描述
---|---|---|---
data | Object | 是 | 本次要改变的数据。
callback | function | 否 | 回调函数。

其中：

- `data` 数据格式为 `key:value`，表示将 `this.data` 中的 key 对应的值改变成 value。

- `callback` 是一个回调函数，在本次 `setData` 对界面渲染完成后调用。

示例代码如下：

- index.ttml 中的配置

```html
<view>{{text}}</view>
<button bindtap="changeText"> Change normal data </button>
<view>{{num}}</view>
<button bindtap="changeNum"> Change normal num </button>
<view>{{array[0].text}}</view>
<button bindtap="changeItemInArray"> Change Array data </button>
<view>{{object.text}}</view>
<button bindtap="changeItemInObject"> Change Object data </button>
<view>{{newField.text}}</view>
<button bindtap="addNewField"> Add new data </button>
```

- index.js 中的配置

```js
//index.js
Page({
  data: {
    text: 'init data',
    num: 0,
    array: [{text: 'init data'}],
    object: {
      text: 'init data'
    }
  },
  changeText: function() {
    // this.data.text = 'changed data'  // 这样无法更新UI
    this.setData({
      text: 'changed data'
    })
  },
  changeNum: function() {
    this.data.num = 1
    this.setData({
      num: this.data.num
    })
  },
  changeItemInArray: function() {
    this.setData({
      'array[0].text':'changed data'
    })
  },
  changeItemInObject: function(){
    this.setData({
      'object.text': 'changed data'
    });
  },
  addNewField: function() {
    this.setData({
      'newField.text': 'new data'
    })
  }
})
```

### 配置页面分享

onShareAppMessage(Object object) 用于配置页面分享。当用户点击页面内转发按钮（TTML 中使用`button`组件，并设置属性为`open-type="share"`），或者点击右上角菜单的分享按钮时，会回调该方法。用户可以在该方法内自定义分享内容。

#### onShareAppMessage 参数说明

字段 | 类型 | 描述
---|---|---
from | String | 转发事件来源。<br>- button：页面内转发按钮。<br>- menu：右上角转发菜单。

#### 自定义分享内容

该事件处理函数需要返回（return） 一个 Object，用于自定义转发内容，返回内容的结构如下表所示。

名称 | 类型 | 是否必填 | 默认值 | 描述
---|---|---|---|---
title | String | 是 | 当前小程序的名字。 | 分享的标题。
path | String | 是 | 小程序的当前页面。 | 移动端打开小程序加载的页面，如果不支持移动端则需传空字符串('')，否则默认为当前分享页面的路径。
PCPath | String | 否 | \- | PC 端打开小程序加载的页面。如果不支持 PC 端，可传空字符串。
PCMode | String | 否 | \- | PC 端打开小程序加载的模式，如果需要在 PC 端打开小程序，则必须传 PCMode 字段。取值说明：<br>- sidebar-semi：在聊天页以侧边栏的形式打开小程序。在非聊天页以独立小窗口的形式打开小程序。<br>- window-semi：以独立小窗口的形式打开小程序。<br>- appCenter：在工作台中打开小程序。<br>- window：以独立大窗口的形式打开小程序。
imageUrl | String | 否 | 小程序当前页面从顶部向下截取 210 × 130 作为分享图。 | 自定义分享图。目前仅支持网络图片路径，图片大小建议 1160 × 720。
success | function | 否 | \- | 分享成功的回调。
fail | function | 否 | \- | 分享失败的回调。

`success`，`fail` 回调函数仅支持 v3.7.0+ 版本，且依赖于用户登录。

- success 的返回值 res 中，有一个 `data` 数据，说明如下表所示。

名称 | 类型 | 描述
---|---|---
data | array | 选择会话列表。

- data 数组的每个数据都是 Object 类型，结构说明如下表所示。

名称 | 类型 | 描述
---|---|---
id | string | openChatId。
chatType | string | 会话类型。取值：<br>- 0：单聊<br>- 1：群聊

示例代码如下：

```js
Page({
  onShareAppMessage: function (opt) {
      console.log(opt);
      return Object.assign({}, this.data.shareData, {
        title: opt.from === 'button' ? 'button share' : 'menu share',
        path: '/page/API/pages/share/share?a=b&from=' + opt.from,
        PCPath: '/page/API/pages/share/share?a=b&from=' + opt.from,
        PCMode: 'sidebar-semi',
        success (res) {
          console.log('success', res)
        },
        fail (err) {
          console.error(err);
        }
      })
    }
})
```

### 选区事件
选区事件的版本要求：飞书 ≥ v4.2

该事件用于监听 text 组件选区改变的事件，回调参数为一个 Object，包含的参数说明如下表所示。

名称 | 类型 | 描述
---|---|---
content | string | 选中的文本。
isCollapsed | boolean | 是否有选区。
position | {x: number, y: number, width: number, height: number} | 选区坐标位置。
selectedObject | Array<{startOffset: number, endOffset: number, text: string, id?: string, dataset?: Object}> | 当 text 组件嵌套时，会返回每个 text 组件选中的信息。

示例代码如下：

```js
Page({
  onSelectionChange(evt) {
    console.log(evt.content)
    if (evt.isCollapsed) {
      // 有选区状态，可以认为开始选择文本
    } else {
      // 无选区状态，可以认为取消选择文本
    }
  }
})
```

