微信小程序开发《7 .框架之视图层--wxml》
2018-02-25 15:21
579 查看
视图层
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合
WXML,可以构建出页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
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'} } })
事件
<view bindtap="add"> {{count}} </view>
Page({ data: { count: 1 }, add: function(e) { this.setData({ count: this.data.count + 1 }) } })
数据绑定
WXML 中的动态数据均来自对应 Page 的 data。简单绑定
数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于:内容
<view> {{ message }} </view>
Page({ data: { message: 'Hello MINA!' } })
组件属性(需要在双引号之内)
<view id="item-{{id}}"> </view>
Page({ data: { id: 0 } })
控制属性(需要在双引号之内)
<view wx:if="{{condition}}"> </view>
Page({ data: { condition: true } })
关键字(需要在双引号之内)
true:boolean 类型的 true,代表真值;
false: boolean 类型的 false,代表假值。
<checkbox checked="{{false}}"> </checkbox>特别注意:不要直接写
checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。
运算
可以在{{}}内进行简单的运算,支持的有如下几种方式:
三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
算数运算
<view> {{a + b}} + {{c}} + d </view>
Page({ data: { a: 1, b: 2, c: 3 } })view中的内容为
3 + 3 + d。
逻辑判断
<view wx:if="{{length > 5}}"> </view>
字符串运算
<view>{{"hello" + name}}</view>
Page({ data:{ name: 'MINA' } })
数据路径运算
<view>{{object.key}} {{array[0]}}</view>
Page({ data: { object: { key: 'Hello ' }, array: ['MINA'] } })
组合
也可以在 Mustache 内直接进行组合,构成新的对象或者数组。数组
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
Page({ data: { zero: 0 } })最终组合成数组
[0, 1, 2, 3, 4]。
对象
<template is="objectCombine" data="{{for: a, bar: b}}"></template>
Page({ data: { a: 1, b: 2 } })最终组合成的对象是
{for: 1, bar: 2}也可以用扩展运算符
...来将一个对象展开
<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>
Page({ data: { obj1: { a: 1, b: 2 }, obj2: { c: 3, d: 4 } } })最终组合成的对象是
{a: 1, b: 2, c: 3, d: 4, e: 5}。如果对象的 key 和 value 相同,也可以间接地表达。
<template is="objectCombine" data="{{foo, bar}}"></template>
Page({ data: { foo: 'my-foo', bar: 'my-bar' } })最终组合成的对象是
{foo: 'my-foo', bar:'my-bar'}。注意:上述方式可以随意组合,但是如有存在变量名相同的情况,后边的会覆盖前面,如:
<template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>
Page({ data: { obj1: { a: 1, b: 2 }, obj2: { b: 3, c: 4 }, a: 5 } })最终组合成的对象是
{a: 5, b: 3, c: 6}。注意: 花括号和引号之间如果有空格,将最终被解析成为字符串
<view wx:for="{{[1,2,3]}} "> {{item}} </view>等同于
<view wx:for="{{[1,2,3] + ' '}}"> {{item}} </view>
列表渲染
wx:for
在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为
index,数组当前项的变量名默认为
item
<view wx:for="{{array}}"> {{index}}: {{item.message}} </view>
Page({ data: { array: [{ message: 'foo', }, { message: 'bar' }] } })使用
wx:for-item可以指定数组当前元素的变量名,使用
wx:for-index可以指定数组当前下标的变量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName"> {{idx}}: {{itemName.message}} </view>
wx:for也可以嵌套,下边是一个九九乘法表
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="i"> <view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j"> <view wx:if="{{i <= j}}"> {{i}} * {{j}} = {{i * j}} </view> </view> </view>
block wx:for
类似block wx:if,也可以将
wx:for用在
<block/>标签上,以渲染一个包含多节点的结构块。例如:
<block wx:for="{{[1, 2, 3]}}"> <view> {{index}}: </view> <view> {{item}} </view> </block>
wx:key
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如<input/>中的输入内容,
<switch/>的选中状态),需要使用
wx:key来指定列表中项目的唯一的标识符。
wx:key的值以两种形式提供字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
保留关键字
*this代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。如不提供
wx:key,会报一个
warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。示例代码:
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch> <button bindtap="switch"> Switch </button> <button bindtap="addToFront"> Add to the front </button> <switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch> <button bindtap="addNumberToFront"> Add to the front </button>
Page({ data: { objectArray: [ {id: 5, unique: 'unique_5'}, {id: 4, unique: 'unique_4'}, {id: 3, unique: 'unique_3'}, {id: 2, unique: 'unique_2'}, {id: 1, unique: 'unique_1'}, {id: 0, unique: 'unique_0'}, ], numberArray: [1, 2, 3, 4] }, switch: function(e) { const length = this.data.objectArray.length for (let i = 0; i < length; ++i) { const x = Math.floor(Math.random() * length) const y = Math.floor(Math.random() * length) const temp = this.data.objectArray[x] this.data.objectArray[x] = this.data.objectArray[y] this.data.objectArray[y] = temp } this.setData({ objectArray: this.data.objectArray }) }, addToFront: function(e) { const length = this.data.objectArray.length this.data.objectArray = [{id: length, unique: 'unique_' + length}].concat(this.data.objectArray) this.setData({ objectArray: this.data.objectArray }) }, addNumberToFront: function(e){ this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray) this.setData({ numberArray: this.data.numberArray }) } })注意:当
wx:for的值为字符串时,会将字符串解析成字符串数组
<view wx:for="array"> {{item}} </view>等同于
<view wx:for="{{['a','r','r','a','y']}}"> {{item}} </view>注意: 花括号和引号之间如果有空格,将最终被解析成为字符串
<view wx:for="{{[1,2,3]}} "> {{item}} </view>等同于
<view wx:for="{{[1,2,3] + ' '}}" > {{item}} </view>
条件渲染
wx:if
在框架中,使用wx:if="{{condition}}"来判断是否需要渲染该代码块:
<view wx:if="{{condition}}"> True </view>也可以用
wx:elif和
wx:else来添加一个 else 块:
<view wx:if="{{length > 5}}"> 1 </view> <view wx:elif="{{length > 2}}"> 2 </view> <view wx:else> 3 </view>
block wx:if
因为wx:if是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个
<block/>标签将多个组件包装起来,并在上边使用
wx:if控制属性。
<block wx:if="{{true}}"> <view> view1 </view> <view> view2 </view> </block>注意:
<block/>并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
wx:if
vs hidden
因为 wx:if之中的模板也可能包含数据绑定,所有当
wx:if的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。同时
wx:if也是惰性的,如果在初始渲染条件为
false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。相比之下,
hidden就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。一般来说,
wx:if有更高的切换消耗而
hidden有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用
hidden更好,如果在运行时条件不大可能改变则
wx:if较好。
模板
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。定义模板
使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:
<!-- index: int msg: string time: string --> <template name="msgItem"> <view> <text> {{index}}: {{msg}} </text> <text> Time: {{time}} </text> </view> </template>
使用模板
使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:<template is="msgItem" data="{{...item}}"/>
Page({ data: { item: { index: 0, msg: 'this is a template', time: '2016-09-15' } } })is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:
<template name="odd"> <view> odd </view> </template> <template name="even"> <view> even </view> </template> <block wx:for="{{[1, 2, 3, 4, 5]}}"> <template is="{{item % 2 == 0 ? 'even' : 'odd'}}"/> </block>
模板的作用域
模板拥有自己的作用域,只能使用 data 传入的数据以及模版定义文件中定义的<wxs />模块。
引用
WXML 提供两种文件引用方式import和
include。
import
import可以在该文件中使用目标文件定义的
template,如:在 item.wxml 中定义了一个叫
item的
template:
<!-- item.wxml --> <template name="item"> <text>{{text}}</text> </template>在 index.wxml 中引用了 item.wxml,就可以使用
item模板:
<import src="item.wxml"/> <template is="item" data="{{text: 'forbar'}}"/>
import 的作用域
import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template。如:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的
template,但是C不能使用A定义的
template。
<!-- A.wxml --> <template name="A"> <text> A template </text> </template>
<!-- B.wxml --> <import src="a.wxml"/> <template name="B"> <text> B template </text> </template>
<!-- C.wxml --> <import src="b.wxml"/> <template is="A"/> <!-- Error! Can not use tempalte when not import A. --> <template is="B"/>
include
include可以将目标文件除了
<template/>
<wxs/>外的整个代码引入,相当于是拷贝到
include位置,如:
<!-- index.wxml --> <include src="header.wxml"/> <view> body </view> <include src="footer.wxml"/>
<!-- header.wxml --> <view> header </view>
<!-- footer.wxml --> <view> footer </view>
相关文章推荐
- 微信小程序开发详解 3 :开发框架视图层
- 微信小程序开发《8 .框架之视图层--wxs》
- 微信小程序开发《9 .框架之视图层--wxss》
- 微信小程序开发详解 1 : 初始小程序 2 :开发框架配置和逻辑层
- 微信小程序开发手记之四:视图容器
- PHPCMS微信小程序万能API接口模块,快速使用PHPCMS框架开发微信小程序
- 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app
- 【微信小程序开发•系列文章二】视图层
- 微信小程序的学习(3)-视图层WXML
- 使用Vue.js开发微信小程序:开源框架mpvue解析
- 使用AUI框架开发微信小程序
- tp5微信小程序全栈开发 十一——前端框架构建与令牌管理,首页、专题、分类等模块编写
- 快速了解微信小程序的使用,一个根据小程序的框架开发的 todos app
- 微信小程序 框架和视图
- 微信小程序开发—小程序框架详解(直播分享)
- 微信小程序开发系列——2. 开发者工具以及开发框架简介
- 微信小程序 开发之滑块视图容器(swiper)详解及实例代码
- 微信小程序开发《5. 框架之配置》
- 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app
- 微信小程序开发系列——4.小程序视图页面基础知识