6月13号是什么星座| 199是什么意思| 肌钙蛋白高说明什么| iqc是什么意思| 长庚是什么意思| 属羊的跟什么属相犯冲| 腹胀吃什么药| 正名是什么意思| 重阳节送老人什么礼物| 什么旺土| 趴着睡觉是什么原因| 水痘用什么药| 哀伤是什么意思| zero什么意思| 后背疼挂什么科| 气血虚什么症状| 莹五行属性是什么| 肝硬化是什么原因引起的| viola是什么意思| 扁桃体作用是什么| 黛是什么颜色| 柠檬什么季节成熟| 鬼冢虎什么档次| 送朋友什么礼物好| 趴着睡觉是什么原因| 女人吃火龙果有什么好处| 肺气肿是什么| 龙抬头是什么意思| 执拗是什么意思| 强肉弱食是什么意思| 细菌感染有什么症状表现| 小孩咬手指甲是什么原因| 和五行属什么| 什么是桃花劫| 车震是什么意思| 血常规24项能查出什么病| 血糖有点高吃什么食物好| 女人肺气虚吃什么补最快| 肝脏在人体的什么位置| 石家庄有什么特产| 各的偏旁是什么| 五花八门是什么生肖| 勃起不坚硬吃什么药| 血管炎是什么症状| 什么的医生| 女人打呼噜是什么原因| 枣什么时候成熟| 什么是热辐射| 低血压是什么原因造成的| hpv病毒是什么病| 七月二十二什么日子| 月经血块是什么原因| 老年人吃什么钙片好| b超挂什么科| black什么颜色| 五月一号什么星座| 乳房痒是什么原因| 独活主治什么病| 脑梗用什么药| 看甲状腺去医院挂什么科| 该说不说的是什么意思| 经常打哈欠是什么原因| 半夜容易醒是什么原因| 若叶青汁有什么功效| 陈皮有什么作用| 取保候审需要什么条件| 64是什么| 白醋和小苏打一起用起什么效果| s是什么牌子| PT医学上是什么意思| 反流性食管炎吃什么药最有效| 带鱼屏是什么意思| 榴莲什么样的好| 十二月份的是什么星座| 早上起来嘴巴苦是什么原因| 嗔恨是什么意思| 乳腺结节看什么科| 陈旧性心梗是什么意思| 徒然是什么意思| 得了破伤风是什么症状| 吃什么食物对心脏有好处| 分水岭是什么意思| cup什么意思| 女生肾虚是什么原因| 泰安有什么好吃的| 什么是211大学| 履约是什么意思| 龟苓膏有什么功效| 思想包袱是什么意思| 舌吻有什么好处| 吃什么补气最快| 家里进鸟了是什么预兆| 单侧流鼻血是什么原因| 2017什么年| 火什么银花| 翡翠有什么作用与功效| 津液亏虚吃什么中成药| y3是什么牌子| 鼻子流血什么原因| 植物神经是什么| 规培结束后是什么医生| 3月30日什么星座| aosc是什么病| 2222是什么意思| 宁字五行属什么的| 勃起不硬吃什么药| 己未日五行属什么| 肝火郁结是什么症状| 白洞是什么| 易烊千玺原名叫什么| 湿气重可以吃什么水果| 为什么下雨后会出现彩虹| 茯苓的作用是什么| 女孩学什么专业好就业| 瘤是什么意思| 肠易激综合征吃什么中成药| 吃什么长胎快| o型血为什么叫贵族血| 二级建造师什么时候出成绩| 走路脚心疼是什么原因| 染指什么意思| 前白蛋白低是什么意思| 脾气暴躁易怒是什么病| 火车动车高铁有什么区别| 为什么不想上班| nba打铁是什么意思| naco是什么牌子| 骨质疏松有什么症状| 女性肾火旺有什么症状| 迅雷不及掩耳之势是什么意思| 二级建造师什么时候出成绩| 痔疮饮食要注意什么| 澳大利亚位于什么板块| 大拇指疼痛什么原因引起的| 黄褐斑内调吃什么药| 咳嗽恶心干呕是什么原因引起的| 梦见做棺材是什么意思| 掼蛋是什么意思| 女大一抱金鸡是什么意思| kfc是什么| 高净值什么意思| 建档立卡户是什么意思| Mary英文名什么意思| 耳朵嗡嗡的响是什么原因| 打饱嗝吃什么药| 粉饼是干什么用的| 高铁跟动车有什么区别| 焦急的什么| 碳酸氢钠有什么作用| 背部爱出汗是什么原因| 什么牌子的保温杯好| 净身出户需要什么条件| viagra是什么药| 膝盖背面叫什么| 鸟字旁的字和什么有关| 深渊是什么意思| adidas是什么品牌| 海藻是什么植物| ace是什么意思| 露水夫妻是什么意思| 有什么好处| 勃起功能障碍吃什么药| 辛属什么五行| 减肥喝什么茶| 小针刀是什么手术| 难受是什么意思| 眼睛为什么会长麦粒肿| 椅子像什么| 肝内强回声是什么意思| 胃窦隆起是什么意思| 紫色适合什么肤色的人| 7月4日是什么星座| 什么原因造成低血糖| 蕾字五行属什么| 鼻窦炎有什么症状表现| 高丽参是什么参| 夏天适合吃什么| 促胃动力药什么时候吃| 骨折有什么忌口| 淋巴系统由什么组成| 什么茶减肥效果好| 火文念什么| 为什么医生不推荐特立帕肽呢| 酸奶用什么菌发酵| 胸闷气短吃什么药| 发热门诊属于什么科| cmn是什么意思| 老人脚肿是什么原因引起的| 男人皮肤黑穿什么颜色的衣服好看| 眼睛跳是什么原因| 高硼硅是什么材质| 九月初三是什么星座| 朱元璋长什么样| q币有什么用| 蜱虫用什么药可以消灭| 耳朵挂什么科| 12月14日什么星座| 坐东北朝西南是什么宅| 香榧是什么| 畏寒是什么意思| 三点水加分念什么| 吉祥什么意思| 为什么会堵奶| 莓茶什么人不适合喝| 燚是什么意思| 思伤脾是什么意思| 证候是什么意思| 肌酸激酶高是什么原因| 来源朋友验证消息是什么意思| 湿热体质吃什么食物好| 飞短流长是什么意思| 老人大便失禁是什么原因| 蒲公英和什么一起泡水喝最好| 梦见洗手是什么意思| 专场是什么意思| 鬼代表什么数字| 人彘是什么意思| 心电图是检查什么的| yellow是什么颜色| 小金鱼吃什么食物| 89年蛇是什么命| 蜜饯是什么| 23号来月经什么时候是排卵期| 手脚抽筋吃什么药| sca是什么意思| 无水焗是什么意思| 梦见小男孩是什么预兆| 什么食物蛋白质含量高| 二氧化碳低是什么原因| 什么叫甲沟炎| 心脏是由什么组织构成的| 来大姨妈不能吃什么| 五个月宝宝吃什么辅食最好| 六月初六是什么节| 解脲脲原体是什么意思| 继发性闭经是什么意思| 拉黑屎是什么原因| 尿常规能查出什么病| 大便干燥拉不出来是什么原因| 什么品牌的床好| 肽是什么意思| 皮肤长小肉粒是什么原因| 黑色的鸟是什么鸟| 狂躁症吃什么药| camp是什么| 用纸可以折什么| 大陆去台湾需要什么手续| 胎儿为什么会喜欢臀位| 梦见吃排骨是什么意思| 人老了为什么会瘦| 肛门出血是什么原因| 声优是什么意思| 三合一是什么意思| 青蛙属于什么类动物| 一天什么时候最热| 五福是什么生肖| 甲状腺功能是什么| 猕猴桃树长什么样| 荨麻疹用什么药最好| 什么的形象| 经常脚抽筋是什么原因| 三伏天什么时候开始| 71年什么时候退休| 胆小怕事是什么生肖| 百度

