tencent cloud

文档反馈

渲染层

最后更新时间:2024-07-12 18:58:47
    框架的渲染层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反映成视图,同时将渲染层的事件发送给逻辑层。
    WXML(WeiXin Markup language) 用于描述页面的结构。
    WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
    WXSS(WeiXin Style Sheet) 用于描述页面的样式。
    组件(Component)是视图的基本组成单元。

    1. WXML

    WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件事件系统可以构建出页面的结构。
    要完整了解 WXML 语法,请参考 WXML 语法参考
    用以下一些简单的例子来看看 WXML 具有什么能力:

    1.1 数据绑定

    <!-- wxml -->
    <view> {{message}} </view>
    // page.js
    Page({
    data: {
    message: 'Hello MINA!'
    }
    })

    1.2 列表渲染

    <!--wxml-->
    <view wx:for="{{array}}"> {{item}} </view>

    1.3 条件渲染

    <!--wxml-->
    <view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
    <view wx:elif="{{view == 'APP'}}"> APP </view>
    <view wx:else="{{view == 'MINA'}}"> MINA </view>
    // page.js
    Page({
    data: {
    view: 'MINA'
    }
    })

    1.4 模板

    <!--wxml-->
    <template name="staffName">
    <view>
    FirstName: {{firstName}}, LastName: {{lastName}}
    </view>
    </template>
    
    <template is="staffName" data="{{...staffA}}"></template>
    <template is="staffName" data="{{...staffB}}"></template>
    <template is="staffName" data="{{...staffC}}"></template>
    // page.js
    Page({
    data: {
    staffA: {firstName: 'Hulk', lastName: 'Hu'},
    staffB: {firstName: 'Shang', lastName: 'You'},
    staffC: {firstName: 'Gideon', lastName: 'Lin'}
    }
    })

    2. WXSS

    WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
    WXSS 用来决定 WXML 的组件应该怎么显示。
    为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
    与 CSS 相比,WXSS 扩展的特性有:
    尺寸单位
    样式导入
    注意:
    iOS 8 及以下的 iOS 版本,如使用 flexbox 布局,需添加display: -webkit-flex属性。

    2.1 尺寸单位

    rpx(responsive pixel):可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
    根据不同的设备屏幕宽度,rpx 和 px 的换算关系也会有所不同。例如:
    设备
    屏幕宽度
    rpx 换算 px(屏幕宽度/750)
    px 换算 rpx (750/屏幕宽度)
    iPhone5
    320px
    1rpx = 0.42px
    1px = 2.34rpx
    iPhone6
    375px
    1rpx = 0.5px
    1px = 2rpx
    iPhone6 Plus
    414px
    1rpx = 0.552px
    1px = 1.81rpx
    说明:
    建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
    注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

    2.2 样式导入

    使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用;表示语句结束。
    示例代码:
    /** common.wxss **/
    .small-p {
    padding:5px;
    }
    /** app.wxss **/
    @import "common.wxss";
    .middle-p {
    padding:15px;
    }

    2.3 内联样式

    框架组件上支持使用 style、class 属性来控制组件的样式。
    style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
    /** common.wxss **/
    .small-p {
    padding:5px;
    }
    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.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

    3. WXS

    WXS(WeiXin Script)是内联在 WXML 中的脚本段。通过 WXS 可以在模板中内联少量处理脚本,丰富模板的数据预处理能力。另外,WXS 还可以用来编写简单的 WXS 事件响应函数
    从语法上看,WXS 类似于有少量限制的 JavaScript 。要完整了解 WXS 语法,请参考WXS - 介绍
    以下是一些使用 WXS 的简单示例。 页面渲染:
    <!--wxml-->
    <wxs module="m1">
    var msg = "hello world";
    
    module.exports.message = msg;
    </wxs>
    
    <view> {{m1.message}} </view>
    页面输出:
    hello world
    数据处理:
    // page.js
    Page({
    data: {
    array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
    }
    })
    <!--wxml-->
    <!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
    <wxs 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;
    </wxs>
    
    <!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
    <view> {{m1.getMax(array)}} </view>
    页面输出:
    5

    4. 事件系统

    4.1 什么是事件

    事件是渲染层到逻辑层的通讯方式。
    事件可以将用户的行为反馈到逻辑层进行处理。
    事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
    事件对象可以携带额外信息,如 id, dataset, touches。

    4.2 事件的使用方式

    在组件中绑定一个事件处理函数。
    bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
    <view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
    在相应的Page定义中写上相应的事件处理函数,参数是event
    Page({
    tapName: function(event) {
    console.log(event)
    }
    })
    可以看到log出来的信息大致如下:
    {
    "type":"tap",
    "timeStamp":895,
    "target": {
    "id": "tapTest",
    "dataset": {
    "hi":"Weixin"
    }
    },
    "currentTarget": {
    "id": "tapTest",
    "dataset": {
    "hi":"Weixin"
    }
    },
    "detail": {
    "x":53,
    "y":14
    },
    "touches":[{
    "identifier":0,
    "pageX":53,
    "pageY":14,
    "clientX":53,
    "clientY":14
    }],
    "changedTouches":[{
    "identifier":0,
    "pageX":53,
    "pageY":14,
    "clientX":53,
    "clientY":14
    }]
    }

    4.3 使用WXS函数响应事件

    4.3.1 背景

    有频繁用户交互的效果在小程序上表现是比较卡顿的,例如页面有2个元素 A 和 B,用户在 A 上做 touchmove 手势,要求 B 也跟随移动,movable-view 就是一个典型的例子。一次 touchmove 事件的响应过程为:
    touchmove 事件从渲染层(Webview)抛到逻辑层(App Service);
    逻辑层(App Service)处理 touchmove 事件,再通过 setData 来改变 B 的位置。
    一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟。

    4.3.2 解决方案

    本方案基本的思路是减少通信的次数,让事件在渲染层(Webview)响应。小程序的框架分为渲染层(Webview)和逻辑层(App Service),这样分层的目的是管控,开发者的代码只能运行在逻辑层(App Service),而这个思路就必须要让开发者的代码运行在渲染层(Webview)。
    使用 WXS 函数用来响应小程序事件,目前只能响应内置组件的事件,不支持自定义组件事件。
    WXS 函数的除了纯逻辑的运算,还可以通过封装好的 ComponentDescriptor 实例来访问以及设置组件的 class 和样式,对于交互动画,设置 style 和 class 足够了。
    WXS 函数接受2个参数,第一个是 event,在原有的 event 的基础上加了event.instance对象,第二个参数是ownerInstanceevent.instance一样是一个ComponentDescriptor对象。具体使用如下:
    在组件中绑定和注册事件处理的 WXS 函数:
    <wxs module="wxs" src="./test.wxs"></wxs>
    <view id="tapTest" data-hi="Weixin" bindtap="{{wxs.tapName}}"> Click me! </view>
    **注:绑定的WXS函数必须用{{}}括起来**
    test.wxs 文件实现 tapName 函数:
    function tapName(event, ownerInstance) {
    console.log('tap Weixin', JSON.stringify(event))
    }
    module.exports = {
    tapName: tapName
    }
    ownerInstance 包含了一些方法,可以设置组件的样式和 class。
    WXS 函数的例子如下:
    var wxsFunction = function(event, ownerInstance) {
    var instance = ownerInstance.selectComponent('.classSelector') // 返回组件的实例
    instance.setStyle({
    "font-size": "14px" // 支持rpx
    })
    instance.getDataset()
    instance.setClass(className)
    // ...
    return false // 不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault
    }
    其中入参 event 是小程序事件对象基础上多了 event.instance 来表示触发事件的组件的 ComponentDescriptor 实例。
    ownerInstance 表示的是触发事件的组件所在的组件的 ComponentDescriptor 实例,如果触发事件的组件是在页面内的,则 ownerInstance 表示的是页面实例。
    ComponentDescriptor 目前支持的 API 如下:
    方法
    参数
    描述
    selectComponent
    selector 对象
    返回组件的 ComponentDescriptor 实例。
    selectAllComponents
    selector对象数组
    返回组件的 ComponentDescriptor 实例数组。
    setStyle
    Object/string
    设置组件样式,支持rpx。设置的样式优先级比组件 wxml 里面定义的样式高。不能设置最顶层页面的样式。
    addClass/removeClass/hasClass
    string
    设置组件的 class。设置的 class 优先级比组件 wxml 里面定义的 class 高。不能设置最顶层页面的 class。
    getDataset
    返回当前组件/页面的 dataset 对象。
    callMethod
    (funcName:string, args:object)
    调用当前组件/页面在逻辑层(App Service)定义的函数。funcName 表示函数名称,args 表示函数的参数。
    getState
    返回一个 object 对象,当有局部变量需要存储起来后续使用的时候用这个方法。
    triggerEvent
    (eventName, detail)
    和组件的triggerEvent一致。

    4.3.3 使用方法

    WXML 定义事件:
    <wxs module="test" src="./test.wxs"></wxs>
    <view
    change:prop="{{test.propObserver}}"
    prop="{{propValue}}"
    bindtouchmove="{{test.touchmove}}"
    class="movable">
    </view>
    上面的 change:prop(属性前面带 change: 前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}} 括起来。类似 Component 定义的 properties 里面的 observer 属性,在 setData({propValue: newValue}) 调用之后会触发。
    注意:
    WXS 函数必须用 {{}} 括起来。当 prop 的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次 WxsPropObserver 的函数。
    WXS 文件 test.wxs 里面定义并导出事件处理函数和属性改变触发的函数:
    module.exports = {
    touchmove: function(event, instance) {
    console.log('log event', JSON.stringify(event))
    },
    propObserver: function(newValue, oldValue, ownerInstance, instance) {
    console.log('prop observer', newValue, oldValue)
    }
    }

    4.4 事件详解

    4.4.1 事件分类

    事件分为冒泡事件和非冒泡事件:
    冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递;
    非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
    WXML的冒泡事件列表:
    类型
    触发条件
    touchstart
    手指触摸动作开始
    touchmove
    手指触摸后移动
    touchcancel
    手指触摸动作被打断,如来电提醒,弹窗
    touchend
    手指触摸动作结束
    tap
    手指触摸后马上离开
    longpress
    手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发
    longtap
    手指触摸后,超过350ms再离开(推荐使用 longpress 事件代替)
    transitionend
    会在 WXSS transition 或 wx.createAnimation 动画结束后触发
    animationstart
    会在一个 WXSS animation 动画开始时触发
    animationiteration
    会在一个 WXSS animation 一次迭代结束时触发
    animationend
    会在一个 WXSS animation 动画完成时触发
    touchforcechange
    在支持 3D Touch 的 iPhone 设备,重按时会触发
    说明:
    除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(详见 组件概览)

    4.4.2 普通事件绑定

    事件绑定的写法类似于组件的属性,如:
    <view bindtap="handleTap">
    Click here!
    </view>
    如果用户点击这个 view ,则页面的 handleTap 会被调用。
    事件绑定函数可以是一个数据绑定,如:
    <view bindtap="{{ handlerName }}">
    Click here!
    </view>
    此时,页面的 this.data.handlerName 必须是一个字符串,指定事件处理函数名;如果它是个空字符串,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)。
    在大多数组件和自定义组件中, bind 后可以紧跟一个冒号,其含义不变,如 bind:tap

    4.4.3 绑定并阻止事件冒泡

    bind外,也可以用catch来绑定事件。与bind不同,catch会阻止事件向上冒泡。
    例如在下边这个例子中,单击 inner view 会先后调用handleTap3handleTap2(因为 tap 事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),单击 middle view 会触发handleTap2,单击 outer view 会触发handleTap1
    <view id="outer" bindtap="handleTap1">
    outer view
    <view id="middle" catchtap="handleTap2">
    middle view
    <view id="inner" bindtap="handleTap3">
    inner view
    </view>
    </view>
    </view>

    4.4.4 互斥事件绑定

    自基础库版本 1.5.44 起,除 bindcatch 外,还可以使用 mut-bind 来绑定事件。一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发。
    换而言之,所有 mut-bind 是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响 bindcatch 的绑定效果。
    例如在下边这个例子中,单击 inner view 会先后调用 handleTap3handleTap2 ,单击 middle view 会调用 handleTap2handleTap1
    <view id="outer" mut-bind:tap="handleTap1">
    outer view
    <view id="middle" bindtap="handleTap2">
    middle view
    <view id="inner" mut-bind:tap="handleTap3">
    inner view
    </view>
    </view>
    </view>

    4.4.5 事件的捕获阶段

    触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。
    在下面的代码中,单击 inner view 会先后调用handleTap2handleTap4handleTap3handleTap1
    <view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
    outer view
    <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
    </view>
    </view>
    如果将上面代码中的第一个 capture-bind 改为 capture-catch,将只触发 handleTap2。
    <view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
    outer view
    <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
    </view>
    </view>

    4.4.6 事件对象

    如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。
    BaseEvent 基础事件对象属性列表:
    属性
    类型
    说明
    type
    String
    事件类型
    timeStamp
    Integer
    事件生成时的时间戳
    target
    Object
    触发事件的组件的一些属性值集合
    currentTarget
    Object
    当前组件的一些属性值集合
    CustomEvent 自定义事件对象属性列表(继承 BaseEvent):
    属性
    类型
    说明
    detail
    Object
    额外的信息
    TouchEvent 触摸事件对象属性列表(继承 BaseEvent):
    属性
    类型
    说明
    touches
    Array
    触摸事件,当前停留在屏幕中的触摸点信息的数组
    changedTouches
    Array
    触摸事件,当前变化的触摸点信息的数组
    特殊事件:canvas 中的触摸事件不可冒泡,所以没有 currentTarget。

    4.4.7 type

    代表事件的类型。

    4.4.8 timeStamp

    页面打开到触发事件所经过的毫秒数。

    4.4.9 target

    触发事件的源组件。
    属性
    类型
    说明
    id
    String
    事件源组件的 id
    dataset
    Object
    事件源组件上由 data - 开头的自定义属性组成的集合

    4.4.10 currentTarget

    事件绑定的当前组件。
    属性
    类型
    说明
    id
    String
    当前组件的 id
    dataset
    Object
    当前组件上由 data - 开头的自定义属性组成的集合
    说明:
    target 和 currentTarget 可以参考上例中,单击 inner view 时,handleTap3 收到的事件对象 target 和 currentTarget 都是 inner,而 handleTap2 收到的事件对象 target 就是 inner,currentTarget 就是 middle。

    4.4.11 dataset

    在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
    在 WXML 中,这些自定义数据以 data- 开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:
    data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType ;
    data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype 。
    代码示例:
    <view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
    
    Page({
    bindViewTap:function(event){
    event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
    event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
    }
    })

    4.4.12 touches

    touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。表示当前停留在屏幕上的触摸点。
    Touch 对象
    属性
    类型
    说明
    identifier
    Number
    触摸点的标识符
    pageX, pageY
    Number
    距离文档左上角的距离,文档的左上角为原点,横向为X轴,纵向为Y轴
    clientX, clientY
    Number
    距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴
    CanvasTouch对象
    属性
    类型
    说明
    identifier
    Number
    触摸点的标识符
    x, y
    Number
    距离 Canvas 左上角的距离,Canvas 的左上角为原点 ,横向为X轴,纵向为Y轴

    4.4.13 changedTouches

    changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)。

    4.4.14 detail

    自定义事件所携带的数据,如表单组件的提交事件会携带用户的输入,媒体的错误事件会携带错误信息,详见 组件概览 定义中各个事件的定义。
    单击事件的detail 带有的 x, y 同 pageX, pageY 代表距离文档左上角的距离。

    5. 基础组件

    框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。详细介绍请参考 组件概览
    什么是组件:
    组件是视图层的基本组成单元。
    一个组件通常包括开始标签结束标签属性用来修饰这个组件,内容在两个标签之内。
    <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
    组件的样式类
    在对应的 WXSS 中定义的样式类
    style
    String
    组件的内联样式
    可以动态设置的内联样式
    hidden
    Boolean
    组件是否显示
    所有组件默认显示
    data-*
    Any
    自定义属性
    组件上触发的事件时,会发送给事件处理函数
    bind* / catch*
    EventHandler
    组件的事件
    详见事件
    特殊属性
    几乎所有组件都有各自定义的属性,可以对该组件的功能或样式进行修饰,请参考各个 组件概览 的定义。

    6. 获取界面上的节点信息

    6.1 WXML节点信息

    节点信息查询 API 可以用于获取节点属性、样式、在界面上的位置等信息。
    最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置。
    示例代码:
    const query = wx.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 来代替 wx.createSelectorQuery,这样可以确保在正确的范围内选择节点。

    6.2 WXML节点布局相交状态

    节点布局相交状态 API 可用于监听两个或多个组件节点在布局位置上的相交状态。这一组 API 常常可以用于推断某些节点是否可以被用户看见、有多大比例可以被用户看见。
    这一组 API 涉及的主要概念如下。
    参照节点:监听的参照节点,取它的布局区域作为参照区域。如果有多个参照节点,则会取它们布局区域的 交集 作为参照区域。页面显示区域也可作为参照区域之一;
    目标节点:监听的目标,默认只能是一个节点(使用 selectAll 选项时,可以同时监听多个节点);
    相交区域:目标节点的布局区域与参照区域的相交区域;
    相交比例:相交区域占参照区域的比例;
    阈值:相交比例如果达到阈值,则会触发监听器的回调函数。阈值可以有多个;
    以下示例代码可以在目标节点(用选择器 .target-class指定)每次进入或离开页面显示区域时,触发回调函数。
    示例代码:
    Page({
    onLoad: function(){
    wx.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(){
    wx.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 来代替 wx.createIntersectionObserver ,这样可以确保在正确的范围内选择节点。

    7. 响应显示区域变化

    7.1 显示区域尺寸

    显示区域指小程序界面中可以自由布局展示的区域。在默认情况下,小程序显示区域的尺寸自页面初始化起就不会发生变化。但以下三种方式都可以改变这一默认行为。
    在手机上启用屏幕旋转支持
    小程序在手机上支持屏幕旋转。使小程序中的页面支持屏幕旋转的方法是:在 app.jsonwindow 段中设置 "pageOrientation": "auto" ,或在页面 json 文件中配置 "pageOrientation": "auto"
    以下是在单个页面 json 文件中启用屏幕旋转的示例。
    代码示例:
    {
    "pageOrientation": "auto"
    }
    如果页面添加了上述声明,则在屏幕旋转时,这个页面将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。pageOrientation 还可以被设置为 landscape ,表示固定为横屏显示。
    在iPad上启用屏幕旋转支持
    在 iPad 上运行的小程序可以支持屏幕旋转。使小程序支持 iPad 屏幕旋转的方法是:在 app.json 中添加 "resizable": true 。
    代码示例:
    {
    "resizable": true
    }
    如果小程序添加了上述声明,则在屏幕旋转时,小程序将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。
    注意:
    在 iPad 上不能单独配置某个页面是否支持屏幕旋转。

    7.2 Media Query

    有时,对于不同尺寸的显示区域,页面的布局会有所差异。此时可以使用 media query 来解决大多数问题。
    代码示例:
    .my-class {
    width: 40px;
    }
    
    @media (min-width: 480px) {
    /* 仅在 480px 或更宽的屏幕上生效的样式规则 */
    .my-class {
    width: 200px;
    }
    }

    7.3 屏幕旋转事件

    有时,仅仅使用 media query 无法控制一些精细的布局变化。此时可以使用 js 作为辅助。
    在 js 中读取页面的显示区域尺寸,可以使用 selectorQuery.selectViewport
    页面尺寸发生改变的事件,可以使用页面的 onResize 来监听。对于自定义组件,可以使用 resize 生命周期来监听。回调函数中将返回显示区域的尺寸信息。
    代码示例:
    Page({
    onResize(res) {
    res.size.windowWidth // 新的显示区域宽度
    res.size.windowHeight // 新的显示区域高度
    }
    })
    Component({
    pageLifetimes: {
    resize(res) {
    res.size.windowWidth // 新的显示区域宽度
    res.size.windowHeight // 新的显示区域高度
    }
    }
    })
    此外,还可以使用 wx.onWindowResize 来监听(但这不是推荐的方式)。

    8. 页面动画

    8.1 界面动画的常见方式

    在小程序中,通常可以使用 CSS 渐变 和 CSS 动画 来创建简易的界面动画。
    动画过程中,可以使用 bindtransitionend bindanimationstart bindanimationiteration bindanimationend 来监听动画事件。
    事件名
    含义
    transitionend
    CSS 渐变结束或 wx.createAnimation 结束一个阶段
    animationstart
    CSS 动画开始
    animationiteration
    CSS 动画结束一个阶段
    animationend
    CSS 动画结束
    说明:
    这几个事件都不是冒泡事件,需要绑定在真正发生了动画的节点上才会生效。
    同时,还可以使用 wx.createAnimation 接口来动态创建简易的动画效果(新版小程序基础库中推荐使用下述的关键帧动画接口代替)。

    8.2 高级的动画方式

    在一些复杂场景下,上述的动画方法可能并不适用。
    WXS 响应事件 的方式可以通过使用 WXS 来响应事件的方法来动态调整节点的 style 属性。通过不断改变 style 属性的值可以做到动画效果。同时,这种方式也可以根据用户的触摸事件来动态地生成动画。
    连续使用 setData 来改变界面的方法也可以达到动画的效果。这样可以任意地改变界面,但通常会产生较大的延迟或卡顿,甚至导致小程序僵死。此时可以通过将页面的 setData 改为 自定义组件 中的 setData 来提升性能。
    
    联系我们

    联系我们,为您的业务提供专属服务。

    技术支持

    如果你想寻求进一步的帮助,通过工单与我们进行联络。我们提供7x24的工单服务。

    7x24 电话支持