# @qihoo/wx2qh

> 360小程序迁移工具

Latest version **1.0.6** (published 2019-12-16) · MIT license · 0 weekly downloads

## Install

```sh
npm install @qihoo/wx2qh
pnpm add @qihoo/wx2qh
yarn add @qihoo/wx2qh
bun add @qihoo/wx2qh
```

Provides the command `wx2qh`.

## Health

**Score 20/100 (F)** — status: abandoned.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.6 |
| Published | 2019-12-16 |
| First published | 2019-09-19 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | ESM + CommonJS |
| Dependencies | 42 |
| Unpacked size | 82.2 KB |
| Known vulnerabilities | 0 (+53 in 2 direct dependencies) |
| Install scripts | no |
| Maintainers | heweixiao, lgy573, lizheming, zhanping |
| Keywords | 360小程序, 转换, transform, wx2qh |

## Links

- npm: https://www.npmjs.com/package/@qihoo/wx2qh
- npm.io page: https://npm.io/package/@qihoo/wx2qh

## Dependencies (42)

- [chalk](https://npm.io/package/chalk.md) ^2.4.2
- [debug](https://npm.io/package/debug.md) ^4.1.1
- [execa](https://npm.io/package/execa.md) ^2.0.4
- [xtend](https://npm.io/package/xtend.md) ^4.0.1
- [ccount](https://npm.io/package/ccount.md) ^1.0.0
- [globby](https://npm.io/package/globby.md) ^10.0.1
- [lodash](https://npm.io/package/lodash.md) ^4.17.11
- [postcss](https://npm.io/package/postcss.md) ^7.0.17
- [unified](https://npm.io/package/unified.md) ^8.0.0
- [electron](https://npm.io/package/electron.md) ^7.1.2
- [fs-extra](https://npm.io/package/fs-extra.md) ^8.1.0
- [inquirer](https://npm.io/package/inquirer.md) ^7.0.0
- [minimist](https://npm.io/package/minimist.md) ^1.2.0
- [prettier](https://npm.io/package/prettier.md) ^1.18.2
- [to-vfile](https://npm.io/package/to-vfile.md) ^6.0.0
- [lru-cache](https://npm.io/package/lru-cache.md) ^5.1.1
- [@babel/types](https://npm.io/package/@babel/types.md) ^7.7.4
- [rehype-parse](https://npm.io/package/rehype-parse.md) ^6.0.0
- [@babel/parser](https://npm.io/package/@babel/parser.md) ^7.5.5
- [unist-builder](https://npm.io/package/unist-builder.md) ^1.0.4
- [unist-util-is](https://npm.io/package/unist-util-is.md) ^3.0.0
- [parse-entities](https://npm.io/package/parse-entities.md) ^1.2.2
- [vfile-reporter](https://npm.io/package/vfile-reporter.md) ^6.0.0
- [@babel/traverse](https://npm.io/package/@babel/traverse.md) ^7.5.5
- [@babel/generator](https://npm.io/package/@babel/generator.md) ^7.7.4
- [rehype-stringify](https://npm.io/package/rehype-stringify.md) ^6.0.0
- [unist-util-visit](https://npm.io/package/unist-util-visit.md) ^1.4.1
- [download-git-repo](https://npm.io/package/download-git-repo.md) ^3.0.2
- [hast-util-to-html](https://npm.io/package/hast-util-to-html.md) ^6.0.0
- [unist-util-filter](https://npm.io/package/unist-util-filter.md) ^1.0.2
- [unist-util-select](https://npm.io/package/unist-util-select.md) ^2.0.2
- [unist-util-source](https://npm.io/package/unist-util-source.md) ^1.0.5
- [html-void-elements](https://npm.io/package/html-void-elements.md) ^1.0.0
- [stringify-entities](https://npm.io/package/stringify-entities.md) ^2.0.0
- [postcss-safe-parser](https://npm.io/package/postcss-safe-parser.md) ^4.0.1
- [hast-util-is-element](https://npm.io/package/hast-util-is-element.md) ^1.0.0
- [hast-util-whitespace](https://npm.io/package/hast-util-whitespace.md) ^1.0.0
- [property-information](https://npm.io/package/property-information.md) ^5.0.1
- [stricter-htmlparser2](https://npm.io/package/stricter-htmlparser2.md) ^3.9.6
- [comma-separated-tokens](https://npm.io/package/comma-separated-tokens.md) ^1.0.0
- [space-separated-tokens](https://npm.io/package/space-separated-tokens.md) ^1.0.0
- [hast-util-parse-selector](https://npm.io/package/hast-util-parse-selector.md) ^2.2.0

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 1.0.6 (latest) — 2019-12-16
- 1.0.10 (next) — 2020-01-13
- 1.0.9 — 2020-01-13
- 1.0.8 — 2020-01-13
- 1.0.7 — 2020-01-13
- 1.0.5 — 2019-12-16
- 1.0.3 — 2019-12-13
- 1.0.2 — 2019-12-13
- 1.0.1 — 2019-12-12
- 1.0.0 — 2019-12-09
- 0.1.2-alpha.5 — 2019-10-17
- 0.1.2-alpha.4 — 2019-10-17
- 0.1.2-alpha.3 — 2019-10-17
- 0.1.2-alpha.2 — 2019-10-16
- 0.1.2-alpha.1 — 2019-10-16
- … 5 more at https://npm.io/package/@qihoo/wx2qh/versions

## README

# wx2qh

wx2qh 是用来将微信小程序迁移到 360 小程序的转化工具，它基于 AST，然后按照一定的规则静态分析来抹平平台之间的语法差异，简化迁移微信小程序到 360 小程序流程。

- wx2qh 解决了平台之间的语法差异，而运行时的差异需要进行二次开发来修复
- 不支持迁移第三方框架开发的微信小程序

<span style="color: #d73a49">切记：</span>

转换完成后，需要切换到转化后生成目录（dest 指定目录）安装 [@qihoo/seapp-builder](https://www.npmjs.com/package/@qihoo/seapp-builder)来构建转化后的代码

# 目录

- [CLI](#cli)
  - [安装](#安装)
  - [编译整个项目](#编译整个项目)
  - [编译选定文件](#编译选定文件)
  - [忽略某些文件](#忽略某些文件)
  - [使用 preset](#使用-preset)
  - [常见转化问题](#常见转化问题)
- [API](#api)
  - [Props](#props)
  - [Methods](#methods)
    - [api.processor](#api-processor-name-matcher)
    - [api.nextTick](#api-nextTick-callback)
    - [api.logger](#api-logger-type-log-canSave)
- [Processor](#processor)
  - [processor.use](#processor-use-plugin-options)
  - [Attacher](#attacher)
    - [function attacher()](#function-attacher-options)
    - [function transformer()](function-transformer-node-file-next)
- [Preset](#preset)
- [Changelog](#changelog)

# CLI

切记：转换完成后，需要切换到转化后生成目录（dest 指定目录）安装 [@qihoo/seapp-builder](https://www.npmjs.com/package/@qihoo/seapp-builder)来构建转化后的代码

## 安装

建议全局安装。

```shell
 npm i -g @qihoo/wx2qh
```

项目内安装：

```shell
  npm i @qihoo/wx2qh
```

命令行参数如下：

```shell
wx2qh \<source\> \<output\>    transform the files in source directory to dest
  wx2qh version              output version number
  wx2qh help                 output usage infomation

  options:
    -f,--file   set files pattern  \<glob\>
    -i,--ignore set ignore files pattern  \<glob\>
    -p,--preset set preset config \<string\>
    -r,--ratio  set rpx2px ratio  \<number\>
```

参数说明：

- `source` 待迁移微信小程序项目路径(必填)
- `output` 迁移后，360 小程序的生成目录(默认值为 . 即当前目录)
- `-f`,`--file` 指定要转化的文件(`glob`: dir/\*.wxml)
- `-i`, `--ignore` 忽略要转化的文件
- `-p`, `--preset` 指定预设配置文件路径,详情见[使用 preset](#使用-preset)
- `-r`, `--ratio` 指定 rpx2px 的转化比例(默认：2， 2rpx => 1px)

## 编译整个项目

编译整个 wxApp 目录下的文件并输出到 360mp 目录，这个时候会对 已存在的 360mp 目录做二次确认，防止因为路径填写错误 覆盖原有文件，360mp 目录不存在则没有二次确认。

```shell
  wx2qh ./wxApp ./360mp
```

```shell
? The output directory `/work/360mp` is existed, Pick an action: (Use arrow keys)
\> Overwrite // 删除 360mp 目录，然后写入
  Merge      // 直接写入
  Cancel     // 取消
```

## 编译选定文件

可以通过设置 file(f) 选项编译符合这个规则的文件，值是 glob 类型。

```shell
  wx2qh ./wxApp ./360mp -f=*.wxml
```

## 忽略某些文件

可以通过设置 ignore(i) 选项忽略符合这个规则的文件，值是 glob 类型。

```shell
  wx2qh ./wxApp ./360mp -i=*.test.js
```

## 使用 preset

可以通过设置 preset(p) 选项设置预设值，从而可以拓展和修改 wx2qh 的一些内置配置、插件等。preset 的路径支持情况如下：

- 本地路径：preset.startsWith('.')
- 绝对路径：path.isAbsolute(preset)
- npm package：preset.startsWith('wx2qh-plugin-')
- 默认：wxApp 目录下的 .wx2qhrc.json

```shell
  wx2qh ./wxApp ./360mp -p ./wx2qh-plugin-preset
```

## 常见转化问题

- 转换 getApp()
  在所有调用 getApp 的地方改写成如下：

```javascript
let app = null
Page({
  beforeCreate() {
    app = getApp()
  }
})
```

- 确认 app.json 中添加 sdkversion 字段()

```javascript
{
  "sdkversion": "1.0.0"
}
```

# API

## Props

- transformer
  - `object`
  - 转换 `processor` 执行器
- compilation
  - `map`
  - 内置 `processor` 的 `Parser` 和 `Compiler` 存储容器
- output
  - `string`
  - 编译后文件的输出路径
- options
  - `object`
  - 配置选项，包括 cli 选项，prettier 配置等。等同于 [PRESET](#preset)
- ticks
  - `set`
  - api.nexttick 传入回调的存储容器
- files
  - `array`
  - vfile 存储容器

## Methods

### api.processor(name[, matcher])

###### 参数

- name (`string` | `object`) `processor` 名称
  - `object` 需要满足 { name, matcher }
- matcher (`string` | `regexp` | `function`) 过滤 files 中的 vfile
  - `string` 强制转换成正则
  - `function` 自定义过滤规则，参数是 vfile

###### 返回值

`processor` 定义文本处理流程，详情请见[processor](#processor)

###### 例子

```js
module.exports = function(api) {
  // 1. (name: string, matcher: string): Processor {}
  const processor = api.processor('demo', '*.wxml')

  // 2. (name: string, matcher: RegExp): Processor {}
  const processor = api.processor('demo', /\*.wxml/)

  // 3. (name: string, matcher: function): Processor {}
  const processor = api.processor('demo', file => file.path === 'index.wxml')

  // 4. (name: object): processor {}
  const processor = api.processor({ name: 'demo', matcher: '*.wxml' })

  return processor
}
```

### api.nextTick(callback)

###### 参数

- callback (`function`) 持有 filesMap 上下文的回调函数,该 callback 会在输出文件之前串行调用

###### 例子

```js
module.exports = function(api) {
  api.nextTick(callback)

  function callback(filesmap) {
    // some handling process...
  }
}
```

### api.logger(type, log[, canSave])

###### 参数

- type (`string`) 日志类型
  - error 错误日志
  - warn 警告日志
  - info 信息日志
  - done 完成日志
- log (`string`|`object`) 日志内容
  - `object` { file, row, column, message }, 会在 `canSave=true` 打印位置等其他信息
- canSave (`boolean`, optional) [default: `false`] 是否存入 logStore

###### 例子

```js
module.exports = function demoProcessor(api) {
  // 1. (type: string, log: string): void {}
  api.logger('error', 'I am a error log')
  api.logger('warn', 'I am a warning log')
  // 2. (type: string, log: object, canSave: boolean): void {}
  api.logger(
    'info',
    {
      file: 'app.json',
      message: 'has sdkversion prop',
      row: 10,
      colum: 4
    },
    true
  )
}
```

# Processor

关于 `processor`，下面只列出一些常用接口，更详细文档请参考 [unifiedjs](https://github.com/unifiedjs/unified#table-of-contents)

## processor.use(plugin[, options])

使用 use 方法为 `processor` 配置插件,并可以可选的传入配置项

###### 场景

- processor.use(plugin[, options])
- processor.use(preset)
- processor.use(list)

###### 参数

- plugin ([`Attacher`](#attacher))
- options (`*`, optional) 插件的配置选项
- preset (`object`) { settings: {}, plugins: [] }，都是可选属性
- list (`array`) [plugin, preset, [plugin, options]]

###### 返回值

`processor` 返回当前调用 `use` 的调用者，可链式调用

###### 例子

```js
module.exports = function demoProcessor() {
  const processor = api.processor('demo', 'index.wxml')

  processor
    // plugin with options:
    .use(plugin, {})
    // Plugins:
    .use([plugin, pluginB])
    // Two plugins, the second with options:
    .use([plugin, [pluginB, {}]])
    // Preset with plugins and settings:
    .use({
      settings: [(position: false)],
      plugins: [plugin, [pluginB, {}]]
    })
    // Settings only:
    .use({ settings: { position: false } })

  function plugin() {}
  function pluginB() {}

  return processor
}
```

## Attacher

`processor` 插件仅仅是一种概念，而 `attacher` 是 `processor` 插件的实现，它可以访问和修改 `processor` 的属性和方法，尤其是可以为 `processor` 添加必要的 `Parser` 和 `Compiler` 从而实现 `text` 到 `ast` 的反序列化，`ast` 到 `text` 的序列化。

###### 例子

`demoProcessor.js`:

```js
module.exports = function demoProcessor(api) {
  const processor = api.processor('demo', 'demo.wxml')

  // 获取内置的 compilation ，可以用来处理 xml 类型文件
  const wxmlCompilation = api.compilation.get('wxml2vue')

  processor
    // 自定义
    // .use([parser, compiler])
    // 内置
    .use(wxmlCompilation)
    .use(demoAttacher)

  return processor
}
function demoAttacher(options) {
  return span2div

  function span2div(tree) {
    // process tree...
    const spanElement = tree.children[0]
    const spanText = spanElement.children[0]
    spanElement.tagName = 'div'
    spanText.value = `I am a div`
  }
}
// 自定义 Parser ，也可以使用第三方 Parser 以及 内置的
function parser(settings) {
  this.Parser = parser

  function parser(doc) {
    return {
      type: 'default',
      contents: String(doc),
      toString() {
        return this.contents
      }
    }
  }
}
// 自定义 Compiler ，也可以使用第三方 Parser 以及 内置的
function compiler() {
  this.Compiler = compiler

  function compiler(tree) {
    return tree.toString()
  }
}
```

`demo.wxml`:

```html
<span>I am a span</span>
```

`cmd`:

```shell
  wx2qh ./demo.wxml ./360mp -p ./demoProcessor.js
```

output `360mp/index.wxml`:

```html
<div>I am a div</div>
```

### function attacher([options])

###### context

上下文对象（`this`）指向 `processor`

###### 参数

- options (`*`, optional) 配置选项

###### 返回值

[transformer](#transformer) 可选

### function transformer(node, file[, next])

###### 参数

- node (`node`) 经过 Parser 转换后的语法树
- file (`vfile`) 正在被 `processor` 处理的 file
- next (`function`, optional)

###### 返回值

- void 如果返回时是 `void`，当前处理的 `node` 将继续流入下一个 `transform`。
- Error 如果返回 `Error`， `processor` 将停止工作。
- node 如果返回 `node`，返回的 `node` 将流入下一个 `transformer`
- Promise 如果返回的是 `Promise`，将会等到 `Promise` 达到最终状态，然后将返回值流入下一个 `transformer` 或者中断 `processor`

#### function next(err[, tree[, file]])

###### 参数

- err (`Error`, optional)
- tree (`node`, optional)
- file (`vfile`, optional)

# Preset

preset 配置如下：

```js
  // 是否需要合并内置 options
  root: true, // boolean
  // === wx2qh cli options ===
  file: '**',
  ignore: [],
  preset: undefined,
  ratio: 2,
  // ====
  // === prettier config ===
  // 是否开启 使用 prettier 格式化代码
  prettier: true,
  // prettier 配置
  prettierrc: {
    // 默认 parser
    parser: 'babel',
    // 根据条件选择合适的 parser
    parserEntries: [
      [/\.js$/, 'babel'],
      [/\.wxss$/, 'scss'],
      [/\.wxml$/, 'html'],
      [/\.json$/, 'json']
    ],
    printWidth: 80,
    trailingComma: 'none',
    tabWidth: 2,
    semi: false,
    singleQuote: true,
    useTabs: false,
    bracketSpacing: true,
    insertPragma: false,
    arrowParens: 'avoid',
    htmlWhitespaceSensitivity: 'ignore'
  },
  // ===
  // 插件列表 processor
  plugins: [
    require('wxml2vue'),
    require('wxjs2vue'),
    require('wxss2css'),
    require('wx2qh-plugin-preset')
  ]
```

# CHANGELOG

## v1.0.1

#### FEATURE

- 插件化重构
- 根据文件后缀格式化代码(prettier)
- 支持在行内样式中转换 rpx2px
- 支持 hidden=x 转为 v-show="false"
- app.json 配置默认添加 sdkversion 字段

## v0.1.2-alpha.0

#### FEATURE

- 支持样式比例转换
- 支持 template 标签转换
- 支持 include 和 import 标签转换
- 自动生成添加了 360 小程序构建工具 latest 版本依赖的 package.json 文件

#### FIX

- css 迁移时 @keyframes 100% 没有正确转化 100% => .is_100%

# 能力

我们将以下几个方面来阐述 wx2qh 的迁移能力，您能够了解到它做了什么

- [视图](#视图)
- [样式](#样式)
- [框架](#框架)
- [接口](#接口)

### 视图

wxml 语法转换为 vue 语法

#### 转化关系对应

##### 一、attrs

将微信小程序标签上的属性绑定语法变为 360 小程序绑定语法，如：

| 微信小程序      | 360 小程序 |
| :-------------- | :--------- |
| id="item"       | id="item"  |
| id=" {{item}} " | :id="item" |

##### 二、components

将微信小程序组件转换为 360 小程序组件。如果 360 小程序组件没有该组件，则不转换且给出提示。

目前支持组件转换的列表如下：

| 微信小程序     | 360 小程序        |
| :------------- | :---------------- |
| movable-view   | se-movable-view   |
| movable-area   | se-movable-area   |
| scroll-view    | se-scroll-view    |
| swiper         | se-swiper         |
| swiper-item    | se-swiper-item    |
| view           | se-view           |
| icon           | se-icon           |
| progress       | se-progress       |
| rich-text      | se-rich-text      |
| text           | se-text           |
| button         | se-button         |
| checkbox       | se-checkbox       |
| checkbox-group | se-checkbox-group |
| form           | se-form           |
| input          | se-input          |
| radio          | se-radio          |
| radio-group    | se-radio-group    |
| slider         | se-slider         |
| switch         | se-switch         |
| audio          | se-audio          |
| image          | se-image          |
| video          | se-video          |
| ad             | se-ad             |
| block          | template          |

##### 三、directives

将微信小程序的指令转换为 360 小程序指令：

| 微信小程序                                              | 360 小程序                  |
| :------------------------------------------------------ | :-------------------------- |
| wx:for="{{array}}" wx:for-item="xxx" wx:for-index="yyy" | v-for="(xxx, yyy) in array" |
| wx:if                                                   | v-if                        |
| wx:elif                                                 | v-else-if                   |
| wx:else                                                 | v-else                      |

##### 四、template

将微信小程序的 template 转换成 360 小程序中的 component，目前仅支持 template 的内容转换。微信小程序源码中，通过`<import src="a.wxml"/>` 和 `<include src="header.wxml"/>` 这两种方式引用的地方需要将转换后的内容手动添加过来。

###### template 模版内容转换

转换前：

```
<template name="A">
    <div wx:for="{{ array }}" wx:for-item="it" wx:for-index="$index">{{it}}{{$index}}</div>
    <template name="B">
      <div class="x-{{ ccc }}">{{ bbb }} {{ array.length }}</div>
    </template>
    <template is="C" data="{{ ...xxx, x: xxx[eee + 'c'] ? ccc : 22 }}"></template>
</template>
```

转换后：

```
<template name="A" scope="{ array, ccc, eee, xxx }">
    <div v-for="(it, $index) in array">{{it}}{{$index}}</div>
    <template name="B" scope="{ array, bbb, ccc }">
      <div :class="\`x-\${ccc}\`">{{ bbb }} {{ array.length }}</div>
    </template>
    <component is="C" v-bind="{ ...xxx, x: xxx[eee + 'c'] ? ccc : 22 }"></component>
</template>
```

###### template 引用转换

转换前：

```
<template is="{{staffName}}" data="{{...staffA}}"></template>
```

转换后：

```
<component :is="staffName" v-bind="{ ...staffA }"></component>
```

### 样式

#### 基础组件标签转换

1. wx 小程序里有，但 360 小程序里没有的基础组件标签：不用转换，直接将该节点转化为注释节点。
2. wx 小程序里有，但 360 小程序里没有且与 html 原生标签同名的基础组件：不做处理，直接使用原生标签。
3. wx 小程序里有，且 360 小程序里也有的基础组件标签：统一转换为 class 选择器形式，.is\_[基础组件标签名]。

#### 单位转换

遍历所有 css 属性，将 wx 小程序的 `rpx` 转化为 `px`。

### 框架

> 由于我们底层是基于 Vue 的，文档从 Vue 的角度说明迁移后的能力支持

接口支持情况如下，其他的 选项(option) 请参考[能力支持表格](#能力支持)：

- App
  - 支持 data 和 methods 直接定义在 选项(options) 根级别上

```javascript
App({
  func1: function() {},
  data1: 111
})
```

- getApp
  - 由于框架实现差异，getApp 只能在 beforeCreate 或之后的 vue 生命周期中获取

```javascript
let app = null
Page({
  beforeCreate() {
    app = getApp()
  }
})
```

- Page
  - 支持 this.setData
- getCurrentPages
  - 暂不支持(需要开发者二次开发改写)
- Component
  - 选项(options)支持情况见下表格
- Behavior
  - 暂不支持(需要开发者二次开发改写)

#### 能力支持

**注意格式问题**

- `-` 代表待定，目前不支持，未来可能支持
- `N` 代表遗弃，现在和未来都不支持
- `Y` 代表已支持，（框架支持）

| 微信小程序                    | 描述                                                                           | Seapp                                            | Version |
| ----------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------ | ------- |
| `App`: onLaunch               | `lifecycle`-监听小程序初始化                                                   | `beforeCreate` `created` `beforeMount` `mounted` |         |
| `App`: onShow                 | `lifecycle`-监听小程序启动或切前台                                             | `-`                                              |         |
| `App`: onHide                 | `lifecycle`-监听小程序切后台                                                   | `-`                                              |         |
| `App`: onError                | 错误监听函数                                                                   | `-`                                              |         |
| `App`: onPageNotFound         | 页面不存在监听函数                                                             | `-`                                              |         |
| `Page`: data                  | 页面的初始数据                                                                 | `data`                                           |         |
| `Page`: onLoad                | `lifecycle`-监听页面加载                                                       | `mounted`                                        |         |
| `Page`: onShow                | `lifecycle`-监听页面显示                                                       | `onShow`                                         |         |
| `Page`: onReady               | `lifecycle`-监听页面初次渲染完成                                               | `onReady`                                        |         |
| `Page`: onHide                | `lifecycle`-监听页面隐藏                                                       | `onHide`                                         |         |
| `Page`: onUnload              | `lifecycle`-监听页面卸载                                                       | `beforeDestroy` `destroy`                        |         |
| `Page`: onPullDownRefresh     | 监听用户下拉动作                                                               | `-`                                              |         |
| `Page`: onReachBottom         | 页面上拉触底事件的处理函数                                                     | `-`                                              |         |
| `Page`: onShareAppMessage     | 用户点击右上角转发                                                             | `-`                                              |         |
| `Page`: onPageScroll          | 页面滚动触发事件的处理函数                                                     | `-`                                              |         |
| `Page`: onResize              | 页面尺寸改变时触发                                                             | `-`                                              |         |
| `Page`: onTabItemTap          | 当前是 tab 页时，点击 tab 时触发                                               | `-`                                              |         |
| `Component`: properties       | 组件的对外属性                                                                 | `props`                                          |         |
| `Component`: data             | 组件的内部数据                                                                 | `data`                                           |         |
| `Component`: observers        | 组件数据字段监听器                                                             | `watch`                                          | 2.6.1   |
| `Component`: methods          | 组件的方法                                                                     | `methods`                                        |         |
| `Component`: behaviors        | 类似于 mixins 和 traits                                                        | `mixins`                                         |         |
| `Component`: created          | `lifecycle`-在组建实例创建时执行，不能调用 setData                             | `beforeCreate` `created`                         |         |
| `Component`: attached         | `lifecycle`-在组件实例进入页面节点树时执行                                     | `beforeMount`                                    |         |
| `Component`: ready            | `lifecycle`-在组件布局完成后执行                                               | `mounted`                                        |         |
| `Component`: moved            | `lifecycle`-在组件实例被移动到节点树另一个位置时执行                           | `-`                                              |         |
| `Component`: detached         | `lifecycle`-在组件实例被从页面节点树移除时执行                                 | `destroy`                                        |         |
| `Component`: relations        | 组件间关系定义                                                                 | `-`                                              |         |
| `Component`: externalClasses  | 组件接受的外部样式类                                                           | `Y`                                              |         |
| `Component`: options          | 一些选项（文档中介绍相关特性时会涉及具体的选项设置）                           | `-`                                              |         |
| `Component`: lifetimes        | 组件生命周期生命对象 （权重 > normal）                                         | `Y`                                              | 2.2.3   |
| `Component`: pageLifetimes    | 组件所在页面的生命周期声明对象                                                 | `-`                                              | 2.2.3   |
| `Component`: definitionFilter | 定义段过滤器，用于自定义组件扩展                                               | `-`                                              | 2.2.3   |
| `All`: 其他                   | 开发者可以添加任意的函数或数据到 Object 参数中，在页面的函数中用 this 可以访问 | `Y`                                              |         |

### 接口

由于 360 小程序 api 与微信小程序 api 无论是方法名，参数形式基本保持一致，所以 360 小程序实现了的 api 迁移后都支持

[360 小程序 api 文档](https://mp.360.cn/doc/miniprogram/dev/#/e1487ee88399013ec06eff05007391fc)

---
_Source: https://npm.io/package/@qihoo/wx2qh · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