发轫甲骨绝学开拓古史天地

百度 百香果什么时候成熟

框架的视图层由 FXML 与 FTSS 编写,基础单元是组件。

  • FXML 用于描述页面的结构,类似于 HTML ;
  • FTSS 用于描述组件和页面的样式,是 css 的子集; fts 是小程序的一套脚本语言,基础语法同javascript,结合 FXML,可以创建出页面的结构。

组件 (Component) 是视图的基本组成单元,类似于HTML页面的各种标签,如div、span、img等

# 1. FXML

FXML 是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

以下是一些简单的示例:?

# 1.1 数据绑定

<!--fxml-->
<view> hello {{name}} </view>
// page.js
Page({
  data: {
    name: 'cortana'
  }
})

# 1.2 列表渲染

<!--fxml-->
<view ft:for="{{array}}"> {{item}} </view>
// page.js
Page({
  data: {
    array: ["苹果", "香蕉", "橘子", "西瓜"]
  }
})

# 1.3 条件渲染

<!--fxml-->
<view ft:if="{{type == 1}}"> 类型 1 </view>
<view ft:elif="{{view == 2'}}"> 类型 2 </view>
<view ft:else="{{view == 3}}"> 类型 3  </view>
// page.js
Page({
  data: {
    type: 1
  }
})

# 1.4 模板

<!--fxml-->
<template name="cat">
  <view>
    age: {{name}}, age: {{age}}
  </view>
</template>

<template is="cat" data="{{...cat1}}"></template>
// page.js
Page({
  data: {
    cat1: {name: 'blue', age: '2'},
  }
})

# 1.5 事件

<view bindtap="getDate"> {{date}} </view> //点击事件 bindtap
Page({
  data: {
    date: ""
  },
  getDate: function(e) {
    this.setData({
      date: new Date()
    })
  }
})

