框架说明
文件组织
目录结构
JS FA 应用的 JS 模块(entry/src/main/js/module)的典型开发目录结构如下:
图 1 目录结构
目录结构中文件分类如下:
- .html 结尾的 HTML 模板文件,这个文件用来描述当前页面的文件布局结构。
- .css 结尾的 CSS 样式文件,这个文件用于描述页面样式。
- .js 结尾的 JS 文件,这个文件用于处理页面和用户的交互。
各个文件夹的作用:
- app.js 文件用于全局 JavaScript 逻辑和应用生命周期管理。
- pages 目录用于存放所有组件页面。
- common 目录用于存放公共资源文件,比如:媒体资源和 JS 文件。
- i18n 目录用于配置不同语言场景资源内容,比如应用文本词条,图片路径等资源。
WARNING
i18n 是开发保留文件夹,不可重命名。
文件访问规则
应用资源可通过绝对路径或相对路径的方式进行访问,本开发框架中绝对路径以"/"开头,相对路径以"./"或"../"。具体访问规则如下:
- 引用代码文件,需使用相对路径,比如:../common/utils.js。
- 引用资源文件,推荐使用绝对路径。比如:/common/xxx.png。
- 公共代码文件和资源文件推荐放在 common 下,通过以上两条规则进行访问。
- CSS 样式文件中通过 url()函数创建
<url>
数据类型,如:url(/common/xxx.png)。
提示:
当代码文件 A 需要引用代码文件 B 时:
- 如果代码文件 A 和文件 B 位于同一目录,则代码文件 B 引用资源文件时可使用相对路径,也可使用绝对路径。
- 如果代码文件 A 和文件 B 位于不同目录,则代码文件 B 引用资源文件时必须使用绝对路径。因为 Webpack 打包时,代码文件 B 的目录会发生变化。
媒体文件格式
表 1 支持的图片格式
格式 | 支持版本 | 支持的文件类型 |
---|---|---|
BMP | API Version 3+ | .bmp |
JPEG | API Version 3+ | .jpg |
PNG | API Version 3+ | .jpg |
存储目录定义
应用使用文件存储接口访问文件时,可以通过使用特定 scheme(只支持 internal)来访问预定义的一些文件存取目录。不同设备上对应的实际位置不同。对于不在下列目录下的文件访问将被拒绝(禁止使用../等方式访问父目录)。
image 组件支持应用私有目录内的图片资源访问。5+
目录类型 | 路径前缀 | 访问可见性 | 说明 |
---|---|---|---|
应用私有目录 | internal://app/ | 仅本应用可见 | 随应用卸载删除。 |
js 标签配置
js 标签中包含了实例名称、页面路由信息。
标签 | 类型 | 默认值 | 必填 | 描述 |
---|---|---|---|---|
name | string | default | 是 | 标识 JS 实例的名字。 |
pages | Array | - | 是 | 路由信息,详见“pages”。 |
提示:
name、pages 标签配置需在配置文件中的“js”标签中完成设置。
pages
定义每个页面的路由信息,每个页面由页面路径和页面名组成,页面的文件名就是页面名。比如:
{
...
"pages": [
"pages/index/index",
"pages/detail/detail"
]
...
}
提示:
- 应用首页固定为"pages/index/index"。
- 页面文件名不能使用组件名称,比如:text.html、button.html 等。
示例
{
"app": {
"bundleName": "com.Xiaomi Watch.player",
"version": {
"code": 1,
"name": "1.0"
},
"vendor": "example"
}
"module": {
...
"js": [
{
"name": "default",
"pages": [
"pages/index/index",
"pages/detail/detail"
]
}
],
"abilities": [
{
...
}
]
}
}
app.js
每个应用可以在 app.js 自定义应用级生命周期的实现逻辑,包括:
- onCreate:在应用生成时被调用的生命周期函数。
- onDestory:在应用销毁时被调用的生命周期函数。
以下示例仅在生命周期函数中打印对应日志:
// app.js
export default {
onCreate() {
console.info("Application onCreate");
},
onDestroy() {
console.info("Application onDestroy");
},
};
多语言支持
基于开发框架的应用会覆盖多个国家和地区,开发框架支持多语言能力后,可以让应用开发者无需开发多个不同语言的版本,就可以同时支持多种语言的切换,为项目维护带来便利。
开发者仅需要通过定义资源文件和引用资源两个步骤,就可以使用开发框架的多语言能力;如果需要在应用中获取当前系统语言,请参考获取语言。
定义资源文件
资源文件用于存放应用在多种语言场景下的资源内容,开发框架使用 JSON 文件保存资源定义。
在文件组织中指定的 i18n 文件夹内放置每个语言地区下的资源定义文件即可,资源文件命名为“语言-地区.json”格式,例如英文(美国)的资源文件命名为 en-US.json。当开发框架无法在应用中找到系统语言的资源文件时,默认使用 en-US.json 中的资源内容。
资源文件内容格式如下:
en-US.json
{
"strings": {
"hello": "Hello world!",
"object": "Object parameter substitution-{name}",
"array": "Array type parameter substitution-{0}",
"symbol": "@#$%^&*()_+-={}[]\\|:;\"'<>,./?"
},
"files": {
"image": "image/en_picture.PNG"
}
}
引用资源
在应用中使用$t方法引用资源,$t 既可以在 html 中使用,也可以在 js 中使用。系统将根据当前语言环境和指定的资源路径(通过$t 的 path 参数设置),显示对应语言的资源文件中的内容。
表 1 $t 参数说明
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
path | string | 是 | 资源路径 |
params | Array | 否 | 运行时用来替换占位符的实际内容,占位符分为两种: 具名占位符,例如{name}。实际内容必须用 Object 类型指定,例如:$t('strings.object', { name: 'Hello world' })。 数字占位符,例如{0}。实际内容必须用 Array 类型指定,例如:$t('strings.array', ['Hello world'])。 |
- 示例代码
<!-- xxx.html -->
<div>
<!-- 不使用占位符,text中显示“Hello world!” -->
<text>{{ $t('strings.hello') }}</text>
<!-- 具名占位符格式,运行时将占位符{name}替换为“Hello world” -->
<text>{{ $t('strings.object', { name: 'Hello world' }) }}</text>
<!-- 数字占位符格式,运行时将占位符{0}替换为“Hello world” -->
<text>{{ $t('strings.array', ['Hello world']) }}</text>
<!-- 先在js中获取资源内容,再在text中显示“Hello world” -->
<text>{{ hello }}</text>
<!-- 先在js中获取资源内容,并将占位符{name}替换为“Hello world”,再在text中显示“Object parameter substitution-Hello world” -->
<text>{{ replaceObject }}</text>
<!-- 先在js中获取资源内容,并将占位符{0}替换为“Hello world”,再在text中显示“Array type parameter substitution-Hello world” -->
<text>{{ replaceArray }}</text>
<!-- 获取图片路径 -->
<image src="{{ $t('files.image') }}" class="image"></image>
<!-- 先在js中获取图片路径,再在image中显示图片 -->
<image src="{{ replaceSrc }}" class="image"></image>
</div>
// xxx.js
// 下面为在js文件中的使用方法。
export default {
data: {
hello: "",
replaceObject: "",
replaceArray: "",
replaceSrc: "",
},
onInit() {
this.hello = this.$t("strings.hello");
this.replaceObject = this.$t("strings.object", { name: "Hello world" });
this.replaceArray = this.$t("strings.array", ["Hello world"]);
this.replaceSrc = this.$t("files.image");
},
};
语法
HTML 语法参考
HTML 是一套标记语言,通过组件,事件构建出页面的内容。页面具备数据绑定、事件绑定、列表渲染、条件渲染等高级能力。
页面结构
<!-- xxx.html -->
<div class="item-container">
<text class="item-title">Image Show</text>
<div class="item-content">
<image src="/common/xxx.png" class="image"></image>
</div>
</div>
数据绑定
<!-- xxx.html -->
<div onclick="changeText">
<text> {{content[1]}} </text>
</div>
// xxx.js
export default {
data: {
content: ["Hello World!", "Welcome to my world!"],
},
changeText: function () {
this.content.splice(1, 1, this.content[0]);
},
};
提示:
- 针对数组内的数据修改,请使用 splice 方法生效数据绑定变更。
- html 中的 js 表达式不支持 ES6 语法。
CSS 语法参考
CSS 是描述 HTML 页面结构的样式语言。所有组件均存在系统默认样式,也可在页面 CSS 样式文件中对组件、页面自定义不同的样式。
样式导入
为了模块化管理和代码复用,CSS 样式文件支持 @import 语句,导入 CSS 文件。
声明样式
每个页面目录下存在一个与布局 html 文件同名的 css 文件,用来描述该 html 页面中组件的样式,决定组件应该如何显示。
- 内部样式,支持使用 style、class 属性来控制组件的样式。例如:
<!-- index.html -->
<div class="container">
<text style="color: red">Hello World</text>
</div>
/* index.css */
.container {
justify-content: center;
}
- 文件导入,合并外部样式文件。例如,在 common 目录中定义样式文件 style.css,并在 index.css 文件首行中进行导入:
/* style.css */
.title {
font-size: 50px;
}
/* index.css */
@import "../../common/style.css";
.container {
justify-content: center;
}
选择器
css 选择器用于选择需要添加样式的元素,支持的选择器如下表所示:
选择器 | 样例 | 样例描述 |
---|---|---|
.class | .container | 用于选择 class="container"的组件。 |
#id | #titleId | 用于选择 id="titleId"的组件。 |
, | .title, .content | 用于选择 class="title"和 class="content"的组件。 |
示例:
<!-- 页面布局xxx.html -->
<div id="containerId" class="container">
<text id="titleId" class="title">标题</text>
<div class="content">
<text id="contentId">内容</text>
</div>
</div>
/* 页面样式xxx.css */
/* 对class="title"的组件设置样式 */
.title {
font-size: 30px;
}
/* 对id="contentId"的组件设置样式 */
#contentId {
font-size: 20px;
}
/* 对所有class="title"以及class="content"的组件都设置padding为5px */
.title,
.content {
padding: 5px;
}
伪类
css 伪类是选择器中的关键字,用于指定要选择元素的特殊状态。
名称 | 支持组件 | 描述 |
---|---|---|
:active | input[type="button"] | 表示被用户激活的元素,如:被用户按下的按钮。轻量级智能穿戴上伪类选择器上仅支持 background-color 和 background-image 的样式设置。 |
:checked | input[type="checkbox"、type="radio"] | 表示 checked 属性为 true 的元素。轻量级智能穿戴上伪类选择器上仅支持 background-color 和 background-image 的样式设置。 |
伪类示例如下,设置按钮的:active 伪类可以控制被用户按下时的样式:
<!-- index.html -->
<div class="container">
<input type="button"class="button"value="Button"></input>
</div>
/* index.css */
.button:active {
background-color: #888888; /*按钮被激活时,背景颜色变为#888888 */
}
样式预编译
预编译提供了利用特有语法生成 css 的程序,可以提供变量、运算等功能,令开发者更便捷地定义组件样式,目前支持 less、sass 和 scss 的预编译。使用样式预编译时,需要将原 css 文件后缀改为 less、sass 或 scss,如 index.css 改为 index.less、index.sass 或 index.scss。
- 当前文件使用样式预编译,例如将原 index.css 改为 index.less:
/* index.less */
/* 定义变量 */
@colorBackground: #000000;
.container {
background-color: @colorBackground; /* 使用当前less文件中定义的变量 */
}
- 引用预编译文件,例如 common 中存在 style.scss 文件,将原 index.css 改为 index.scss,并引入 style.scss:
/* style.scss */
/* 定义变量 */
$colorBackground: #000000;
在 index.scss 中引用:
/* index.scss */
/* 引入外部scss文件 */
@import'../../common/style.scss';
.container{
background-color: $colorBackground; /* 使用style.scss中定义的变量 */
}
提示:
引用的预编译文件建议放在 common 目录进行管理。
JS 语法参考
JS 文件用来定义 HTML 页面的业务逻辑,支持 ECMA 规范的 JavaScript 语言。基于 JavaScript 语言的动态化能力,可以使应用更加富有表现力,具备更加灵活的设计。下面讲述 JS 文件的编译和运行的支持情况。
语法
支持 ES6 语法。轻量级智能穿戴支持的 ES6 语法有限,仅支持以下 ES6 语法:
- let/const
- arrow functions
- class
- default value
- destructuring assignment
- destructuring binding pattern
- enhanced object initializer
- for-of
- rest parameter
- template strings
模块声明
使用 import 方法引入功能模块:
import router from "@system.router";
代码引用
使用 import 方法导入 js 代码:
import utils from "../../common/utils.js";
对象
页面对象
属性 类型 描述 data Object/Function 页面的数据模型,类型是对象或者函数,如果类型是函数,返回值必须是对象。属性名不能以$或_开头,不要使用保留字 for, if, show, tid。 $refs Object 持有注册过 ref 属性的 DOM 元素或子组件实例的对象。
获取 DOM 元素
- 通过$refs 获取 DOM 元素
<!-- index.html -->
<div class="container">
<image-animator
class="image-player"
ref="animator"
images="{{images}}"
duration="1s"
onclick="handleClick"
></image-animator>
</div>
// index.js
export default {
data: {
images: [
{ src: '/common/frame1.png' },
{ src: '/common/frame2.png' },
{ src: '/common/frame3.png' },
],
},
handleClick() {
const animator = this.$refs.animator; // 获取ref属性为animator的DOM元素
const state = animator.getState();
if (state === 'paused') {
animator.resume();
} elseif (state === 'stopped') {
animator.start();
} else {
animator.pause();
}
},
};
生命周期接口
- 页面生命周期
属性 | 类型 | 参数 | 返回值 | 描述 | 触发时机 |
---|---|---|---|---|---|
onInit | Function | 无 | 无 | 页面初始化 | 页面数据初始化完成时触发,只触发一次。 |
onReady | Function | 无 | 无 | 页面创建完成 | 页面创建完成时触发,只触发一次。 |
onShow | Function | 无 | 无 | 页面显示 | 页面显示时触发。 |
onHide | Function | 无 | 无 | 页面消失 | 页面消失时触发。 |
onDestroy | Function | 无 | 无 | 页面销毁 | 页面销毁时触发。 |
onBackPress | Function | 无 | 无 | - | 当用户点击返回实体按键时触发该事件。如果事件响应方法最后返回true表示不返回,自己处理业务逻辑(完毕后开发者自行调用 API 返回);否则:不返回数据,或者返回其它数据,表示遵循系统逻辑:返回到上一页。 |
页面 A 的生命周期接口的调用顺序:
打开页面 A:onInit() -> onReady() -> onShow()
在页面 A 打开页面 B:onHide() -> onDestroy()
从页面 B 返回页面 A:onInit() -> onReady() -> onShow()
退出页面 A:onHide() -> onDestroy()
页面隐藏到后台运行:onHide()
页面从后台运行恢复到前台:onShow()
应用生命周期
属性 | 类型 | 参数 | 返回值 | 描述 | 触发时机 |
---|---|---|---|---|---|
onCreate | Function | 无 | 无 | 应用创建 | 当应用创建时调用。 |
onDestroy | Function | 无 | 无 | 应用退出 | 当应用退出时触发。 |