首页IT科技小程序界面图标(走进小程序【六】微信小程序架构之【视图层】万字详解)

小程序界面图标(走进小程序【六】微信小程序架构之【视图层】万字详解)

时间2025-05-04 10:40:57分类IT科技浏览3372
导读:🌟前言...

🌟前言

哈喽小伙伴们            ,上一期为大家讲解了一下小程序的架构之【逻辑层】篇          。今天接着上篇               ,给大家结合官方文档讲解一下小程序的架构之【视图层】;今天的文章有点长      ,很多知识点也是官方文档给我们提供的;也是想告诉大家         ,总有一天我们进入职场后               ,会甩开我们的拐棍或者离开我们的靠山独自去面对困难; 所以养成阅读官方文档的好习惯对我们日后工作也有很大的好处                  。好了         ,让我们一起来看看吧🤘

🌟小程序架构

小程序开发框架的目标是通过尽可能简单          、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务     。

整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)       。小程序提供了自己的视图层描述语言 WXML 和 WXSS      ,以及基于 JavaScript 的逻辑层框架               ,并在视图层与逻辑层间提供了数据传输和事件系统           ,让开发者能够专注于数据与逻辑                  。

View 层用来渲染页面结构   ,AppService 层用来逻辑处理                  、数据请求     、接口调用        。

它们在两个线程里运行    。

视图层和逻辑层通过系统层的 JSBridage

进行通信                ,逻辑层把数据变化通知到视图层             ,触发视图层页面更新,视图层把触发的事件通知到逻辑层进行业务处理 视图层使用 WebView 渲染              ,iOS中使用自带 WKWebView               ,在 Android 使用腾讯的 x5内核(基于 Blink)运行                 。 逻辑层使用在 iOS 中使用自带的 JSCore 运行   ,在 Android中使用腾讯的 x5 内核(基于 Blink)运行           。 开发工具使用 nw.js 同时提供了视图层和逻辑层的运行环境  。

🌟视图层 View

框架的视图层由 WXML 与 WXSS 编写            ,由组件来进行展示                。

将逻辑层的数据反映成视图               ,同时将视图层的事件发送给逻辑层              。

WXML(WeiXin Markup language) 用于描述页面的结构。

WXS(WeiXin Script) 是小程序的一套脚本语言      ,结合 WXML         ,可以构建出页面的结构             。

WXSS(WeiXin Style Sheet) 用于描述页面的样式                 。

组件(Component)是视图的基本组成单元  。

🌟WXML

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

要完整了解 WXML 语法      ,请参考WXML 语法参考                  。

用以下一些简单的例子来看看 WXML 具有什么能力:

🌟数据绑定

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

🌟列表渲染

<!--wxml--> <view wx:for="{{array}}"> {{item}} </view> // page.js Page({ data: { array: [1, 2, 3, 4, 5] } })

🌟条件渲染

<!--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 } })

🌟模板

<!--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} } })

🌟WXSS

WXSS (WeiXin Style Sheets)是一套样式语言               ,用于描述 WXML 的组件样式     。

WXSS 用来决定 WXML 的组件应该怎么显示       。 为了适应广大的前端开发者           ,WXSS 具有 CSS 大部分特性                  。同时为了更适合开发微信小程序   ,WXSS 对 CSS 进行了扩充以及修改        。

与 CSS 相比                ,WXSS 扩展的特性有:

尺寸单位 样式导入

🌟尺寸单位

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 作为视觉稿的标准           。 注意: 在较小的屏幕上不可避免的会有一些毛刺   ,请在开发时尽量避免这种情况  。

🌟样式导入

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

示例代码:

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

🌟内联样式

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

style:静态的样式统一写到 class 中。style 接收动态的样式      ,在运行时会进行解析         ,请尽量避免将静态的样式写进 style 中               ,以免影响渲染速度             。 class:用于指定样式规则         ,其属性值是样式规则中类选择器名(样式类名)的集合      ,样式类名不需要带上.               ,样式类名之间用空格分隔                 。 <view class="normal_view" />

🌟选择器

目前支持的选择器有:

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

🌟全局样式与局部样式

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

🌟WXS

WXS(WeiXin Script)是小程序的一套脚本语言             ,结合 WXML,可以构建出页面的结构                  。