# 2. FTSS

与 CSS FTSS 扩展的特性有:

  • 尺寸单位
  • 样式导入

# 2.1 尺寸单位

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。

设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)
iPhone5 1rpx = 0.42px 1px = 2.34rpx
iPhone6 1rpx = 0.5px 1px = 2rpx
iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx

注意

  • 开发“人民网+”小程序时设计师可以用 iPhone6 作为视觉稿的标准。
  • 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

# 2.2 样式导入

使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。

示例代码

/** common.ftss **/
.small-p {
  padding:5px;
}
/** app.ftss **/
@import "common.ftss";
.middle-p {
  padding:15px;
}

# 2.3 内联样式

框架组件上支持使用 style、class 属性来控制组件的样式。

style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。

<view style="color:{{color}};" />

class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上.,样式类名之间用空格分隔。

<view class="normal_view" />

# 2.4 选择器

目前支持的选择器有:

选择器 样例 样例描述
.class .intro 选择所有拥有 class="intro" 的组件
#id #firstname 选择拥有 id="firstname" 的组件
element view 选择所有 view 组件
element, element view, checkbox 选择所有文档的 view 组件和所有的 checkbox 组件
::after view::after 在 view 组件后边插入内容
::before view::before 在 view 组件前边插入内容

# 2.5 全局样式与局部样式

定义在 app.ftss 中的样式为全局样式,作用于每一个页面。在 page 的 FTSS 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.ftss 中相同的选择器。

# 3. FTS

FTS(是小程序的一套脚本语言,结合 FXML,可以构建出页面的结构。?

注意

FTS 不依赖于SDK的基础库版本,可以在所有版本的小程序中运行。 FTS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。 FTS 的运行环境和其他 JavaScript 代码是隔离的,FTS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。 FTS 函数不能作为组件的事件回调。

以下是一些使用 FTS 的简单示例:

页面渲染

<!--fxml-->
<fts module="m1">
var msg = "hello world";
module.exports.message = msg;
</fts>

<view> {{m1.message}} </view>

页面输出

hello world

数据处理

// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
  }
})
<!--fxml-->
<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
<fts module="m1">
var getMax = function(array) {
  var max = undefined;
  for (var i = 0; i < array.length; ++i) {
    max = max === undefined ?
      array[i] :
      (max >= array[i] ? max : array[i]);
  }
  return max;
}

module.exports.getMax = getMax;
</fts>

<!-- 调用 fts 里面的 getMax 函数,参数为 page.js 里面的 array -->
<view> {{m1.getMax(array)}} </view>

页面输出

5

# 4. FTS 响应事件

# 4.1 背景

当小程序需要实现频繁用户交互的效果时,如果采用常规实现方法,如:

页面有 2 个元素 A 和 B,用户在 A 上做 touchmove 手势,要求 B 也跟随移动,movable-view 就是一个典型的例子。一次 touchmove 事件的响应过程为:

i、touchmove 事件从视图层(View)抛到逻辑层(Service)

ii、逻辑层(Service)处理 touchmove 事件,再通过 setData 来改变 B 的位置

一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。

此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟,交互的实际表现不会很理想。

# 4.2 解决方案

基于以上原因,可以使用 FTS 函数用来响应小程序事件,然后在视图层(View)处理 dom 样式,实现比较好的效果。

目前只能响应内置组件的事件,不支持自定义组件事件。

FTS 函数的除了纯逻辑的运算,还可以通过封装好的 ComponentDescriptor 实例来访问以及设置组件的 class 和样式,对于交互动画,设置 style 和 class 能满足绝大多数需求了。

FTS 函数的例子如下:

var event = function(event, ownerInstance) {
    // 获取组件实例
    var instance = ownerInstance.selectComponent('.some-component')
    instance.setStyle({
      color: 'red',
      "font-size": '18rpx'
    })
    instance.setClass('other-class')
    return false // 不往上冒泡
}

其中入参 event 是小程序事件对象基础上多了 event.instance 来表示触发事件的组件的 ComponentDescriptor 实例。

ownerInstance 表示的是触发事件的组件所在的组件的 ComponentDescriptor 实例,如果触发事件的组件是在页面内的,则 ownerInstance 表示的是页面实例。

ComponentDescriptor 目前支持的 API 如下:

方法 参数 描述
selectComponent selector 对象 返回组件的 ComponentDescriptor 实例。
selectAllComponents selector 对象数组 返回组件的 ComponentDescriptor 实例数组。
setStyle Object/string 设置组件样式,支持rpx。设置的样式优先级比组件 fxml 里面定义的样式高。不能设置最顶层页面的样式。
addClass/removeClass/hasClass string 设置组件的 class。设置的 class 优先级比组件 fxml 里面定义的 class 高。不能设置最顶层页面的 class。
callMethod (funcName:string, args:object) 调用当前组件/页面在逻辑层(App Service)定义的函数。funcName表示函数名称,args表示函数的参数。
getComputedStyle Array <string> 指定样式名列表,返回节点对应样式名的当前值。
getBoundingClientRect 返回节点的尺寸信息。

