提交 5bb302cf 编写于 作者: W wangshuainan1 提交者: Gitee

Merge branch 'OpenHarmony-3.1-Release' of gitee.com:openharmony/docs into OpenHarmony-3.1-Release

Signed-off-by: Nwangshuainan1 <wangshuainan1@huawei.com>
......@@ -90,9 +90,9 @@ Use the following APIs to delete a **Storage** instance or data file.
context.getFilesDir().then((filePath) => {
path = filePath;
console.info("======================>getFilesDirPromsie====================>");
});
let promise = dataStorage.getStorage(path + '/mystore');
});
```
......@@ -120,14 +120,15 @@ Use the following APIs to delete a **Storage** instance or data file.
```js
promise.then((storage) => {
let getPromise = storage.get('startup', 'default');
let getPromise = storage.get('startup', 'default')
getPromise.then((value) => {
console.info("The value of startup is " + value);
}).catch((err) => {
console.info("Failed to get the value of startup with err: " + err);
})
}).catch((err) => {
console.info("Failed to get the storage.");
console.info("Failed to get the storage.")
})
```
......@@ -149,7 +150,7 @@ Use the following APIs to delete a **Storage** instance or data file.
var observer = function (key) {
console.info("The key of " + key + " changed.");
}
storage.on('change', observer);
storage.on('change', observer)
storage.putSync('startup', 'auto'); // Modify data in the Storage instance.
storage.flushSync(); // Trigger the StorageObserver callback.
......@@ -169,7 +170,7 @@ Use the following APIs to delete a **Storage** instance or data file.
promise.then(() => {
console.info("Succeeded in deleting the storage.");
}).catch((err) => {
console.info("Failed to deleted the storage with err: " + err);
console.info("Failed to delete the storage with err: " + err);
})
```
......@@ -30,7 +30,7 @@ The following table lists the USB APIs currently available. For details, see the
## How to Develop
You can set a USB device as a host to connect to a device for data transfer. The development procedure is as follows:
You can set a USB device as the USB host to connect to other USB devices for data transfer. The development procedure is as follows:
1. Obtain the USB device list.
......
......@@ -141,7 +141,7 @@ Processes an asynchronous function and returns a promise version.
| Name| Type| Readable| Writable| Description|
| -------- | -------- | -------- | -------- | -------- |
| encoding | string | Yes| No| Encoding format.<br>- Supported formats: utf-8, ibm866, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-8-i, iso-8859-10, iso-8859-13, iso-8859-14, iso-8859-15, koi8-r, koi8-u, macintosh, windows-874, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, x-mac-cyrilli, gbk, gb18030, big5, euc-jp, iso-2022-jp, shift_jis, euc-kr, utf-16be, utf-16le|
| encoding | string | Yes| No| Encoding format.<br>- Supported formats: utf-8.|
| fatal | boolean | Yes| No| Whether to display fatal errors.|
| ignoreBOM | boolean | Yes| No| Whether to ignore the byte order marker (BOM). The default value is **false**, which indicates that the result contains the BOM.|
......
......@@ -26,58 +26,30 @@
| -------- | -------- | -------- |
| ohos.sensor | sensor.on(sensorType, callback:AsyncCallback&lt;Response&gt;): void | 持续监听传感器数据变化 |
| ohos.sensor | sensor.once(sensorType, callback:AsyncCallback&lt;Response&gt;): void | 获取一次传感器数据变化 |
| ohos.sensor | sensor.off(sensorType, callback:AsyncCallback&lt;void&gt;): void | 注销传感器数据的监听 |
| ohos.sensor | sensor.off(sensorType, callback?:AsyncCallback&lt;void&gt;): void | 注销传感器数据的监听 |
## 开发步骤
1. 获取设备上传感器的数据,需要在“config.json”里面进行配置请求权限。具体如下:
1. 获取设备上传感器的数据前,需要检查是否已经配置请求相应的权限。 <br>
系统提供的传感器权限有:
- ohos.permission.ACCELEROMETER
```
"reqPermissions":[
{
"name":"ohos.permission.ACCELEROMETER",
"reason":"",
"usedScene":{
"ability": ["sensor.index.MainAbility",".MainAbility"],
"when":"inuse"
}
},
{
"name":"ohos.permission.GYROSCOPE",
"reason":"",
"usedScene":{
"ability": ["sensor.index.MainAbility",".MainAbility"],
"when":"inuse"
}
},
{
"name":"ohos.permission.ACTIVITY_MOTION",
"reason":"ACTIVITY_MOTION_TEST",
"usedScene":{
"ability": ["sensor.index.MainAbility",".MainAbility"],
"when":"inuse"
}
},
{
"name":"ohos.permission.READ_HEALTH_DATA",
"reason":"HEALTH_DATA_TEST",
"usedScene":{
"ability": ["sensor.index.MainAbility",".MainAbility"],
"when":"inuse"
}
},
]
```
- ohos.permission.GYROSCOPE
- ohos.permission.ACTIVITY_MOTION
- ohos.permission.READ_HEALTH_DATA
具体配置方式请参考[权限申请声明](../security/accesstoken-guidelines.md)
2. 持续监听传感器数据变化。
```
import sensor from "@ohos.sensor"
sensor.on(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data){
console.info("Subscription succeeded. data = " + data);//调用成功,打印对应传感器的数据
}
);
import sensor from "@ohos.sensor";
sensor.on(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data){
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,持续监听传感器接口的结果如下图所示:
......@@ -87,11 +59,8 @@
3. 注销传感器数据监听。
```
import sensor from "@ohos.sensor"
sensor.off(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function() {
console.info("Succeeded in unsubscribing from acceleration sensor data.");//注销成功,返回打印结果
}
);
import sensor from "@ohos.sensor";
sensor.off(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER);
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,注销传感器成功结果如下图所示:
......@@ -101,11 +70,10 @@
4. 获取一次传感器数据变化。
```
import sensor from "@ohos.sensor"
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
console.info("Data obtained successfully. data=" + data);//获取数据成功,打印对应传感器的数据
}
);
import sensor from "@ohos.sensor";
sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
```
以SensorType为SENSOR_TYPE_ID_ACCELEROMETER为例展示运行结果,获取数据成功日志如下图所示:
......@@ -115,15 +83,15 @@
若接口调用不成功,建议使用try/catch语句捕获代码中可能出现的错误信息。例如:
```
import sensor from "@ohos.sensor";
try {
sensor.once(sensor.sensorType.SENSOR_TYPE_ACCELEROMETER,function(data) {
console.info("Data obtained successfully. data=" + data);//获取数据成功,打印对应传感器的数据
sensor.once(sensor.SensorType.SENSOR_TYPE_ID_ACCELEROMETER, function(data) {
console.info("Data obtained successfully. x: " + data.x + "y: " + data.y + "z: " + data.z);// 获取数据成功
});
} catch (error) {
console.error(error);
console.error("Get sensor data fail");
}
```
## 相关实例
针对传感器开发,有以下相关实例可供参考:
......
......@@ -8,10 +8,10 @@ OpenHarmony系统传感器是应用访问底层硬件传感器的一种设备抽
| 传感器类型 | 描述 | 说明 | 主要用途 |
| --------------------------------------- | --------- | ---------------------------------------- | -------------------- |
| SENSOR_TYPE_ACCELEROMETER | 加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的加速度(包括重力加速度),单位&nbsp;:&nbsp;m/s2 | 检测运动状态 |
| SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED | 未校准加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的未校准的加速度(包括重力加速度),单位&nbsp;:&nbsp;m/s2 | 检测加速度偏差估值 |
| SENSOR_TYPE_LINEAR_ACCELERATION | 线性加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的线性加速度(不包括重力加速度),单位&nbsp;:&nbsp;m/s2 | 检测每个单轴方向上的线性加速度 |
| SENSOR_TYPE_GRAVITY | 重力传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的重力加速度,单位&nbsp;:&nbsp;m/s2 | 测量重力大小 |
| SENSOR_TYPE_ACCELEROMETER | 加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的加速度(包括重力加速度),单位&nbsp;:&nbsp;m/s² | 检测运动状态 |
| SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED | 未校准加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的未校准的加速度(包括重力加速度),单位&nbsp;:&nbsp;m/s² | 检测加速度偏差估值 |
| SENSOR_TYPE_LINEAR_ACCELERATION | 线性加速度传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的线性加速度(不包括重力加速度),单位&nbsp;:&nbsp;m/s² | 检测每个单轴方向上的线性加速度 |
| SENSOR_TYPE_GRAVITY | 重力传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,施加在设备上的重力加速度,单位&nbsp;:&nbsp;m/s² | 测量重力大小 |
| SENSOR_TYPE_GYROSCOPE | 陀螺仪传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,设备的旋转角速度,单位&nbsp;:&nbsp;rad/s | 测量旋转的角速度 |
| SENSOR_TYPE_GYROSCOPE_UNCALIBRATED | 未校准陀螺仪传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,设备的未校准旋转角速度,单位&nbsp;:&nbsp;rad/s | 测量旋转的角速度及偏差估值 |
| SENSOR_TYPE_SIGNIFICANT_MOTION | 大幅度动作传感器 | 测量三个物理轴(x、y&nbsp;&nbsp;z)上,设备是否存在大幅度运动;如果取值为1则代表存在大幅度运动,取值为0则代表没有大幅度运动 | 用于检测设备是否存在大幅度运动 |
......@@ -60,3 +60,4 @@ OpenHarmony传感器包含如下四个模块:Sensor API、Sensor Framework、S
| 心率计 | ohos.permission.READ_HEALTH_DATA | user_grant | 允许读取健康数据 |
2. 传感器数据订阅和取消订阅接口成对调用,当不再需要订阅传感器数据时,开发者需要调用取消订阅接口停止数据上报。
\ No newline at end of file
......@@ -22,53 +22,18 @@
## 开发步骤
1. 控制设备上的振动器,需要在“config.json”里面进行配置请求权限。具体如下:
```
”reqPermissions“:[
{
"name":"ohos.permission.ACCELEROMETER",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
],
"when":"inuse"
}
},
{
"name":"ohos.permission.VIBRATE",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
],
"when":"inuse"
}
},
{
"name":"ohos.permission.ACTIVITY_MOTION",
"reason"":"",
"usedScene":{
"ability""[
".MainAbility"
],
"when":"inuse"
}
},
]
```
1. 控制设备上的振动器,需要申请权限ohos.permission.VIBRATE。具体配置方式请参考[权限申请声明](../security/accesstoken-guidelines.md)
2. 触发设备振动。
```
import vibrator from "@ohos.vibrator"
vibrator.vibrate(1000).then((error)=>{
if(error){//调用失败,打印error.code和error.message
console.log("Promise return failed.error.code"+error.code+"error.message"+error.message);
}else{//调用成功,设备开始振动
vibrator.vibrate(1000).then((error) => {
if (error) { //调用失败,打印error.code和error.message
console.log("Promise return failed.error.code " + error.code + "error.message " + error.message);
} else { //调用成功,设备开始振动
console.log("Promise returned to indicate a successful vibration.")
};
}
})
```
......@@ -76,12 +41,12 @@
```
import vibrator from "@ohos.vibrator"
vibrator.stop(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET).then((error)=>{
if(error){//调用失败,打印error.code和error.message
console.log("Promise return failed.error.code"+error.code+"error.message"+error.message);
}else{//调用成功,设备停止振动
Console.log("Promise returned to indicate successful.");
};
vibrator.stop(vibrator.VibratorStopMode.VIBRATOR_STOP_MODE_PRESET).then((error) => {
if (error) { //调用失败,打印error.code和error.message
console.log("Promise return failed.error.code " + error.code + "error.message " + error.message);
} else { //调用成功,设备停止振动
console.log("Promise returned to indicate successful.");
}
})
```
......
......@@ -23,7 +23,7 @@ Vibrator属于控制类小器件,主要包含以下四个模块:Vibrator API
## 约束与限制
在使用振动器时,开发者需要配置请求振动器的权限ohos.permission.VIBRATE,才能控制振动器振动,权限类型是system_grant
在使用振动器时,开发者需要配置请求振动器的权限ohos.permission.VIBRATE,才能控制振动器振动。
......@@ -140,7 +140,7 @@ promiseWrapper(original: (err: Object, value: Object) =&gt; void): Object
| 名称 | 参数类型 | 可读 | 可写 | 说明 |
| -------- | -------- | -------- | -------- | -------- |
| encoding | string | 是 | 否 | 编码格式。<br/>-&nbsp;支持格式:utf-8、ibm866、iso-8859-2、iso-8859-3、iso-8859-4、iso-8859-5、iso-8859-6、iso-8859-7、iso-8859-8、iso-8859-8-i、iso-8859-10、iso-8859-13、iso-8859-14、iso-8859-15、koi8-r、koi8-u、macintosh、windows-874、windows-1250、windows-1251、windows-1252、windows-1253、windows-1254、windows-1255、windows-1256、windows-1257、windows-1258、x-mac-cyrilli、gbk、gb18030、big5、euc-jp、iso-2022-jp、shift_jis、euc-kr、utf-16be、utf-16le。 |
| encoding | string | 是 | 否 | 编码格式。<br/>-&nbsp;支持格式:utf-8。 |
| fatal | boolean | 是 | 否 | 是否显示致命错误。 |
| ignoreBOM | boolean | 是 | 否 | 是否忽略BOM(byte&nbsp;order&nbsp;marker)标记,默认值为false&nbsp;,表示解码结果包含BOM标记。 |
......
......@@ -43,17 +43,10 @@
| icon-height | &lt;length&gt; | - | 否 | 设置圆形按钮内部图标的高,默认填满整个圆形按钮。<br/>>&nbsp;![icon-note.gif](public_sys-resources/icon-note.gif)&nbsp;**说明:**<br/>>&nbsp;icon使用svg图源时必须设置该样式。 |
| radius | &lt;length&gt; | - | 否 | 按钮圆角半径。在圆形按钮类型下该样式优先于通用样式的width和height样式。 |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> - 胶囊按钮(type=capsule)时,不支持border相关样式;
>
> - 圆形按钮(type=circle)时,不支持文本相关样式;
>
> - 文本按钮(type=text)时,自适应文本大小,不支持尺寸设置(radius,width,height),背景透明不支持background-color样式。
### type设置为arc
除支持[通用样式](../arkui-js/js-components-common-styles.md)中background-color、opacity、display、visibility、position、[left|top|right|bottom外,还支持如下样式:
除支持[通用样式](../arkui-js/js-components-common-styles.md)中background-color、opacity、display、visibility、position、[left|top|right|bottom]外,还支持如下样式:
| 名称 | 类型 | 默认值 | 必填 | 描述 |
| -------- | -------- | -------- | -------- | -------- |
......
......@@ -127,7 +127,8 @@ import prompt from '@system.prompt';
export default {
data: {
direction: 'column',
list: []
list: [],
listAdd: []
},
onInit() {
this.list = []
......
......@@ -95,6 +95,7 @@
height: 300px;
}
.stepperItem {
width: 100%;
flex-direction: column;
align-items: center;
}
......
......@@ -32,25 +32,32 @@ LongPressGesture(value?: { fingers?: number, repeat?: boolean, duration?: number
@Entry
@Component
struct LongPressGestureExample {
@State count: number = 0
@State count: number = 0;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Text('LongPress onAction:' + this.count)
}
.height(200).width(300).padding(60).border({ width:1 }).margin(30)
Column() {
Text('LongPress onAction:' + this.count).fontSize(28)
// 单指长按文本触发该手势事件
.gesture(
LongPressGesture({ repeat: true })
//长按动作存在会连续触发
// 由于repeat设置为true,长按动作存在时会连续触发,触发间隔为duration(默认值500ms)
.onAction((event: GestureEvent) => {
if (event.repeat) { this.count++ }
if (event.repeat) {
this.count++;
}
})
//长按动作一结束触发
// 长按动作一结束触发
.onActionEnd(() => {
this.count = 0
this.count = 0;
})
)
}
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
.margin(30)
}
}
```
......
......@@ -20,16 +20,16 @@ PanGesture(value?: { fingers?: number, direction?: PanDirection, distance?: numb
## PanDirection枚举说明
| 名称 | 描述 |
| -------- | -------- |
| All | 所有方向。 |
| Horizontal | 水平方向。 |
| Vertical | 竖直方向。 |
| Left | 向左拖动。 |
| Right | 向右拖动。 |
| Up | 向上拖动。 |
| Down | 向下拖动。 |
| None | 任何方向都不可触发拖动手势事件。 |
| 名称 | 描述 |
| -------- | -------- |
| All | 所有方向。 |
| Horizontal | 水平方向。 |
| Vertical | 竖直方向。 |
| Left | 向左拖动。 |
| Right | 向右拖动。 |
| Up | 向上拖动。 |
| Down | 向下拖动。 |
| None | 任何方向都不可触发拖动手势事件。 |
## PanGestureOptions
......@@ -44,11 +44,11 @@ PanGestureOptions(options?: { fingers?: number, direction?: PanDirection, distan
**接口:**
| 名称 | 功能描述 |
| -------- | -------- |
| setDirection(value:&nbsp;PanDirection) | 设置direction属性。 |
| setDistance(value:&nbsp;number) | 设置distance属性。 |
| setFingers(value:&nbsp;number) | 设置fingers属性。 |
| 名称 | 功能描述 |
| -------- | -------- |
| setDirection(value:&nbsp;PanDirection) | 设置direction属性。 |
| setDistance(value:&nbsp;number) | 设置distance属性。 |
| setFingers(value:&nbsp;number) | 设置fingers属性。 |
## 事件
......@@ -68,30 +68,57 @@ PanGestureOptions(options?: { fingers?: number, direction?: PanDirection, distan
@Entry
@Component
struct PanGestureExample {
@State offsetX: number = 0
@State offsetY: number = 0
@State offsetX: number = 0;
@State offsetY: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Left | PanDirection.Right });
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Column() {
Column() {
Text('PanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
}
.height(100).width(200).padding(20).border({ width: 1 }).margin(80)
.translate({ x: this.offsetX, y: this.offsetY, z: 5 })
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
.margin(50)
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
// 左右拖动触发该手势事件
.gesture(
PanGesture({})
PanGesture(this.panOption)
.onActionStart((event: GestureEvent) => {
console.info('Pan start')
console.info('Pan start');
})
.onActionUpdate((event: GestureEvent) => {
this.offsetX = event.offsetX
this.offsetY = event.offsetY
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
})
.onActionEnd(() => {
console.info('Pan end')
this.positionX = this.offsetX;
this.positionY = this.offsetY;
console.info('Pan end');
})
)
Button('修改PanGesture触发条件')
.onClick(() => {
// 将PanGesture手势事件触发条件改为双指以任意方向拖动
this.panOption.setDirection(PanDirection.All);
this.panOption.setFingers(2);
})
}
}
}
```
![zh-cn_image_0000001174264374](figures/zh-cn_image_0000001174264374.gif)
示意图:
向左拖动:
![zh-cn_image_0000001174264374](figures/zh-cn_image_0000001174264374.png)
点击按钮修改PanGesture触发条件,双指向左下方拖动:
![zh-cn_image1_0000001174264374](figures/zh-cn_image1_0000001174264374.png)
\ No newline at end of file
......@@ -32,28 +32,42 @@ PinchGesture(value?: { fingers?: number, distance?: number })
@Entry
@Component
struct PinchGestureExample {
@State scaleValue: number = 1
@State scaleValue: number = 1;
@State pinchValue: number = 1;
@State pinchX: number = 0;
@State pinchY: number = 0;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Text('PinchGesture scale:' + this.scale)
Column() {
Column() {
Text('PinchGesture scale:\n' + this.scaleValue)
Text('PinchGesture center:\n(' + this.pinchX + ',' + this.pinchY + ')')
}
.height(100).width(200).padding(20).border({ width: 1 }).margin(80)
.scale({ x: this.scaleValue, y: this.scaleValue, z: this.scaleValue })
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
.margin({ top: 100 })
.scale({ x: this.scaleValue, y: this.scaleValue, z: 1 })
// 三指捏合触发该手势事件
.gesture(
PinchGesture()
PinchGesture({ fingers: 3 })
.onActionStart((event: GestureEvent) => {
console.info('Pinch start')
console.info('Pinch start');
})
.onActionUpdate((event: GestureEvent) => {
this.scaleValue = event.scale
this.scaleValue = this.pinchValue * event.scale;
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
})
.onActionEnd(() => {
console.info('Pinch end')
this.pinchValue = this.scaleValue;
console.info('Pinch end');
})
)
}.width('100%')
}
}
```
![zh-cn_image_0000001174582848](figures/zh-cn_image_0000001174582848.gif)
![zh-cn_image_0000001174582848](figures/zh-cn_image_0000001174582848.png)
......@@ -32,28 +32,37 @@ RotationGesture(value?: { fingers?: number, angle?: number })
@Entry
@Component
struct RotationGestureExample {
@State angle: number = 0
@State angle: number = 0;
@State rotateValue: number = 0;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Column() {
Column() {
Text('RotationGesture angle:' + this.angle)
}
.height(100).width(200).padding(20).border({ width:1 })
.margin(80).rotate({ x:1, y:2, z:3, angle: this.angle })
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
.margin(80)
.rotate({ angle: this.angle })
// 双指旋转触发该手势事件
.gesture(
RotationGesture()
.onActionStart((event: GestureEvent) => {
console.log('Rotation start')
console.info('Rotation start');
})
.onActionUpdate((event: GestureEvent) => {
this.angle = event.angle
this.angle = this.rotateValue + event.angle;
})
.onActionEnd(() => {
console.log('Rotation end')
this.rotateValue = this.angle;
console.info('Rotation end');
})
)
}.width('100%')
}
}
```
![zh-cn_image_0000001174264372](figures/zh-cn_image_0000001174264372.gif)
![zh-cn_image_0000001174264372](figures/zh-cn_image_0000001174264372.png)
......@@ -32,8 +32,6 @@ SwipeGesture(value?: { fingers?: number; direction?: SwipeDirection; speed?: num
| -------- | -------- |
| onAction(event:(event?:&nbsp;[GestureEvent](ts-gesture-settings.md))&nbsp;=&gt;&nbsp;void) | 滑动手势识别成功回调。 |
![zh-cn_image_0000001231374559](figures/zh-cn_image_0000001231374661.png)
## 示例
```ts
......@@ -41,27 +39,31 @@ SwipeGesture(value?: { fingers?: number; direction?: SwipeDirection; speed?: num
@Entry
@Component
struct SwipeGestureExample {
@State rotateAngle : number = 0
@State speed : number = 1
@State rotateAngle: number = 0;
@State speed: number = 1;
build() {
Column() {
Text("SwipGesture speed : " + this.speed)
Text("SwipGesture angle : " + this.rotateAngle)
Column() {
Text("SwipeGesture speed\n" + this.speed)
Text("SwipeGesture angle\n" + this.rotateAngle)
}
.position({x: 80, y: 200})
.border({width:2})
.width(260).height(260)
.rotate({x: 0, y: 0, z: 1, angle: this.rotateAngle})
.border({ width: 3 })
.width(300)
.height(200)
.margin(100)
.rotate({ angle: this.rotateAngle })
// 单指竖直方向滑动时触发该事件
.gesture(
SwipeGesture({fingers: 1, direction: SwipeDirection.Vertical})
SwipeGesture({ direction: SwipeDirection.Vertical })
.onAction((event: GestureEvent) => {
this.speed = event.speed
this.rotateAngle = event.angle
this.speed = event.speed;
this.rotateAngle = event.angle;
})
)
}.width('100%')
}
}
```
![zh-cn_image_0000001231374559](figures/zh-cn_image_0000001231374559.gif)
![zh-cn_image_0000001231374559](figures/zh-cn_image_0000001231374559.png)
......@@ -29,20 +29,25 @@ TapGesture(value?: { count?: number, fingers?: number })
@Entry
@Component
struct TapGestureExample {
@State value: string = ''
@State value: string = '';
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Text('Click twice')
Text(this.value)
}
.height(200).width(300).padding(60).border({ width: 1 }).margin(30)
Column() {
// 单指双击文本触发手势事件
Text('Click twice').fontSize(28)
.gesture(
TapGesture({ count: 2 })
.onAction(() => {
this.value = 'TapGesture onAction'
.onAction((event: GestureEvent) => {
this.value = JSON.stringify(event.fingerList[0]);
})
)
Text(this.value)
}
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
.margin(30)
}
}
```
......
......@@ -43,43 +43,67 @@ GestureGroup(mode: GestureMode, ...gesture: GestureType[])
@Entry
@Component
struct GestureGroupExample {
@State count: number = 0
@State offsetX: number = 0
@State offsetY: number = 0
@State borderStyles: BorderStyle = BorderStyle.Solid
@State count: number = 0;
@State offsetX: number = 0;
@State offsetY: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
@State borderStyles: BorderStyle = BorderStyle.Solid;
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.SpaceBetween }) {
Column() {
Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
}.translate({ x: this.offsetX, y: this.offsetY, z: 5 })
.height(100).width(200).padding(10).margin(80).border({ width: 1, style: this.borderStyles })
}
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.height(150)
.width(200)
.padding(20)
.margin(20)
.border({ width: 3, style: this.borderStyles })
.gesture(
//以下组合手势为顺序识别,当长按手势事件未正常触发时则不会触发拖动手势事件
GestureGroup(GestureMode.Sequence,
LongPressGesture({ repeat: true })
.onAction((event: GestureEvent) => {
if (event.repeat) {this.count++}
console.log('LongPress onAction')
if (event.repeat) {
this.count++;
}
console.info('LongPress onAction');
})
.onActionEnd(() => {
console.log('LongPress end')
console.info('LongPress end');
}),
PanGesture({})
PanGesture()
.onActionStart(() => {
this.borderStyles = BorderStyle.Dashed
console.log('pan start')
this.borderStyles = BorderStyle.Dashed;
console.info('pan start');
})
.onActionUpdate((event: GestureEvent) => {
this.offsetX = event.offsetX
this.offsetY = event.offsetY
console.log('pan update')
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
console.info('pan update');
})
.onActionEnd(() => {
this.positionX = this.offsetX;
this.positionY = this.offsetY;
this.borderStyles = BorderStyle.Solid;
console.info('pan end');
})
)
.onCancel(() => {
console.log('sequence gesture canceled')
console.info('sequence gesture canceled');
})
)
}
}
```
![zh-cn_image_0000001174104384](figures/zh-cn_image_0000001174104384.gif)
示意图:
按顺序首先触发长按事件:
![zh-cn_image_0000001174104384](figures/zh-cn_image_0000001174104384.png)
按顺序首先触发长按事件,长按事件识别结束之后,其次触发拖动事件,向右下方拖动:
![zh-cn_image1_0000001174104384](figures/zh-cn_image1_0000001174104384.png)
\ No newline at end of file
......@@ -243,7 +243,6 @@ struct FlexExample4 {
![zh-cn_image_0000001174422904](figures/zh-cn_image_0000001174422904.jpg)
![zh-cn_image_0000001219662653](figures/zh-cn_image_0000001219662653.gif)
```
// Example 05
......
......@@ -43,7 +43,7 @@
## 响应手势事件
组件通过gesture方法绑定手势对象,可以通过手势对象提供的事件相应响应手势操作。例如通过TapGesture对象的onAction事件响应点击事件。其余手势的事件定义见各个手势对象章节。
组件通过gesture方法绑定手势对象,可以通过手势对象提供的事件相应响应手势操作。例如通过TapGesture对象的onAction事件响应点击事件。其余手势的事件定义见各个手势对象章节。若需绑定多种手势请使用 [组合手势](ts-combined-gestures.md)
- TapGesture事件说明
| 名称 | 功能描述 |
......@@ -77,8 +77,8 @@
| 名称 | 类型 | 描述 |
| -------- | -------- | -------- |
| id | number | 手指的索引编号。 |
| globalX | number | 相对于设备屏幕左上角的x轴坐标。 |
| globalY | number | 相对于设备屏幕左上角的y轴坐标。 |
| globalX | number | 相对于应用窗口左上角的x轴坐标。 |
| globalY | number | 相对于应用窗口左上角的y轴坐标。 |
| localX | number | 相对于当前组件元素左上角的x轴坐标。 |
| localY | number | 相对于当前组件元素左上角的y轴坐标。 |
......@@ -90,28 +90,51 @@
@Entry
@Component
struct GestureSettingsExample {
@State value: string = ''
@State priorityTestValue: string = '';
@State parallelTestValue: string = '';
build() {
Column(){
Column() {
Text('Click\n' + this.value)
Column() {
Text('TapGesture:' + this.priorityTestValue).fontSize(28)
.gesture(
TapGesture()
.onAction(() => {
this.value = 'gesture onAction'
this.priorityTestValue += '\nText';
}))
}.height(200).width(300).padding(60).border({ width: 1 })
//设置为priorityGesture时,会优先识别该绑定手势忽略内部gesture手势
}
.height(200)
.width(250)
.padding(20)
.margin(20)
.border({ width: 3 })
// 设置为priorityGesture时,点击文本会忽略Text组件的TapGesture手势事件,优先识别父组件Column的TapGesture手势事件
.priorityGesture(
TapGesture()
.onAction((event: GestureEvent) => {
this.value = 'priorityGesture onAction' + '\ncomponent globalPos:('
+ event.target.area.globalPosition.x + ',' + event.target.area.globalPosition.y + ')\nwidth:'
+ event.target.area.width + '\nheight:' + event.target.area.height
}), GestureMask.IgnoreInternal
)
}.padding(60)
this.priorityTestValue += '\nColumn';
}), GestureMask.IgnoreInternal)
Column() {
Text('TapGesture:' + this.parallelTestValue).fontSize(28)
.gesture(
TapGesture()
.onAction(() => {
this.parallelTestValue += '\nText';
}))
}
.height(200)
.width(250)
.padding(20)
.margin(20)
.border({ width: 3 })
// 设置为parallelGesture时,点击文本会同时触发子组件Text与父组件Column的TapGesture手势事件
.parallelGesture(
TapGesture()
.onAction((event: GestureEvent) => {
this.parallelTestValue += '\nColumn';
}), GestureMask.Normal)
}
}
}
```
......
......@@ -155,7 +155,7 @@ setCurrentTime(value: number, seekMode: SeekMode)
@Entry
@Component
struct VideoCreateComponent {
@State srcs: Resource = $rawfile('video1');
@State srcs: Resource = $rawfile('video1.mp4');
@State previewUris: Resource = $r('app.media.img');
@State currentProgressRates: number = 1;
@State autoPlays: boolean = false;
......@@ -197,7 +197,7 @@ struct VideoCreateComponent {
})
Row() {
Button("src").onClick(() => {
this.srcs = $rawfile('video2');
this.srcs = $rawfile('video2.mp4');
});
Button("previewUri").onClick(() => {
this.previewUris = $r('app.media.img1');
......
......@@ -69,7 +69,7 @@
| 类型 | 说明 |
| -------- | -------- |
| and | 将多个媒体特征(Media&nbsp;Feature)以“与”的方式连接成一个媒体查询,只有当所有媒体特征都为true,查询条件成立。另外,它还可以将媒体类型和媒体功能结合起来。<br/>例如:screen&nbsp;and&nbsp;(device-type:&nbsp;wearable)&nbsp;and&nbsp;(max-height:&nbsp;600)&nbsp;表示当设备类型是智能穿戴同时应用的最大高度小于等于600个像素单位时成立。 |
| and | 将多个媒体特征(Media&nbsp;Feature)以逻辑运算符“与”的方式连接成一个媒体查询,只有当所有媒体特征都为true,查询条件成立。另外,它还可以将媒体类型和媒体功能结合起来。<br/>例如:screen&nbsp;and&nbsp;(device-type:&nbsp;wearable)&nbsp;and&nbsp;(max-height:&nbsp;600)&nbsp;表示当设备类型是智能穿戴同时应用的最大高度小于等于600个像素单位时成立。 |
| not | 取反媒体查询结果,媒体查询结果不成立时返回true,否则返回false。在媒体查询列表中应用not,则not仅取反应用它的媒体查询。<br/>例如:not&nbsp;screen&nbsp;and&nbsp;(min-height:&nbsp;50)&nbsp;and&nbsp;(max-height:&nbsp;600)&nbsp;表示当应用高度小于50个像素单位或者大于600个像素单位时成立。<br/>使用not运算符时必须指定媒体类型。 |
| only | 当整个表达式都匹配时,才会应用选择的样式,可以应用在防止某些较早的版本的浏览器上产生歧义的场景。一些较早版本的浏览器对于同时包含了媒体类型和媒体特征的语句会产生歧义,比如:<br/>screen&nbsp;and&nbsp;(min-height:&nbsp;50)<br/>老版本浏览器会将这句话理解成screen,从而导致仅仅匹配到媒体类型(screen),就应用了指定样式,使用only可以很好地规避这种情况。<br/>使用only时必须指定媒体类型。 |
| ,(comma) | 将多个媒体特征以“或”的方式连接成一个媒体查询,如果存在结果为true的媒体特征,则查询条件成立。其效果等同于or运算符。<br/>例如:screen&nbsp;and&nbsp;(min-height:&nbsp;1000),&nbsp;&nbsp;(round-screen:true)&nbsp;表示当应用高度大于等于1000个像素单位或者设备屏幕是圆形时,条件成立。 |
......
......@@ -7,7 +7,6 @@
- 文件组织
- [目录结构](ts-framework-directory.md)
- [应用代码文件访问规则](ts-framework-file-access-rules.md)
- [js标签配置](ts-framework-js-tag.md)
- 资源管理
- [资源文件的分类](ui-ts-basic-resource-file-categories.md)
- [资源访问](ts-resource-access.md)
......
# CSS语法参考
CSS是描述HML页面结构的样式语言。所有组件均存在系统默认样式,也可在页面CSS样式文件中对组件、页面自定义不同的样式。请参考[通用样式](../reference/arkui-js/js-components-common-styles.md)了解基于JS扩展的类Web开发范式支持的组件样式。
CSS是描述HML页面结构的样式语言。所有组件均存在系统默认样式,也可在页面CSS样式文件中对组件、页面自定义不同的样式。请参考[通用样式](../reference/arkui-js/js-components-common-styles.md)了解兼容JS的类Web开发范式支持的组件样式。
## 尺寸单位
......
......@@ -29,3 +29,12 @@ FA应用的eTS模块(entry/src/main)的典型开发目录结构如下:
> - 资源目录resources文件夹位于src/main下,此目录下资源文件的详细规范以及子目录结构规范参看[资源文件的分类](ui-ts-basic-resource-file-categories.md)。
>
> - 页面支持导入TypeScript和JavaScript文件。
**js标签配置:**
开发框架需要在配置文件中标识相关的js标签,其中的每个元素代表一个JS模块的信息,包含了实例名称、页面路由、视图窗口等。
> **说明:**
>
> FA模型请参考 [表22 js对象的内部结构说明](../quick-start/package-structure.md#module对象的内部结构)。
\ No newline at end of file
# js标签配置
开发框架需要应用的config.json中配置相关的js标签,其中包含了实例名称、页面路由、视图窗口配置信息。
| 标签 | 类型 | 默认值 | 必填 | 描述 |
| -------- | -------- | -------- | -------- | -------- |
| name | string | default | 是 | 标识ETS实例的名字。 |
| pages | Array | - | 是 | 页面路由信息,详见[pages](#pages)说明。 |
| window | Object | - | 否 | 视图窗口配置信息,详见[window](#window)说明。 |
| mode | Object | - | 否 | 配置Js&nbsp;Component运行类型与语法风格,详见[mode](#mode)说明。 |
## pages
定义每个页面入口组件的路由信息,每个页面由页面路径和页面名组成,页面的文件名就是页面名。比如:
```
{
"pages": [
"pages/index",
"pages/detail"
]
}
```
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> - pages列表中第一个页面为应用的首页入口。
>
> - 页面文件名不能使用组件名称,比如:Text.ets、Button.ets等。
>
> - 每个页面文件中必须包含[页面入口组件](../ui/ts-component-based-entry.md)(\@Entry装饰)。
## window
window用于配置相关视图显示窗口,支持配置如下属性:
| 类型 | 默认值 | 说明 |
| -------- | -------- | -------- |
| designWidth | - | 配置视图显示的逻辑宽度,缺省默认720(智能穿戴默认454)。视图显示的逻辑宽度决定了lpx像素单位大小,如designWidth配置720时,在视图宽度为1440物理像素时,1lpx为2物理像素。详见[lpx像素单位](../ui/ts-pixel-units.md)说明。 |
```
{
...
"window": {
"designWidth": 720
}
...
}
```
## mode
mode用于配置JS Component的运行类型与语法风格,支持如下属性:
| 类型 | 默认值 | 说明 |
| -------- | -------- | -------- |
| type | - | 配置该JS&nbsp;Component的运行类型,可选值为:<br/>-&nbsp;pageAbility:以ability的方式运行该JS&nbsp;Component。<br/>-&nbsp;form:以卡片的方式运行该JS&nbsp;Component。 |
| syntax | - | 配置该JS&nbsp;Component的语法风格,可选值为:<br/>-&nbsp;hml:以hml/css/js风格进行编写。<br/>-&nbsp;ets:以声明式语法风格进行编写。 |
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> 不支持同时配置type类型为form,syntax类型为ets。
## 示例
config.json:
```
{
"app": {
"bundleName": "com.example.player",
"version": {
"code": 1,
"name": "1.0"
},
"vendor": "example"
},
"module": {
"js": [{
"name": "default",
"pages": [
"pages/index",
"pages/detail"
],
"window": {
"designWidth": 720
},
"mode": {
"type": "pageAbility",
"syntax": "ets"
},
}],
"abilities": [{
...
}]
}
}
```
# 基本概念
基于TS扩展的声明式开发范式提供了一系列基础组件,这些组件以声明方式进行组合和扩展来描述应用程序的UI界面,并且还提供了基本的数据绑定和事件处理机制,帮助开发者实现应用交互逻辑。
基于eTS的声明式开发范式提供了一系列基础组件,这些组件以声明方式进行组合和扩展来描述应用程序的UI界面,并且还提供了基本的数据绑定和事件处理机制,帮助开发者实现应用交互逻辑。
## HelloWorld基本示例
......
......@@ -74,13 +74,7 @@ Button是按钮组件,其类型包括胶囊按钮、圆形按钮、文本按
> ![icon-note.gif](public_sys-resources/icon-note.gif) **说明:**
> - 胶囊按钮(type=capsule)不支持border相关样式。
>
> - 圆形按钮(type=circle)不支持文本相关样式。
>
> - 文本按钮(type=text),自适应文本大小,不支持尺寸样式设置(radius,width,height),背景透明不支持background-color样式。
>
> - Button组件使用的icon图标如果来自云端路径,需要添加网络访问权限 ohos.permission.INTERNET。
> - Button组件使用的icon图标如果来自云端路径,需要添加网络访问权限 ohos.permission.INTERNET。具体申请方式请参考[权限申请声明](../../security/accesstoken-guidelines.md)。
如果需要添加ohos.permission.INTERNET权限,则在resources文件夹下的config.json文件里进行权限配置。
......
......@@ -132,7 +132,7 @@ export default {
<div class="page-container">
<div class="content">
<div class="image-container">
<image class="testimage" src="{{testuri}}" style="display:{{displaytype}};opacity:{{imageopacity}};" onclick="changedisplaytype" onlongpress="changeopacity"> </image>
<image class="testimage" src="{{testuri}}" style="opacity:{{imageopacity}};" onlongpress="changeopacity"> </image>
</div>
<div class="text-container">
<text style="font-size: 37px;font-weight:bold;color:orange;text-align: center;width: 100%;">Touch and hold the image</text>
......
......@@ -11,7 +11,7 @@ Picker是滑动选择器组件,类型支持普通选择器、日期选择器
<!-- index.hml -->
<div class="container">
<picker> picker </picker>
<div>
</div>
```
```
......
# 自定义组件
使用基于JS扩展的类Web开发范式的方舟开发框架支持自定义组件,用户可根据业务需求将已有的组件进行扩展,增加自定义的私有属性和事件,封装成新的组件,方便在工程中多次调用,提高页面布局代码的可读性。具体的封装方法示例如下:
使用兼容JS扩展的类Web开发范式的方舟开发框架支持自定义组件,用户可根据业务需求将已有的组件进行扩展,增加自定义的私有属性和事件,封装成新的组件,方便在工程中多次调用,提高页面布局代码的可读性。具体的封装方法示例如下:
- 构建自定义组件
......
# 概述
基于TS扩展的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。
基于eTS的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。
## 基础能力
使用基于TS扩展的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。
使用基于eTS的声明式开发范式的方舟开发框架,采用更接近自然语义的编程方式,让开发者可以直观地描述UI界面,不必关心框架如何实现UI绘制和渲染,实现极简高效开发。开发框架不仅从组件、动效和状态管理三个维度来提供UI能力,还提供了系统能力接口,实现系统能力的极简调用。
请参考[基于TS扩展的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解组件,更好地开发应用。
请参考[基于eTS的声明式开发范式API](../reference/arkui-ts/ts-universal-events-click.md)文档,全面地了解组件,更好地开发应用。
- **开箱即用的组件**
......@@ -22,12 +22,12 @@
- **状态与数据管理**
状态数据管理作为基于TS扩展的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。
状态数据管理作为基于eTS的声明式开发范式的特色,通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。状态管理包括UI组件状态和应用程序状态,两者协作可以使开发者完整地构建整个应用的数据更新和UI渲染。
- **系统能力接口**
使用基于TS扩展的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。
使用基于eTS的声明式开发范式的方舟开发框架,还封装了丰富的系统能力接口,开发者可以通过简单的接口调用,实现从UI设计到系统能力调用的极简开发。
## 整体架构
......@@ -59,7 +59,7 @@
## 相关实例
基于TS扩展的声明式开发范式的方舟开发框架,有以下相关实例可供参考:
基于eTS的声明式开发范式的方舟开发框架,有以下相关实例可供参考:
- [`Canvas`:画布组件(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Canvas)
......@@ -73,7 +73,7 @@
- [`Gallery`:组件集合(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/Gallery)
- [`BringApp`:拉起系统应用(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BringApp)
- [`BringApp`:拉起系统应用(eTS)(API8)(Full SDK)](https://gitee.com/openharmony/applications_app_samples/tree/master/ETSUI/BringApp)
- [`Chat`:聊天示例应用(eTS)(API8)](https://gitee.com/openharmony/applications_app_samples/tree/master/AppSample/Chat)
......
......@@ -34,13 +34,12 @@
- [测试框架使用指导](ability/ability-delegator.md)
- UI开发
- [方舟开发框架(ArkUI)概述](ui/arkui-overview.md)
- 基于TS扩展的声明式开发范式
- 基于eTS的声明式开发范式
- [概述](ui/ui-ts-overview.md)
- 框架说明
- 文件组织
- [目录结构](ui/ts-framework-directory.md)
- [应用代码文件访问规则](ui/ts-framework-file-access-rules.md)
- [js标签配置](ui/ts-framework-js-tag.md)
- 资源管理
- [资源文件的分类](ui/ui-ts-basic-resource-file-categories.md)
- [资源访问](ui/ts-resource-access.md)
......@@ -104,7 +103,7 @@
- [构建食物分类Grid布局](ui/ui-ts-building-category-grid-layout.md)
- [页面跳转与数据传递](ui/ui-ts-page-redirection-data-transmission.md)
- [性能提升的推荐方案](ui/ts-performance-improvement-recommendation.md)
- 基于JS扩展的类Web开发范式
- 兼容JS的类Web开发范式
- [概述](ui/ui-js-overview.md)
- 框架说明
- [文件组织](ui/js-framework-file.md)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册