注意事项

WXS 不依赖于运行时的基础库版本              ,可以在所有版本的小程序中运行     。 WXS 与 JavaScript 是不同的语言               ,有自己的语法   ,并不和 JavaScript 一致       。 WXS 的运行环境和其他 JavaScript 代码是隔离的            ,WXS 中不能调用其他 JavaScript 文件中定义的函数               ,也不能调用小程序提供的API                  。 由于运行环境的差异      ,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍        。在 android 设备上二者运行效率无差异    。

以下是一些使用 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

🌟事件

🌟什么是事件

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

🌟事件的使用方式

在组件中绑定一个事件处理函数。 如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 }] }

🌟使用WXS函数响应事件

从基础库版本2.4.4开始              ,支持使用WXS函数绑定事件               ,WXS函数接受2个参数   ,第一个是event            ,在原有的event的基础上加了event.instance对象               ,第二个参数是ownerInstance      ,和event.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函数响应事件         ,请点击查看详情                  。

🌟事件详解

🌟事件分类

事件分为冒泡事件和非冒泡事件:

冒泡事件:当一个组件上的事件被触发后      ,该事件会向父节点传递     。 非冒泡事件:当一个组件上的事件被触发后               ,该事件不会向父节点传递       。

WXML的冒泡事件列表:

类型 触发条件 最低版本 touchstart 手指触摸动作开始 touchmove 手指触摸后移动 touchcancel 手指触摸动作被打断           ,如来电提醒   ,弹窗 touchend 手指触摸动作结束 tap 手指触摸后马上离开 longpress 手指触摸后                ,超过350ms再离开             ,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 1.5.0 longtap 手指触摸后              ,超过350ms再离开(推荐使用longpress事件代替) transitionend 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 animationstart 会在一个 WXSS animation 动画开始时触发 animationiteration 会在一个 WXSS animation 一次迭代结束时触发 animationend 会在一个 WXSS animation 动画完成时触发 touchforcechange 在支持 3D Touch 的 iPhone 设备               ,重按时会触发 1.9.90

注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件   ,如 form 的submit事件            ,input 的input事件               ,scroll-view 的scroll事件      ,(详见各个组件)

🌟普通事件绑定

事件绑定的写法类似于组件的属性         ,如:

<view bindtap="handleTap"> Click here! </view>

如果用户点击这个 view               ,则页面的 handleTap 会被调用                  。

事件绑定函数可以是一个数据绑定         ,如:

<view bindtap="{{ handlerName }}"> Click here! </view>

此时      ,页面的 this.data.handlerName 必须是一个字符串               ,指定事件处理函数名;如果它是个空字符串           ,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)        。

自基础库版本 1.5.0 起   ,在大多数组件和自定义组件中                , bind 后可以紧跟一个冒号             ,其含义不变,如 bind:tap     。基础库版本 2.8.1 起              ,在所有组件中开始提供这个支持                 。

🌟绑定并阻止事件冒泡

除 bind 外               ,也可以用 catch 来绑定事件           。与 bind 不同   , catch 会阻止事件向上冒泡  。