# 4.3 使用方法

FXML 定义事件:

<fts module="event" src="./event.fts"></fts>
<view bindtouchmove="{{event.touchmove}}" class="movable"></view>

注意:FTS 函数必须用 {{}} 括起来。

文件 event.ftx 里面定义并导出函数:

module.exports = {
    touchmove: function(event, instance) {
        console.log('log event')
    },
    otherEvent: function(event, instance) {
        console.log('log event')
    }
}

# 5. 简易双向绑定

在 FXML 中,普通的属性的绑定是单向的。例如:

<input value="{{value}}" />

如果使用 this.setData({ value: 'leaf' }) 来更新 value ,this.data.value 和输入框的中显示的值都会被更新为 leaf ;但如果用户修改了输入框里的值,却不会同时改变 this.data.value 。

如果需要在用户输入的同时改变 this.data.value ,需要借助简易双向绑定机制。此时,可以在对应项目之前加入 model: 前缀:

<input model:value="{{value}}" />

这样,如果输入框的值被改变了, this.data.value 也会同时改变。同时, FXML 中所有绑定了 value 的位置也会被一同更新, 数据监听器 也会被正常触发。

在开发者工具中预览效果

用于双向绑定的表达式有如下限制:

<input model:value="值为 {{value}}" />
<input model:value="{{ a + b }}" />

都是非法的;

<input model:value="{{ a.b }}" />

这样的表达式目前暂不支持。

# 5.1 在自定义组件中传递双向绑定

双向绑定同样可以使用在自定义组件上。如下的自定义组件:

// custom-component.js
Component({
  properties: {
    myValue: String
  }
})

<!-- custom-component.FXML -->
<input model:value="{{myValue}}" />

这个自定义组件将自身的 myValue 属性双向绑定到了组件内输入框的 value 属性上。这样,如果页面这样使用这个组件:

<custom-component model:my-value="{{pageValue}}" />

当输入框的值变更时,自定义组件的 myValue 属性会同时变更,这样,页面的 this.data.pageValue 也会同时变更,页面 FXML 中所有绑定了 pageValue 的位置也会被一同更新。

# 5.2 在自定义组件中触发双向绑定更新

自定义组件还可以自己触发双向绑定更新,做法就是:使用 setData 设置自身的属性。例如:

// custom-component.js
Component({
  properties: {
    myValue: String
  },
  methods: {
    update: function() {
      // 更新 myValue
      this.setData({
        myValue: 'leaf'
      })
    }
  }
})

如果页面这样使用这个组件:

<custom-component model:my-value="{{pageValue}}" />

当组件使用 setData 更新 myValue 时,页面的 this.data.pageValue 也会同时变更,页面 FXML 中所有绑定了 pageValue 的位置也会被一同更新。

# 6. 基础组件

框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。详细介绍请参考组件文档。?

# 6.1 什么是组件

  • 组件是视图层的基本组成单元。
  • 一个组件通常包括 开始标签 和 结束标签,属性 用来修饰这个组件,内容 在两个标签之内。
<tagname property="value">
Content goes here ...
</tagname>

注意

所有组件与属性都是小写,以连字符-连接

属性类型

类型 描述 注解
Boolean 布尔值 组件写上该属性,不管是什么值都被当作 true;只有组件上没有该属性时,属性值才为false。如果属性值为变量,变量的值会被转换为Boolean类型
Number 数字 1, 2.5
String 字符串 "string"
Array 数组 [ 1, "string" ]
Object 对象 { key: value }
EventHandler 事件处理函数名 "handlerName" 是 Page 中定义的事件处理函数名
Any 任意属性

公共属性

所有组件都有以下属性

属性名 类型 描述 注解
id String 组件的唯一标示 保持整个页面唯一
class String 组件的样式类 在对应的 FTSS 中定义的样式类
style String 组件的内联样式 可以动态设置的内联样式
hidden Boolean 组件是否显示 所有组件默认显示
data-* Any 自定义属性 组件上触发的事件时,会发送给事件处理函数
bind* / catch* EventHandler 组件的事件 详见事件

特殊属性

几乎所有组件都有各自定义的属性,可以对该组件的功能或样式进行修饰,请参考各个组件的定义。

# 7. 获取界面上的节点信息

# 7.1 FXML节点信息

节点信息查询 API 可以用于获取节点属性、样式、在界面上的位置等信息。

最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置。?

示例代码

const query = ft.createSelectorQuery()
query.select('#the-id').boundingClientRect(function(res){
  res.top // #the-id 节点的上边界坐标(相对于显示区域)
})
query.selectViewport().scrollOffset(function(res){
  res.scrollTop // 显示区域的竖直滚动位置
})
query.exec()

