未验证 提交 c9458657 编写于 作者: O openharmony_ci 提交者: Gitee

!21220 system.app、懒加载文档整改

Merge pull request !21220 from 田雨/master
......@@ -78,19 +78,19 @@ interface DataChangeListener {
| 接口声明 | 参数类型 | 说明 |
| ------------------------------------------------------------ | -------------------------------------- | ------------------------------------------------------------ |
| onDataReloaded(): void | - | 通知组件重新加载所有数据。 |
| onDataAdded(index:&nbsp;number):void<sup>(deprecated)</sup> | number | 通知组件index的位置有数据添加。<br/>从API 8开始,建议使用onDataAdd。<br/>index:数据添加位置的索引值 |
| onDataMoved(from:&nbsp;number,&nbsp;to:&nbsp;number):&nbsp;void<sup>(deprecated)</sup> | from:&nbsp;number,<br/>to:&nbsp;number | 通知组件数据有移动。<br/>从API 8开始,建议使用onDataMove。<br/>from:&nbsp;数据移动起始位置,to:&nbsp;数据移动目标位置。<br/>**说明:**<br/>数据移动前后键值要保持不变,如果键值有变化,应使用删除数据和新增数据接口。 |
| onDataDeleted(index: number):void<sup>(deprecated)</sup> | number | 通知组件删除index位置的数据并刷新LazyForEach的展示内容。<br/>从API 8开始,建议使用onDataDelete。<br/>index:数据删除位置的索引值 |
| onDataChanged(index:&nbsp;number):&nbsp;void<sup>(deprecated)</sup> | number | 通知组件index的位置有数据有变化。<br/>从API 8开始,建议使用onDataChange。<br/>index:数据变化监听器。 |
| onDataAdd(index:&nbsp;number):&nbsp;void<sup>8+</sup> | number | 通知组件index的位置有数据添加。<br/>index:数据添加位置的索引值 |
| onDataMove(from:&nbsp;number,&nbsp;to:&nbsp;number):&nbsp;void<sup>8+</sup> | from:&nbsp;number,<br/>to:&nbsp;number | 通知组件数据有移动。<br/>from:&nbsp;数据移动起始位置,to:&nbsp;数据移动目标位置。<br/>**说明:**<br/>数据移动前后键值要保持不变,如果键值有变化,应使用删除数据和新增数据接口。 |
| onDataDelete(index: number):void<sup>8+</sup> | number | 通知组件删除index位置的数据并刷新LazyForEach的展示内容。<br/>index:数据删除位置的索引值<br/>**说明:** <br/>需要保证dataSource中的对应数据已经在调用onDataDelete前删除,否则页面渲染将出现未定义的行为。 |
| onDataChange(index:&nbsp;number):&nbsp;void<sup>8+</sup> | number | 通知组件index的位置有数据有变化。<br/>index:数据变化位置的索引值 |
| onDataAdded(index:&nbsp;number):void<sup>(deprecated)</sup> | number | 通知组件index的位置有数据添加。<br/>从API 8开始,建议使用onDataAdd。<br/>index:数据添加位置的索引值 |
| onDataMoved(from:&nbsp;number,&nbsp;to:&nbsp;number):&nbsp;void<sup>(deprecated)</sup> | from:&nbsp;number,<br/>to:&nbsp;number | 通知组件数据有移动。<br/>从API 8开始,建议使用onDataMove。<br/>from:&nbsp;数据移动起始位置,to:&nbsp;数据移动目标位置。<br/>**说明:**<br/>数据移动前后键值要保持不变,如果键值有变化,应使用删除数据和新增数据接口。 |
| onDataDeleted(index: number):void<sup>(deprecated)</sup> | number | 通知组件删除index位置的数据并刷新LazyForEach的展示内容。<br/>从API 8开始,建议使用onDataDelete。<br/>index:数据删除位置的索引值 |
| onDataChanged(index:&nbsp;number):&nbsp;void<sup>(deprecated)</sup> | number | 通知组件index的位置有数据有变化。<br/>从API 8开始,建议使用onDataChange。<br/>index:数据变化监听器。 |
## 使用限制
- LazyForEach必须在容器组件内使用,仅有List、Grid以及Swiper组件支持数据懒加载(即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据。
- LazyForEach必须在容器组件内使用,仅有[List](../reference/arkui-ts/ts-container-list.md)[Grid](../reference/arkui-ts/ts-container-grid.md)以及[Swiper](../reference/arkui-ts/ts-container-swiper.md)组件支持数据懒加载(可配置cachedCount属性,即只加载可视部分以及其前后少量数据用于缓冲),其他组件仍然是一次性加载所有的数据。
- LazyForEach在每次迭代中,必须创建且只允许创建一个子组件。
......@@ -177,7 +177,7 @@ class BasicDataSource implements IDataSource {
}
class MyDataSource extends BasicDataSource {
private dataArray: string[] = ['/path/image0', '/path/image1', '/path/image2', '/path/image3'];
private dataArray: string[] = [];
public totalCount(): number {
return this.dataArray.length;
......@@ -201,6 +201,12 @@ class MyDataSource extends BasicDataSource {
@Entry
@Component
struct MyComponent {
aboutToAppear() {
for (var i = 100; i >= 80; i--) {
this.data.pushData(`Hello ${i}`)
}
}
private data: MyDataSource = new MyDataSource();
build() {
......@@ -208,15 +214,17 @@ struct MyComponent {
LazyForEach(this.data, (item: string) => {
ListItem() {
Row() {
Image(item).width('30%').height(50)
Text(item).fontSize(20).margin({ left: 10 })
Text(item).fontSize(50)
.onAppear(() => {
console.info("appear:" + item)
})
}.margin({ left: 10, right: 10 })
}
.onClick(() => {
this.data.pushData('/path/image' + this.data.totalCount());
this.data.pushData(`Hello ${this.data.totalCount()}`);
})
}, item => item)
}
}.cachedCount(5)
}
}
```
......@@ -721,21 +721,19 @@ pushUrl(options: router.RouterOptions): Promise&lt;void&gt;
```ts
let router = uiContext.getRouter();
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
})
} catch (err) {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
### pushUrl
......@@ -819,21 +817,19 @@ pushUrl(options: router.RouterOptions, mode: router.RouterMode): Promise&lt;void
```ts
let router = uiContext.getRouter();
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
})
}, router.RouterMode.Standard)
} catch (err) {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
### pushUrl
......@@ -916,18 +912,16 @@ replaceUrl(options: router.RouterOptions): Promise&lt;void&gt;
```ts
let router = uiContext.getRouter();
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
try {
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
})
} catch (err) {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
### replaceUrl
......@@ -1006,18 +1000,16 @@ replaceUrl(options: router.RouterOptions, mode: router.RouterMode): Promise&lt;v
```ts
let router = uiContext.getRouter();
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
})
try {
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
} catch (err) {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
### replaceUrl
......@@ -1097,21 +1089,19 @@ pushNamedRoute(options: router.NamedRouterOptions): Promise&lt;void&gt;
```ts
let router = uiContext.getRouter();
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
} catch (err) {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
### pushNamedRoute
......@@ -1194,21 +1184,19 @@ pushNamedRoute(options: router.NamedRouterOptions, mode: router.RouterMode): Pro
```ts
let router = uiContext.getRouter();
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
}, router.RouterMode.Standard)
} catch (err) {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
### pushNamedRoute
......@@ -1291,18 +1279,16 @@ replaceNamedRoute(options: router.NamedRouterOptions): Promise&lt;void&gt;
```ts
let router = uiContext.getRouter();
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
try {
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
})
} catch (err) {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
### replaceNamedRoute
......@@ -1382,18 +1368,16 @@ replaceNamedRoute(options: router.NamedRouterOptions, mode: router.RouterMode):
```ts
let router = uiContext.getRouter();
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
try {
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
} catch (err) {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
### replaceNamedRoute
......
......@@ -51,21 +51,19 @@ pushUrl(options: RouterOptions): Promise&lt;void&gt;
**示例:**
```ts
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
})
} catch (err) {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.pushUrl<sup>9+</sup>
......@@ -146,21 +144,19 @@ pushUrl(options: RouterOptions, mode: RouterMode): Promise&lt;void&gt;
**示例:**
```ts
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushUrl({
url: 'pages/routerpage2',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
})
}, router.RouterMode.Standard)
} catch (err) {
console.error(`pushUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.pushUrl<sup>9+</sup>
......@@ -241,18 +237,16 @@ replaceUrl(options: RouterOptions): Promise&lt;void&gt;
**示例:**
```ts
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
try {
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
})
} catch (err) {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.replaceUrl<sup>9+</sup>
......@@ -330,18 +324,16 @@ replaceUrl(options: RouterOptions, mode: RouterMode): Promise&lt;void&gt;
**示例:**
```ts
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
})
try {
router.replaceUrl({
url: 'pages/detail',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
} catch (err) {
console.error(`replaceUrl failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.replaceUrl<sup>9+</sup>
......@@ -420,21 +412,19 @@ pushNamedRoute(options: NamedRouterOptions): Promise&lt;void&gt;
**示例:**
```ts
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
} catch (err) {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.pushNamedRoute<sup>10+</sup>
......@@ -515,21 +505,19 @@ pushNamedRoute(options: NamedRouterOptions, mode: RouterMode): Promise&lt;void&g
**示例:**
```ts
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
try {
router.pushNamedRoute({
name: 'myPage',
params: {
data1: 'message',
data2: {
data3: [123, 456, 789]
}
}
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
}, router.RouterMode.Standard)
} catch (err) {
console.error(`pushNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.pushNamedRoute<sup>10+</sup>
......@@ -610,18 +598,16 @@ replaceNamedRoute(options: NamedRouterOptions): Promise&lt;void&gt;
**示例:**
```ts
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
})
.then(() => {
// success
})
.catch(err => {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
try {
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
})
} catch (err) {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.replaceNamedRoute<sup>10+</sup>
......@@ -699,18 +685,16 @@ replaceNamedRoute(options: NamedRouterOptions, mode: RouterMode): Promise&lt;voi
**示例:**
```ts
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
.then(() => {
// success
})
.catch(err => {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
})
try {
router.replaceNamedRoute({
name: 'myPage',
params: {
data1: 'message'
}
}, router.RouterMode.Standard)
} catch (err) {
console.error(`replaceNamedRoute failed, code is ${err.code}, message is ${err.message}`);
}
```
## router.replaceNamedRoute<sup>10+</sup>
......
# @system.app (应用上下文)
> **说明:**
> **说明:**
>
> - 从API Version 7 开始,该接口不再维护,推荐使用新接口。
>
> - 本模块首批接口从API version 3开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
> 本模块首批接口从API version 3开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
## 导入模块
......@@ -14,14 +12,15 @@
import app from '@system.app'
```
## App
## app.getInfo
### getInfo
getInfo(): AppResponse
static getInfo(): AppResponse
获取当前应用配置文件中声明的信息。
从API Version 7开始,推荐使用[`@ohos.bundle`](js-apis-Bundle.md)
从API Version9开始,推荐使用[bundleManager.getApplicationInfo](js-apis-bundleManager.md#bundlemanagergetapplicationinfo)
**系统能力:** SystemCapability.ArkUI.ArkUI.Lite
......@@ -42,9 +41,9 @@ export default {
}
```
## app.terminate
### terminate
terminate(): void
static terminate(): void
退出当前Ability。
......@@ -61,37 +60,9 @@ export default {
}
}
```
## app.requestFullWindow
### setImageCacheCount<sup>7+</sup>
requestFullWindow(options?: RequestFullWindowOptions): void
请求应用以全窗口运行,FA在某些场景下(如半模态FA)会以非全窗口运行,调用该接口会从非全窗口切换为全窗口运行,如果已经以全窗口运行则该接口调用无效。
从API Version 7开始,推荐使用[`@ohos.window`](js-apis-window.md)
**系统能力:** SystemCapability.ArkUI.ArkUI.Full
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| -------- | -------- | -------- | -------- |
| options | [RequestFullWindowOptions](#requestfullwindowoptions) | 否 | 请求全屏时,设定非全屏到全屏的过渡时间,单位为毫秒,默认时间与非全屏到全屏的距离成正比。 |
**示例:**
```ts
export default {
requestFullWindow() {
app.requestFullWindow({
duration: 200
})
}
}
```
## app.setImageCacheCount<sup>7+</sup>
setImageCacheCount(value: number): void
static setImageCacheCount(value: number): void
设置内存中缓存解码后图片的数量上限,提升再次加载同源图片的加载速度。如果不设置则默认为0,不进行缓存。缓存采用内置的LRU策略,新图片加载后,如果超过缓存上限,会删除最久未再次加载的缓存。建议根据应用内存需求,设置合理缓存数量,数字过大可能导致内存使用过高。
......@@ -120,9 +91,9 @@ export default {
}
```
## app.setImageRawDataCacheSize<sup>7+</sup>
### setImageRawDataCacheSize<sup>7+</sup>
setImageRawDataCacheSize(value: number): void
static setImageRawDataCacheSize(value: number): void
设置内存中缓存解码前图片数据的大小上限,单位为字节,提升再次加载同源图片的加载速度。如果不设置则默认为0,不进行缓存。缓存采用内置的LRU策略,新图片加载后,如果解码前数据超过缓存上限,会删除最久未再次加载的图片数据缓存。建议根据应用内存需求,设置合理缓存上限,过大可能导致应用内存使用过高。
......@@ -152,9 +123,9 @@ export default {
}
```
## app.setImageFileCacheSize<sup>7+</sup>
### setImageFileCacheSize<sup>7+</sup>
setImageFileCacheSize(value: number): void
static setImageFileCacheSize(value: number): void
设置图片文件缓存的大小上限,单位为字节,提升再次加载同源图片的加载速度,特别是对网络图源、缩略图会有较明显提升。如果不设置则默认为100MB。缓存采用内置的LRU策略,新图片加载后,如果超过文件缓存上限,会按照时间由远到近删除缓存图片文件直到缓存图片大小满足缓存上限。建议根据应用实际需求,设置合理文件缓存上限,数字过大可能导致磁盘空间占用过高。
......@@ -184,6 +155,48 @@ export default {
}
```
### ScreenOnVisible<sup>(deprecated)</sup>
static screenOnVisible(options?: ScreenOnVisibleOptions):&nbsp;void
定义屏幕唤醒时是否保持应用可见。
该接口从API Version 8 开始废弃。
**系统能力:** 以下各项对应的系统能力均为SystemCapability.ArkUI.ArkUI.Full
| 名称 | 类型 | 必填 | 说明 |
| ------- | ------------------------------------------------- | ---- | ------------------------------------------------------------ |
| options | [ScreenOnVisibleOptions](#screenonvisibleoptions) | 否 | 当启动保活时,锁屏时将阻止系统返回桌面显示,以保持屏幕唤醒时应用可见。 |
### requestFullWindow<sup>(deprecated)</sup>
static requestFullWindow(options?: RequestFullWindowOptions): void
请求应用以全窗口运行,FA在某些场景下(如半模态FA)会以非全窗口运行,调用该接口会从非全窗口切换为全窗口运行,如果已经以全窗口运行则该接口调用无效。
从API Version 7开始,推荐使用[`@ohos.window`](js-apis-window.md)
**系统能力:** SystemCapability.ArkUI.ArkUI.Full
**参数:**
| 参数名 | 类型 | 必填 | 说明 |
| ------- | ----------------------------------------------------- | ---- | ------------------------------------------------------------ |
| options | [RequestFullWindowOptions](#requestfullwindowoptions) | 否 | 请求全屏时,设定非全屏到全屏的过渡时间,单位为毫秒,默认时间与非全屏到全屏的距离成正比。 |
**示例:**
```ts
export default {
requestFullWindow() {
app.requestFullWindow({
duration: 200
})
}
}
```
## AppResponse
定义AppResponse信息。
......@@ -197,20 +210,6 @@ export default {
| versionName | string | 是 | 表示应用的版本名称。 <br> **系统能力:** SystemCapability.ArkUI.ArkUI.Lite|
| versionCode | number | 是 | 表示应用的版本号。 <br> **系统能力:** SystemCapability.ArkUI.ArkUI.Lite|
## ScreenOnVisible<sup>(deprecated)</sup>
screenOnVisible(options?: ScreenOnVisibleOptions):&nbsp;void
定义屏幕唤醒时是否保持应用可见。
该接口从API Version 8 开始废弃。
**系统能力:** 以下各项对应的系统能力均为SystemCapability.ArkUI.ArkUI.Full
| 名称 | 类型 | 必填 | 说明 |
| -------- | -------- | -------- |-------- |
| options | ScreenOnVisibleOptions | 否 | 当启动保活时,锁屏时将阻止系统返回桌面显示,以保持屏幕唤醒时应用可见。 |
## ScreenOnVisibleOptions
定义屏幕上可见接口的选项。
......
......@@ -2,9 +2,9 @@
创建并显示文本提示框、对话框和操作菜单。
> **说明:**
> **说明:**
>
> - 从API Version 8 开始,该接口不再维护,推荐使用新接口[`@ohos.prompt`](js-apis-prompt.md)。
> - 从API Version 8 开始,该接口不再维护,推荐使用新接口[@ohos.promptAction (弹窗)](js-apis-promptAction.md)。
>
>
> - 本模块首批接口从API version 3开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
......
......@@ -33,7 +33,7 @@ JS文件用来定义HML页面的业务逻辑,支持ECMA规范的JavaScript语
```
import router from '@system.router';
import router from '@ohos.router';
```
- 代码引用
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册