例如在下边这个例子中            ,点击 inner view 会先后调用handleTap3和handleTap2(因为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>

🌟互斥事件绑定

自基础库版本 2.8.2 起         ,除 bind 和 catch 外      ,还可以使用 mut-bind 来绑定事件              。一个 mut-bind 触发后               ,如果事件冒泡到其他节点上           ,其他节点上的 mut-bind 绑定函数不会被触发   ,但 bind 绑定函数和 catch 绑定函数依旧会被触发。

换而言之                ,所有 mut-bind 是“互斥      ”的             ,只会有其中一个绑定函数被触发             。同时,它完全不影响 bind 和 catch 的绑定效果                 。

例如在下边这个例子中              ,点击 inner view 会先后调用 handleTap3 和 handleTap2                ,点击 middle view 会调用 handleTap2 和 handleTap1   。

<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>

🌟事件的捕获阶段

自基础库版本 1.5.0 起   ,触摸类事件支持捕获阶段          。捕获阶段位于冒泡阶段之前            ,且在捕获阶段中               ,事件到达节点的顺序与冒泡阶段恰好相反                  。需要在捕获阶段监听事件时      ,可以采用capture-bind        、capture-catch关键字         ,后者将中断捕获阶段和取消冒泡阶段     。

在下面的代码中               ,点击 inner view 会先后调用handleTap2    、handleTap4                 、handleTap3           、handleTap1       。

<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>

🌟事件对象

如无特殊说明      ,当组件触发事件时               ,逻辑层绑定该事件的处理函数会收到一个事件对象        。

🌟BaseEvent 基础事件对象属性列表: 属性 类型 说明 基础库版本 type String 事件类型 timeStamp Integer 事件生成时的时间戳 target Object 触发事件的组件的一些属性值集合 currentTarget Object 当前组件的一些属性值集合 mark Object 事件标记数据 2.7.1 🌟CustomEvent 自定义事件对象属性列表(继承 BaseEvent): 属性 类型 说明 detail Object 额外的信息 🌟TouchEvent触摸事件对象属性列表(继承 BaseEvent): 属性 类型 说明 touches Array 触摸事件           ,当前停留在屏幕中的触摸点信息的数组 changedTouches Array 触摸事件   ,当前变化的触摸点信息的数组 特殊事件: canvas 中的触摸事件不可冒泡                ,所以没有 currentTarget    。 🌟type

代表事件的类型                 。

timeStamp

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

🌟target

触发事件的源组件  。

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

事件绑定的当前组件                。

属性 类型 说明 id String 当前组件的id dataset Object 当前组件上由data-开头的自定义属性组成的集合

说明: target 和 currentTarget 可以参考上例中             ,点击 inner view 时,handleTap3 收到的事件对象 target 和 currentTarget 都是 inner              ,而 handleTap2 收到的事件对象 target 就是 inner               ,currentTarget 就是 middle              。

🌟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 // 大写会转为小写 } }) 🌟mark

在基础库版本 2.7.1 以上               ,可以使用 mark 来识别具体触发事件的 target 节点                  。此外           , mark 还可以用于承载一些自定义数据(类似于 dataset )     。

当事件触发时   ,事件冒泡路径上所有的 mark 会被合并                ,并返回给事件回调函数       。(即使事件不是冒泡事件             ,也会 mark                   。)

代码示例:

<view mark:myMark="last" bindtap="bindViewTap"> <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button> </view>

在上述 WXML 中,如果按钮被点击              ,将触发 bindViewTap 和 bindButtonTap 两个事件               ,事件携带的 event.mark 将包含 myMark 和 anotherMark 两项        。

Page({ bindViewTap: function(e) { e.mark.myMark === "last" // true e.mark.anotherMark === "leaf" // true } })

mark 和 dataset 很相似   ,主要区别在于: mark 会包含从触发事件的节点到根节点上所有的 mark: 属性值;而 dataset 仅包含一个节点的 data- 属性值    。

细节注意事项:

如果存在同名的 mark             ,父节点的 mark 会被子节点覆盖                 。 在自定义组件中接收事件时               , mark 不包含自定义组件外的节点的 mark            。 不同于 dataset       ,节点的 mark 不会做连字符和大小写转换  。 🌟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轴 🌟CanvasTouch changedTouches

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

🌟detail

自定义事件所携带的数据   ,如表单组件的提交事件会携带用户的输入            ,媒体的错误事件会携带错误信息               ,详见组件定义中各个事件的定义                 。

点击事件的detail 带有的 x, y 同 pageX, pageY 代表距离文档左上角的距离  。

🌟WXS响应事件

🌟背景

有频繁用户交互的效果在小程序上表现是比较卡顿的      ,例如页面有 2 个元素 A 和 B         ,用户在 A 上做 touchmove 手势               ,要求 B 也跟随移动         ,movable-view 就是一个典型的例子          。一次 touchmove 事件的响应过程为:

a                、touchmove 事件从视图层(Webview)抛到逻辑层(App Service)

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

一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染               ,通信的耗时比较大                  。此外 setData 渲染也会阻塞其它脚本执行           ,导致了整个用户交互的动画过程会有延迟     。

🌟实现方案

本方案基本的思路是减少通信的次数   ,让事件在视图层(Webview)响应       。小程序的框架分为视图层(Webview)和逻辑层(App Service)                ,这样分层的目的是管控             ,开发者的代码只能运行在逻辑层(App

Service),而这个思路就必须要让开发者的代码运行在视图层(Webview)              ,如下图所示的流程:

使用 WXS 函数用来响应小程序事件               ,目前只能响应内置组件的事件   ,不支持自定义组件事件                  。WXS 函数的除了纯逻辑的运算            ,还可以通过封装好的ComponentDescriptor 实例来访问以及设置组件的 class 和样式               ,对于交互动画      ,设置 style 和 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的定义如下:

方法 参数 描述 最低版本 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表示函数的参数                  。 requestAnimationFrame Function 和原生 requestAnimationFrame 一样     。用于设置动画       。 getState 无 返回一个object对象           ,当有局部变量需要存储起来后续使用的时候用这个方法                  。 triggerEvent (eventName, detail) 和组件的triggerEvent一致        。 getComputedStyle Array.<string> 参数与 SelectorQuery 的 computedStyle 一致    。 2.11.2 setTimeout (Function, Number) 与原生 setTimeout 一致                 。用于创建定时器           。 2.14.2 clearTimeout Number 与原生 clearTimeout 一致  。用于清除定时器                。 2.14.2 getBoundingClientRect 无 返回值与 SelectorQuery 的 boundingClientRect 一致              。 2.14.2

WXS 运行在视图层(Webview)   ,里面的逻辑毕竟能做的事件比较少                ,需要有一个机制和逻辑层(App Service)开发者的代码通信             ,上面的 callMethod 是 WXS 里面调用逻辑层(App Service)开发者的代码的方法,而 WxsPropObserver 是逻辑层(App Service)开发者的代码调用 WXS 逻辑的机制。

🌟使用方法

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) } } 目前还不支持原生组件的事件、input和textarea组件的 bindinput 事件 1.02.1901170及以后版本的开发者工具上支持交互动画               ,最低版本基础库是2.4.4 目前在WXS函数里面仅支持console.log方式打日志定位问题      ,注意连续的重复日志会被过滤掉                  。

🌟简易双向绑定

基础库 2.9.3 开始支持         ,低版本需做兼容处理     。

🌟双向绑定语法

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

<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 也会同时改变    。同时             , WXML 中所有绑定了 value 的位置也会被一同更新, 数据监听器 也会被正常触发                 。

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

只能是一个单一字段的绑定              ,如 <input model:value="值为 {{value}}" /> <input model:value="{{ a + b }}" />

都是非法的;

目前               ,尚不能 data 路径   ,如 <input model:value="{{ a.b }}" />

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

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

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

// custom-component.js Component({ properties: { myValue: String } }) <!-- custom-component.wxml --> <input model:value="{{myValue}}" />

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

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

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

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

自定义组件还可以自己触发双向绑定更新         ,做法就是:使用 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 也会同时变更               ,页面 WXML 中所有绑定了 pageValue 的位置也会被一同更新             。

🌟基础组件

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

🌟什么是组件:

组件是视图层的基本组成单元          。 组件自带一些功能与微信风格一致的样式                  。 一个组件通常包括 开始标签 和 结束标签   ,属性 用来修饰这个组件                ,内容 在两个标签之内     。 <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 组件的事件 详见事件

🌟特殊属性

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

🌟结语

这篇为小伙伴们讲解小程序的架构之【视图层】的知识;水滴石穿      ,积少成多        。各位小伙伴让我们 let’s be prepared at all times!

✨原创不易         ,还希望各位大佬支持一下! 👍 点赞               ,你的认可是我创作的动力! ⭐️ 收藏         ,你的青睐是我努力的方向! ✏️ 评论      ,你的意见是我进步的财富!

声明:本站所有文章               ,如无特殊说明或标注           ,均为本站原创发布    。任何个人或组织   ,在未征得本站同意时                ,禁止复制             、盗用                 、采集  、发布本站内容到任何网站          、书籍等各类媒体平台                 。如若本站内容侵犯了原著者的合法权益             ,可联系我们进行处理           。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
crawl是什么意思(crawler 0.1.0) ie浏览器阻止(IE总是阻止页面内容)