上述示例中, #the-id 是一个节点选择器,与 CSS 的选择器相近但略有区别,请参见 SelectorQuery.select 的相关说明。

在自定义组件或包含自定义组件的页面中,推荐使用 this.createSelectorQuery 来代替 ft.createSelectorQuery ,这样可以确保在正确的范围内选择节点。

# 7.2 FXML节点布局相交状态

节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组API常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。

这一组API涉及的主要概念如下。

  • 参照节点:监听的参照节点,取它的布局区域作为参照区域。如果有多个参照节点,则会取它们布局区域的 交集 作为参照区域。页面显示区域也可作为参照区域之一。
  • 目标节点:监听的目标,默认只能是一个节点(使用 selectAll 选项时,可以同时监听多个节点)。
  • 相交区域:目标节点的布局区域与参照区域的相交区域。
  • 相交比例:相交区域占参照区域的比例。
  • 阈值:相交比例如果达到阈值,则会触发监听器的回调函数。阈值可以有多个。 以下示例代码可以在目标节点(用选择器 .target-class 指定)每次进入或离开页面显示区域时,触发回调函数。

示例代码

Page({
  onLoad: function(){
    ft.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => {
      res.id // 目标节点 id
      res.dataset // 目标节点 dataset
      res.intersectionRatio // 相交区域占目标节点的布局区域的比例
      res.intersectionRect // 相交区域
      res.intersectionRect.left // 相交区域的左边界坐标
      res.intersectionRect.top // 相交区域的上边界坐标
      res.intersectionRect.width // 相交区域的宽度
      res.intersectionRect.height // 相交区域的高度
    })
  }
})

以下示例代码可以在目标节点(用选择器 .target-class 指定)与参照节点(用选择器 .relative-class 指定)在页面显示区域内相交或相离,且相交或相离程度达到目标节点布局区域的20%和50%时,触发回调函数。?

示例代码

Page({
  onLoad: function(){
    ft.createIntersectionObserver(this, {
      thresholds: [0.2, 0.5]
    }).relativeTo('.relative-class').relativeToViewport().observe('.target-class', (res) => {
      res.intersectionRatio // 相交区域占目标节点的布局区域的比例
      res.intersectionRect // 相交区域
      res.intersectionRect.left // 相交区域的左边界坐标
      res.intersectionRect.top // 相交区域的上边界坐标
      res.intersectionRect.width // 相交区域的宽度
      res.intersectionRect.height // 相交区域的高度
    })
  }
})

注意

与页面显示区域的相交区域并不准确代表用户可见的区域,因为参与计算的区域是“布局区域”,布局区域可能会在绘制时被其他节点裁剪隐藏(如遇祖先节点中 overflow 样式为 hidden 的节点)或遮盖(如遇 fixed 定位的节点)。

在自定义组件或包含自定义组件的页面中,推荐使用 this.createIntersectionObserver 来代替 ft.createIntersectionObserver ,这样可以确保在正确的范围内选择节点。

# 8. 响应显示区域变化

# 8.1 显示区域尺寸

显示区域指小程序界面中可以自由布局展示的区域。在默认情况下,小程序显示区域的尺寸自页面初始化起就不会发生变化。但以下两种方式都可以改变这一默认行为。

# 8.1.1 在手机上启用屏幕旋转支持

从小程序基础库版本 1.5.33 开始,小程序在手机上支持屏幕旋转。使小程序中的页面支持屏幕旋转的方法是:在 app.json 的 window 段中设置 "pageOrientation": "auto" ,或在页面 json 文件中配置 "pageOrientation": "auto" 。

以下是在单个页面 json 文件中启用屏幕旋转的示例。?

代码示例

{
  "pageOrientation": "auto"
}

如果页面添加了上述声明,则在屏幕旋转时,这个页面将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。

从小程序基础库版本 1.5.33 开始, pageOrientation 还可以被设置为 landscape ,表示固定为横屏显示。

# 8.1.2 在 iPad 上启用屏幕旋转支持

从小程序基础库版本 1.5.33 开始,在 iPad 上运行的小程序可以支持屏幕旋转。使小程序支持 iPad 屏幕旋转的方法是:在 app.json 中添加 "resizable": true 。?

代码示例

{
  "resizable": true
}

如果小程序添加了上述声明,则在屏幕旋转时,小程序将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。

注意

在 iPad 上不能单独配置某个页面是否支持屏幕旋转。

# 8.2 Media Query

有时,对于不同尺寸的显示区域,页面的布局会有所差异。此时可以使用 media query 来解决大多数问题。

代码示例

.my-class {
  width: 40px;
}

@media (min-width: 480px) {
  /* 仅在 480px 或更宽的屏幕上生效的样式规则 */
  .my-class {
    width: 200px;
  }
}

