用来定义页面数据和实现生命周期接口
支持 ES6 语法
可以通过 import 引入功能模块,在代码中调用模块方法(具体参看接口部分文档说明)
import fetch from '@system.fetch'
JS 代码引用推荐使用 import 来导入, 例如:
import utils from '../Common/utils.js'
注意: 快应用环境不是 node 环境,不要引用 node 原生模块,如 import fs from 'fs'
属性 | 类型 | 描述 |
---|---|---|
data deprecated | Object | Function | 页面级组件的数据模型,能够转换为 JSON 对象;属性名不能以$或_开头, 不要使用 for, if, show, tid 等保留字 如果是函数,返回结果必须是对象,在组件初始化时会执行函数获取结果作为 data 的值 使用 data 方式声明的属性会被外部数据覆盖,因此存在一定安全风险,推荐使用下面的 public,protected,private 来声明属性(注意:它们不能与 data 同时声明) |
public 1000+ | Object | 页面级组件的数据模型,影响传入数据的覆盖机制:public 内定义的属性允许被传入的数据覆盖,如果外部传入数据的某个属性未被声明,在 public 中不会新增这个属性 |
protected 1000+ | Object | 页面级组件的数据模型,影响传入数据的覆盖机制:protected 内定义的属性,允许被应用内部页面请求传递的数据覆盖,不允许被应用外部请求传递的数据覆盖 |
private 1000+ | Object | 页面级组件的数据模型,影响传入数据的覆盖机制:private 内定义的属性不允许被覆盖 |
computed 1050+ | Object | 计算属性,属性名不能以$或_开头, 不要使用 for, if, show, tid 等保留字 |
属性 | 类型 | 描述 |
---|---|---|
data | Object | Function | 自定义组件的数据模型,能够转换为 JSON 对象;属性名不能以$或_开头, 不要使用 for, if, show, tid 等保留字 如果是函数,返回结果必须是对象,在组件初始化时会执行函数获取结果作为 data 的值 |
props | Array | Object | 定义组件外部可传入的所有属性;属性名不能以$或_开头, 不要使用 for, if, show, tid 等保留字 在模板代码中,请使用短横线分隔命名代替驼峰命名。如,属性定义 props: ['propA'],可通过 <tag prop-a='xx'> 方式传递到组件内部支持 prop 验证 1010+ |
computed 1050+ | Object | 计算属性,属性名不能以$或_开头, 不要使用 for, if, show, tid 等保留字 |
1010+
在自定义组件中,可将 props 定义为带验证需求的对象。其中,key 为属性名,value 为属性对应的验证需求。验证失败则输出错误提示日志,增加 prop 验证有利于规范自定义组件的使用
定义:
属性 | 类型 | 描述 |
---|---|---|
type 1010+ | - | 检查属性值的类型。支持单一类型和多种可能类型,可在原生和自定义构造函数中任意选择,单独或组合使用
|
default 1010+ | - | 设置属性的默认值 |
required 1010+ | Boolean | 设置属性是否必填 |
validator 1010+ | Function | 设置自定义验证函数。若函数的返回值为真,则通过验证;否则验证失败 |
示例:
<script>
export default {
props: {
// 单一类型检查的简写
propA: Number,
// 多种可能类型的简写
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
default () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator (value) {
return value === 'hello'
}
}
}
}
</script>
1050+
{ [key: string]: Function | { get: Function, set: Function } }
export default {
data: {
firstName: 'Quick',
lastName: 'App'
},
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`
},
set(value) {
const names = value.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
},
onReady() {
console.log(this.fullName) // Quick App
this.fullName = 'John Doe'
console.log(this.firstName) // John
console.log(this.lastName) // Doe
}
}
属性 | 类型 | 描述 |
---|---|---|
$app | Object | 应用对象 |
$page | Object | 页面对象 |
$valid | Boolean | 页面对象是否有效 |
$visible | Boolean | 页面是否处于用户可见状态 |
可通过$app
访问
属性 | 类型 | 描述 |
---|---|---|
$def | Object | 使用this.$app.$def 获取在app.ux 中暴露的对象 |
$data | Object | 使用this.$app.$data 获取在manifest.json 的config.data 中声明的全局数据 |
可通过$page
访问
属性 | 类型 | 描述 |
---|---|---|
action | String | 获取打开当前页面的 action。仅在当前页面是通过 filter 匹配的方式打开时有效,否则为 undefined。参见manifest 文件 |
uri | String | 获取打开当前页面的 uri。仅在当前页面是通过 filter 匹配的方式打开时有效,否则为 undefined。参见manifest 文件 |
name 1030+ | String | 获取当前页面路由的名称,与manifest 文件中router.pages 中对应的属性名一致 |
path 1030+ | String | 获取当前页面路由的 path,与manifest 文件中router.pages 中对应的 path 一致 |
component 1030+ | String | 获取当前页面路由的 component,与manifest 文件中router.pages 中对应的 component 一致 |
orientation 1040+ | String | 获取当前页面的屏幕方向: portrait:竖屏 landscape:横屏 |
statusBarHeight 1050+ | Number | 获取当前页面的状态栏高度 |
titleBarHeight 1050+ | Number | 获取当前页面的标题栏高度 |
windowWidth 1050+ | Number | 获取当前页面的可使用窗口宽度 |
windowHeight 1050+ | Number | 获取当前页面可使用窗口高度 |
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$set | Function | key: String value: Any | 添加数据属性,用法:this.$set('key',value) this.$vm('id').$set('key',value) |
$delete | Function | key: String | 删除数据属性,用法:this.$delete('key') this.$vm('id').$delete('key') |
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$element | Function | id: String 组件 id | 获取指定 id 的组件 dom 对象,如果没有指定 id,则返回根组件 dom 对象用法:<template> <div id='xxx'></div> </template> this.$element('xxx') 获取 id 为 xxx 的 div 组件实例对象 this.$element() 获取根组件实例对象 |
$root | Function | 无 | 获取顶层 ViewModel |
$parent | Function | 无 | 获取父亲 ViewModel |
$child | Function | id: String 组件 id | 获取指定 id 的自定义组件的 ViewModel 用法:this.$child('xxx') 获取 id 为 xxx 的 div 组件 ViewModel |
$vm deprecated | Function | id: String 组件 id | 请使用上面this.$child('xxx') 替代 |
$rootElement deprecated | Function | 无 | 请使用上面this.$element() 替代 |
$forceUpdate | Function | 无 | 更新 ViewModel 数据,可能会触发 DOM 操作,如:创建节点、更新节点、删除节点等;这些 DOM 操作不一定在数据更新时立即执行,而是在开发者的业务代码执行后触发; 若开发者期望数据更新时立即执行相应的 DOM 操作,可使用: this.$forceUpdate() ;一般不推荐使用 |
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
$on | Function | type: String 事件名 handler: Function 事件句柄函数 | 添加事件处理句柄用法:this.$on('xxxx', this.fn) fn 是在<script> 中定义的函数 |
$off | Function | type: String 事件名 handler: Function 事件句柄函数 | 删除事件处理句柄用法:this.$off('xxxx', this.fn) this.$off('xxx') 删除指定事件的所有处理句柄 |
$dispatch | Function | type: String 事件名 | 向上层组件发送事件通知用法:this.$dispatch('xxx') 正常情况下,会一直向上传递事件(冒泡)如果要停止冒泡,在事件句柄函数中调用evt.stop() 即可 |
$broadcast | Function | type: String 事件名 | 向子组件发送事件通知用法:this.$broadcast('xxx') 正常情况下,会一直向下传递事件如果要停止传递,在事件句柄函数中调用evt.stop() 即可 |
$emit | Function | type: String 事件名 data: Object 事件参数 | 触发事件,对应的句柄函数被调用用法:this.$emit('xxx') this.$emit('xxx', {a:1}) 传递的事件参数可在事件回调函数中,通过evt.detail 来访问,例如evt.detail.a |
$emitElement | Function | type: String 事件名 data: Object 事件参数 id: String 组件 id (默认为-1 代表根元素) | 触发组件事件, 对应的句柄函数被调用用法:this.$emitElement('xxx', null, 'id') this.$emitElement('xxx', {a:1}) 传递的事件参数可在事件回调函数中,通过evt.detail 来访问,例如evt.detail.a |
$watch | Function | data: String 属性名, 支持'a.b.c'格式,不支持数组索引 handler: String 事件句柄函数名, 函数的第一个参数为新的属性值,第二个参数为旧的属性值 | 动态添加属性/事件绑定,属性必须在 data 中定义,handler 函数必须在<script> 定义;当属性值发生变化时事件才被触发用法:this.$watch('a','handler') |
1010+
可通过$app
访问
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
exit 1010+ | Function | 无 | 退出快应用,结束应用生命周期。 调用方法: this.$app.exit() |
可通过$page
访问
属性 | 类型 | 参数 | 描述 |
---|---|---|---|
setTitleBar | Function | text: String 标题栏文字 textColor: String 文字颜色 backgroundColor: String 背景颜色 backgroundOpacity 1000+ : Number 背景透明度menu 1000+ : Boolean 是否在标题栏右上角显示菜单按钮 | 设置当前页面的标题栏用法:this.$page.setTitleBar({text:'Hello', textColor:'#FF0000', backgroundColor:'#FFFFFF', backgroundOpacity:0.5, menu: true}) |
finish 1010+ | Function | 无 | 从本页面退出,结束页面生命周期。 调用方法: this.$page.finish() |
exitFullscreen 1050+ | Function | 无 | 页面退出全屏模式 |
setStatusBar 1050+ | Function | immersive: Boolean 是否开启状态栏沉浸式 textStyle: String 文字样式 backgroundColor: String 状态栏背景颜色 backgroundOpacity 1000+ : Number 状态栏背景不透明度 | 设置当前页面的状态栏用法:this.$page.setStatusBar({immersive:true, textStyle:'dark', backgroundColor:'#FFFFFF', backgroundOpacity:0.5}) |
scrollTo 1070+ | Function | top: Number 要滚动到的纵坐标,单位:px behavior: String 滚动行为,支持参数 smooth(平滑滚动),instant(瞬间滚动),默认值 auto,效果等同于 instant | 纵向滚动页面到指定的纵坐标用法:this.$page.scrollTo({top:1000, behavior:'smooth'}) |
scrollBy 1070+ | Function | top: Number 滚动的纵轴偏移量 ,单位:px behavior: String 滚动行为,支持参数 smooth(平滑滚动),instant(瞬间滚动),默认值 auto,效果等同于 instant | 以给定的偏移量纵向滚动页面用法:this.$page.scrollBy({top:100}) |
getMenuBarRect 1070+ | Function | 获取 menuBar 的布局位置信息。坐标信息以页面内容区左上角为原点,单位 px | 获取 menuBar 页面位置信息用法:this.$page.getMenuBarRect() |
监听页面初始化。当页面完成初始化时调用,只触发一次
参数名 | 类型 | 描述 |
---|---|---|
query 1060+ | Object | 通过 deeplink、router.push 等接口传入的 uri 中 query 解析成的对象,或者 router.push 等接口传入的 params 对象 |
监听页面创建完成。当页面完成创建可以显示时触发,只触发一次
无
监听页面显示。当进入页面时触发
无
监听页面隐藏。当页面跳转离开时触发
无
监听页面退出。当页面跳转离开(不进入导航栈)时触发
无
监听返回按钮动作。当用户点击返回按钮时触发
无
类型 | 描述 |
---|---|
Boolean | 返回 true 表示页面自己处理返回逻辑,返回 false 表示使用默认的返回逻辑,不返回值会作为 false 处理; 注意:该函数不支持声明为异步函数(即:使用 async 标识),因为返回值代表界面要立即响应用户操作; |
监听菜单按钮动作。当用户点击菜单按钮时触发
无
类型 | 描述 |
---|---|
Boolean | 返回 true 表示开发者自己处理响应逻辑,返回 false 表示使用系统弹出菜单的逻辑,不返回值会作为 false 处理; 注意:该函数不支持声明为异步函数(即:使用 async 标识),因为返回值代表界面要立即响应用户操作; |
1050+
监听页面重新打开。
1.当页面在 manifest 中 launchMode1050+
标识为'singleTask'时,仅会存在一个目标页面实例,用户多次打开目标页面时触发此函数。
2.打开目标页面时在 push 参数中携带 flag 'clearTask',且页面实例已经存在时触发。
该回调中参数为重新打开该页面时携带的参数。
详见页面启动模式
参数名 | 类型 | 描述 |
---|---|---|
query | Object | 通过 deeplink、router.push 等接口传入的 uri 中 query 解析成的对象,或者 router.push 等接口传入的 params 对象 |
1060+
监听应用配置发生变化。当应用配置发生变化时触发,如系统语言或主题模式改变
参数名 | 类型 | 描述 |
---|---|---|
event | Object | 应用配置发生变化的事件 |
event 参数:
参数名 | 类型 | 描述 |
---|---|---|
type | String | 应用配置发生变化的原因类型,支持的 type 值如下所示 |
event 中type
现在支持的参数值如下:
参数值 | 描述 |
---|---|
locale | 应用配置因为语言、地区变化而发生改变 |
themeMode 1070+ | 系统主题模式变更时会触发(不受 manifest.json 的 themeMode 值影响) |
示例代码:
onConfigurationChanged(evt) {
console.log(`触发生命周期onConfigurationChanged, 配置类型:${evt.type}`)
}
car 1060+
监听按键响应。当按键被触发时回调
参数名 | 类型 | 描述 |
---|---|---|
event | Object | 被触发的按键事件 |
event 参数:
参数名 | 类型 | 描述 |
---|---|---|
keyCode | Number | 按下的键位 |
keyAction | Number | 按下或释放的动作 |
repeatCount | Number | 连续按的次数 |
示例代码:
onKey(evt) {
console.log('key pressed!'+event);
console.info(`触发页面生命周期 onKey`)
// false:默认值,表示不拦截key值操作,直接执行对应key值;true:表示自己处理key值;
// return true
}
注意: 一个页面可以多个组件注册onkey回调 但是在遥控器发起操作时,客户端会寻找当前焦点的元素,判断其是否注册了onkey回调。如有,则执行onkey回调 因此,同一个页面只有一个组件的onkey回调会被执行
1050+
自定义组件,指的是通过
属性 | 类型 | 参数 | 返回值 | 描述 | 触发时机 |
---|---|---|---|---|---|
onInit | Function | 无 | 无 | 监听初始化 | 当数据驱动化完成时触发 |
onReady | Function | 无 | 无 | 监听模板创建完成 | 当模板创建完成时触发 |
onDestroy | Function | 无 | 无 | 监听组件销毁 | 当销毁时触发 |
监听应用创建,应用创建时调用
无
1070+
监听应用收到一个外部的打开新页面的请求
无
1070+
监听应用返回前台,应用返回前台时调用
无
1070+
监听应用退到后台,应用退到后台时调用
无
监听应用销毁,应用销毁时调用
无
1030+
监听应用报错,应用捕获异常时调用
参数名 | 类型 | 描述 |
---|---|---|
message | String | 错误描述 |
stack | String | 调用栈 |
1060+
监听页面跳转的异常,当页面跳转异常时,如果前端在 app.ux 定义了 onPageNotFound,将会收到错误回调
页面跳转场景:router.push、router.replace、a 标签配置 href 属性跳转
示例代码:
// this methods must be written at app.ux
// app.ux
export default {
onPageNotFound(params) {
const { uri = '' } = params
console.error('error uri', uri)
}
}
onPageNotFound 回调返回一个对象,对象参数值如下展示:
参数名 | 类型 | 描述 |
---|---|---|
uri | String | 页面跳转出现异常的地址 |
app.ux 对象指的是:开发者在app.ux
中<script>
节点内要导出的对象
属性/方法 | 类型 | 参数 | 描述 |
---|---|---|---|
plugins 1060+ | 数组 | 无 | 数组中的每个元素代表开发者定义的前端插件;详情请参考下面的文档:框架前端插件 ; |
1000+
用来实现不同页面之间的相互通信。
在 BroadcastChannel 的构造函数中,只支持接受一个参数,就是"频道名称"(channel name)
比如:
const test = new BroadcastChannel('channel')
BroadcastChannel 定义的接口如下:
declare interface BroadcastChannel = {
name: string,
postMessage: (message: any) => void;
onmessage: (event: MessageEvent) => void;
close: () => void;
}
消息对象(MessageEvent)的类型定义如下:
declare interface MessageEvent = {
type: string, // "message"
data: any
}
对参数的说明:
名称 | 类型 | 参数 | 描述 |
---|---|---|---|
name | String | String:频道名称 | 频道名称,区分不同的消息频道(注意:不同频道之间不可通信)。 |
postMessage | Function | Object: 消息内容 | 用于在当前频道中广播消息。 |
onmessage | Function | Event:消息对象 | 订阅消息。在频道中接收到广播消息之后,会给所有订阅者派发消息事件。 |
close | Function | 无 | 关闭当前的频道。 |
假设在我们的应用中,有 A、B、C 三个页面
在页面 A 中:
const pageA = new BroadcastChannel('channel1')
pageA.postMessage('haha!')
在页面 B 中:
const pageB = new BroadcastChannel('channel1')
在页面 C 中:
const pageC = new BroadcastChannel('channel1')
pageC.onmessage = function(event) {
console.log(event.data)
pageC.postMessage('hello, i am here!')
}
这样,页面 A 、B 、C 都创建一个监听了 'channel1' 频道的 BroadcastChannel 对象,它们之间可以通过这个对象实现互相通信。
当 pageA 发布了 'haha!' 消息时,pageC 将收到一个消息事件,其 data 字段等于 'haha!',然后也向频道中回复一条消息。注意:自己不会收到自己发的消息。
但是 pageB 并不会收到这些消息,因为他没有实现 onmessage 方法,相当于没有接收频道中的消息,所以他实际上不是一个订阅者。
注意:在 pageA 销毁 channel 当前不与页面 context 进行上下文绑定,需要主动关闭消息通道,如下所示:
const pageA = new BroadcastChannel('tom')
pageA.close()
1060+
开发者有时面对更多的解耦合与 AOP(Aspect Oriented Programming)需求,插件机制用于解决开发者业务代码与平台本身能力的耦合分离;
比如,开发者需要记录用户打开快应用与每个页面打开返回等的时间操作节点,用于埋点需求,此时通过插件机制就可以不侵入到每个页面代码模块中,实现更优雅;
开发者通过定义一个普通的 js 对象就可以代表一个插件(称为:插件对象),该对象提供 install 方法,将在应用启动时加载并安装插件,此时该方法得到执行;
属性/方法 | 类型 | 参数 | 描述 |
---|---|---|---|
install() | Function | VmClass | 第一个参数代表每个组件(页面级 ViewModel、自定义组件 ViewModel)所属的类,称为 VmClass; |
属性/方法 | 类型 | 参数 | 描述 |
---|---|---|---|
mixin() | Function | object | 监听页面的生命周期事件 |
mixinApp() | Function | object | 监听应用的生命周期事件 |
如下代码所示:
// file:plugin-demo.js
const PluginDemo = {
// 安装入口
install(VmClass) {
// 页面生命周期
VmClass.mixin({
onInit() {
console.info(`页面生命周期:onInit`)
},
onReady() {
console.info(`页面生命周期:onReady`)
},
onShow() {
console.info(`页面生命周期:onShow`)
},
onHide() {
console.info(`页面生命周期:onHide`)
}
})
// 应用生命周期
VmClass.mixinApp({
onCreate() {
console.info(`页面生命周期:onCreate`)
}
})
}
}
export default PluginDemo
开发者在app.ux
对象中声明 plugins 属性(类型为数组),数组中的元素声明为需要引入的插件;
如下代码所示:
<script>
// file:app.ux
import pluginDemo from './plugin-demo.js'
export default {
plugins: [
pluginDemo
]
}
</script>