# 8.3 屏幕旋转事件

有时,仅仅使用 media query 无法控制一些精细的布局变化。此时可以使用 js 作为辅助。

在 js 中读取页面的显示区域尺寸,可以使用 selectorQuery.selectViewport 。

页面尺寸发生改变的事件,可以使用页面的 onResize 来监听。对于自定义组件,可以使用 resize 生命周期来监听。回调函数中将返回显示区域的尺寸信息。(从基础库版本 1.5.33 开始支持。)?

代码示例

Page({
  onResize(res) {
    res.size.windowWidth // 新的显示区域宽度
    res.size.windowHeight // 新的显示区域高度
  }
})

# 9. 页面路由

在小程序中所有页面的路由全部由小程序框架进行管理。

# 9.1 页面栈

框架以栈的形式维护了当前所有页面。 当发生路由切换的时候,页面栈的表现如下:

路由方式 页面栈表现
初始化 新页面入栈
打开新页面 新页面入栈
页面重定向 当前页面出栈,新页面入栈
页面返回 页面不断出栈,直到目标返回页
Tab 切换 页面全部出栈,只留下新的 Tab 页面
重加载 页面全部出栈,只留下新的页面

getCurrentPages()

getCurrentPages() 函数用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。?

注意

  1. 不要尝试手动修改页面栈,会导致路由以及页面状态错误。
  2. 不要在 App.onLaunch 的时候调用 getCurrentPages(),此时 page 还没有生成。

路由方式

对于路由的触发方式以及页面生命周期函数如下:

路由方式 触发时机 路由前页面 路由后页面
初始化 小程序打开的第一个页面 onLoad, onShow
打开新页面 调用 API ft.navigateTo 或使用组件 <navigator open-type="navigateTo"/> onHide onLoad, onShow
页面重定向 调用 API ft.redirectTo 或使用组件 <navigator open-type="redirectTo"/> onUnload onLoad, onShow
页面返回 调用 API ft.navigateBack 或使用组件 <navigator open-type="navigateBack">或用户按左上角返回按钮 onUnload onShow
Tab 切换 调用 API ft.switchTab 或使用组件<navigator open-type="switchTab"/>或用户切换 Tab 各种情况请参考下表
重启动 调用 API ft.reLaunch 或使用组件 <navigator open-type="reLaunch"/> onUnload onLoad, onShow

Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):

当前页面 路由后页面 触发的生命周期(按顺序)
A A Nothing happend
A B A.onHide(), B.onLoad(), B.onShow()
A B(再次打开) A.onHide(), B.onShow()
C A C.onUnload(), A.onShow()
C B C.onUnload(), B.onLoad(), B.onShow()
D B D.onUnload(), C.onUnload(), B.onLoad(), B.onShow()
D(从转发进入) A D.onUnload(), A.onLoad(), A.onShow()
D(从转发进入) B D.onUnload(), B.onLoad(), B.onShow()

提示

  • navigateTo, redirectTo 只能打开非 tabBar 页面。
  • switchTab 只能打开 tabBar 页面。
  • reLaunch 可以打开任意页面。
  • 页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
  • 调用页面路由带的参数可以在目标页面的 onLoad 中获取。

# 10. 动画

# 10.1 界面动画的常见方式

在小程序中,通常可以使用 CSS 渐变 和 CSS 动画 来创建简易的界面动画。

在开发者工具中预览效果

动画过程中,可以使用 bindtransitionend bindanimationstart bindanimationiteration bindanimationend 来监听动画事件。

事件名 含义
transitionend CSS 渐变结束或 wx.createAnimation 结束一个阶段
animationstart CSS 动画开始
animationiteration CSS 动画结束一个阶段
animationend CSS 动画结束

注意:这几个事件都不是冒泡事件,需要绑定在真正发生了动画的节点上才会生效。

同时,还可以使用 wx.createAnimation 接口来动态创建简易的动画效果。(新版小程序基础库中推荐使用下述的关键帧动画接口代替。)

# 10.2 关键帧动画

还有一种更友好的动画创建方式,用于代替旧的 wx.createAnimation 。它具有更好的性能和更可控的接口。

在页面或自定义组件中,当需要进行关键帧动画时,可以使用 this.animate 接口:

this.animate(selector, keyframes, duration, callback)

参数说明

属性 类型 默认值 必填 说明
selector String 选择器(同 SelectorQuery.select 的选择器格式)
keyframes Array 关键帧信息
duration Number 动画持续时长(毫秒为单位)
callback function 动画完成后的回调函数

keyframes 中对象的结构

属性 类型 默认值 必填 说明
offset Number 关键帧的偏移,范围[0-1]
ease String linear 动画缓动函数
transformOrigin String 基点位置,即 CSS transform-origin
backgroundColor String 背景颜色,即 CSS background-color
bottom Number/String 底边位置,即 CSS bottom
height Number/String 高度,即 CSS height
left Number/String 左边位置,即 CSS left
width Number/String 宽度,即 CSS width
opacity Number 不透明度,即 CSS opacity
right Number 右边位置,即 CSS right
top Number/String 顶边位置,即 CSS top
matrix Array 变换矩阵,即 CSS transform matrix
matrix3d Array 三维变换矩阵,即 CSS transform matrix3d
rotate Number 旋转,即 CSS transform rotate
rotate3d Array 三维旋转,即 CSS transform rotate3d
rotateX Number X 方向旋转,即 CSS transform rotateX
rotateY Number Y 方向旋转,即 CSS transform rotateY
rotateZ Number Z 方向旋转,即 CSS transform rotateZ
scale Array 缩放,即 CSS transform scale
scale3d Array 三维缩放,即 CSS transform scale3d
scaleX Number X 方向缩放,即 CSS transform scaleX
scaleY Number Y 方向缩放,即 CSS transform scaleY
scaleZ Number Z 方向缩放,即 CSS transform scaleZ
skew Array 倾斜,即 CSS transform skew
skewX Number X 方向倾斜,即 CSS transform skewX
skewY Number Y 方向倾斜,即 CSS transform skewY
translate Array 位移,即 CSS transform translate
translate3d Array 三维位移,即 CSS transform translate3d
translateX Number X 方向位移,即 CSS transform translateX
translateY Number Y 方向位移,即 CSS transform translateY
translateZ Number Z 方向位移,即 CSS transform translateZ

# 示例代码

  this.animate('#container', [
    { opacity: 1.0, rotate: 0, backgroundColor: '#FF0000' },
    { opacity: 0.5, rotate: 45, backgroundColor: '#00FF00'},
    { opacity: 0.0, rotate: 90, backgroundColor: '#FF0000' },
    ], 5000, function () {
      this.clearAnimation('#container', { opacity: true, rotate: true }, function () {
        console.log("清除了#container上的opacity和rotate属性")
      })
  }.bind(this))

  this.animate('.block', [
    { scale: [1, 1], rotate: 0, ease: 'ease-out'  },
    { scale: [1.5, 1.5], rotate: 45, ease: 'ease-in', offset: 0.9},
    { scale: [2, 2], rotate: 90 },
  ], 5000, function () {
    this.clearAnimation('.block', function () {
      console.log("清除了.block上的所有动画属性")
    })
  }.bind(this))

调用 animate API 后会在节点上新增一些样式属性覆盖掉原有的对应样式。如果需要清除这些样式,可在该节点上的动画全部执行完毕后使用 this.clearAnimation 清除这些属性。

this.clearAnimation(selector, options, callback)

参数说明

属性 类型 默认值 必填 说明
selector String 选择器(同 SelectorQuery.select 的选择器格式)
options Object 需要清除的属性,不填写则全部清除
callback Function 清除完成后的回调函数

# 10.3 高级的动画方式

在一些复杂场景下,上述的动画方法可能并不适用。

WXS 响应事件 的方式可以通过使用 WXS 来响应事件的方法来动态调整节点的 style 属性。通过不断改变 style 属性的值可以做到动画效果。同时,这种方式也可以根据用户的触摸事件来动态地生成动画。

连续使用 setData 来改变界面的方法也可以达到动画的效果。这样可以任意地改变界面,但通常会产生较大的延迟或卡顿,甚至导致小程序僵死。此时可以通过将页面的 setData 改为 自定义组件 中的 setData 来提升性能。

# 11. 初始渲染缓存

# 11.1 初始渲染缓存工作原理

小程序页面的初始化分为两个部分。

  • 逻辑层初始化:载入必需的小程序代码、初始化页面 this 对象(也包括它涉及到的所有自定义组件的 this 对象)、将相关数据发送给视图层。
  • 视图层初始化:载入必需的小程序代码,然后等待逻辑层初始化完毕并接收逻辑层发送的数据,最后渲染页面。

在启动页面时,尤其是小程序冷启动、进入第一个页面时,逻辑层初始化的时间较长。在页面初始化过程中,用户将看到小程序的标准载入画面(冷启动时)或可能看到轻微的白屏现象(页面跳转过程中)。

启用初始渲染缓存,可以使视图层不需要等待逻辑层初始化完毕,而直接提前将页面初始 data 的渲染结果展示给用户,这可以使得页面对用户可见的时间大大提前。它的工作原理如下:

  • 在小程序页面第一次被打开后,将页面初始数据渲染结果记录下来,写入一个持久化的缓存区域(缓存可长时间保留,但可能因为小程序更新、基础库更新、储存空间回收等原因被清除);
  • 在这个页面被第二次打开时,检查缓存中是否还存有这个页面上一次初始数据的渲染结果,如果有,就直接将渲染结果展示出来;
  • 如果展示了缓存中的渲染结果,这个页面暂时还不能响应用户事件,等到逻辑层初始化完毕后才能响应用户事件。

利用初始渲染缓存,可以:

  • 快速展示出页面中永远不会变的部分,如导航栏;
  • 预先展示一个骨架页,提升用户体验;
  • 展示自定义的加载提示;

# 11.2 支持的组件

在初始渲染缓存阶段中,复杂组件不能被展示或不能响应交互。

目前支持的内置组件:

  • <view />
  • <text />
  • <button />
  • <image />
  • <scroll-view />
  • <rich-text /> 自定义组件本身可以被展示(但它们里面用到的内置组件也遵循上述限制)。

# 11.3 静态初始渲染缓存

若想启用初始渲染缓存,最简单的方法是在页面的json文件中添加配置项 "initialRenderingCache": "static"

{
  "initialRenderingCache": "static"
}

如果想要对所有页面启用,可以在app.jsonwindow配置段中添加这个配置:

{
  "window": {
    "initialRenderingCache": "static"
  }
}

添加这个配置项之后,在手机中预览小程序首页,然后杀死小程序再次进入,就会通过初始渲染缓存来渲染首页。

请注意

这种情况下,初始渲染缓存记录的是页面data应用在页面FXML上的结果,不包含任何setData的结果。

例如,如果想要在页面中展示出“正在加载”几个字,这几个字受到loading数据字段控制:

<view wx:if="{{loading}}">正在加载</view>

这种情况下,loading应当在data中指定为true,如:

// 正确的做法
Page({
  data: {
    loading: true
  }
})

而不能通过setDataloading置为true

// 错误的做法!不要这么做!
Page({
  data: {},
  onLoad: function() {
    this.setData({
      loading: true
    })
  }
})

换而言之,这种做法只包含页面data的渲染结果,即页面的纯静态成分。

# 11.4 在初始渲染缓存中添加动态内容

有些场景中,只是页面data的渲染结果会比较局限。有时会想要额外展示一些可变的内容,如展示的广告图片 URL 等。

这种情况下可以使用“动态”初始渲染缓存的方式。首先,配置"initialRenderingCache": "dynamic"

{
  "initialRenderingCache": "dynamic"
}

此时,初始渲染缓存不会被自动启用,还需要在页面中调用this.setInitialRenderingCache(dynamicData)才能启用。其中,dynamicData是一组数据,与data一起参与页面 FXML 渲染。

Page({
  data: {
    loading: true
  },
  onReady: function() {
    this.setInitialRenderingCache({
      loadingHint: '正在加载' // 这一部分数据将被应用于界面上,相当于在初始 data 基础上额外进行一次 setData
    })
  }
})

<view wx:if="{{loading}}">{{loadingHint}}</view>

从原理上说,在动态生成初始渲染缓存的方式下,页面会在后台使用动态数据重新渲染一次,因而开销相对较大。因而要尽量避免频繁调用this.setInitialRenderingCache,如果在一个页面内多次调用,仅最后一次调用生效。

注意:

  • this.setInitialRenderingCache调用时机不能早于PageonReadyComponentready生命周期,否则可能对性能有负面影响。
  • 如果想禁用初始渲染缓存,调用this.setInitialRenderingCache(null)
分泌物是褐色是什么原因 拍肺部片子挂什么科 时间是什么 宋朝后面是什么朝代 国色天香是什么生肖
紫荆花代表什么生肖 酗酒是什么意思 手发热是什么原因 补钙最好的食物是什么 什么是孢子
肺部疼痛什么原因 乳腺增生结节吃什么药效果好 卫生纸筒可以做什么 打边炉是什么意思 pa什么意思
双子座男生喜欢什么样的女生 把碗打碎了有什么征兆 偏安一隅是什么意思 日本为什么投降 桑叶长什么样子图片
bg是什么意思hcv9jop3ns3r.cn 聚乙二醇是什么东西hcv8jop9ns7r.cn 青枝骨折属于什么骨折hcv8jop6ns0r.cn 抽筋什么原因hcv8jop7ns5r.cn 鸳鸯浴是什么意思hcv8jop0ns0r.cn
尿蛋白定量高说明什么hcv9jop6ns1r.cn 北京朝阳医院擅长什么imcecn.com 车工是做什么的hcv9jop3ns4r.cn 孕妇血糖高有什么症状wmyky.com 口周读什么hcv8jop0ns1r.cn
预检是什么意思shenchushe.com 生粉和淀粉有什么区别weuuu.com 血压偏低吃什么hcv7jop9ns7r.cn 费力不讨好是什么生肖hcv9jop7ns4r.cn 今年25岁属什么生肖的hcv8jop7ns8r.cn
娇喘什么意思hcv9jop1ns9r.cn 火疖子用什么药膏hcv7jop6ns9r.cn 头晕是什么症状引起的hcv9jop2ns4r.cn 西米露是什么做的shenchushe.com peep是什么意思hcv9jop2ns6r.cn
百度