视图层:Pages主要有 wxml页面文件和模板文件、wxs脚本文件、wxss样式文件;component是抽取出来的业务单元,同样拥有wxml页面文件和模板文件、wxs脚本文件、wxss样式文件。
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式。
组件(Component)是视图的基本组成单元。
一:WXML:WXML(WeiXin Markup Language)是一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
MVVM模式:
在网页的一般开发流程中,我们通常会通过 JS 操作 DOM (对应 HTML 的描述产生的树),以引起界面的一些变化响应用户的行为。例如,用户点击某个按钮的时候,JS 会记录一些状态变化到 JS 变量里边,同时通过 DOM API 操控 DOM 的属性或者行为,进而引起界面一些变化。
当项目越来越大的时候,你的代码会充斥着非常多的界面交互逻辑和程序的各种状态变量,显然这不是一个很好的开发模式。
MVVM 的开发模式把渲染和逻辑分离:不让 JS 直接操控 DOM,JS只需要管理状态(数据)变化即可;然后再通过一种模板语法来描述状态和界面结构的关系,将状态(数据)变化实时更新到界面。
MVVM在微信小程序开发中的实现:通过数据绑定,将状态(数据)在界面上显示;通过 WXS脚本语言,根据状态(数据)动态决定页面结构。
通过 {{ }} 的语法把一个变量绑定到界面上,我们称为数据绑定。仅仅通过数据绑定还不够完整的描述状态和界面的关系,还需要 if/else, for等控制能力,在小程序里边,这些控制能力都用 wx: 开头的wxs语法来表达。
1)数据绑定
简单数据绑定:使用 Mustache 语法(双大括号)将要绑定的变量包起来。数据在js文件中定义,在wxml文件中绑定。
Page({
data: { //定义数据
message: 'Hello world!'
}
})
<view> {{ message }} </view> //数据绑定到页面
组件属性绑定:wxml中组件的属性值也可以通过数据绑定来赋值。
<view id="{{数据名}}"> </view>
条件语句值绑定:条件语句的值也可以通过数据绑定来赋值。
<view wx:if="{{condition}}"> </view>
Page({
data: {
condition: true //条件语句的值
}
})
关键字绑定:对于一些关键字、保留字,需要在 {{关键字}} 内才能起作用,如果只有双引号、没有双括号,则只是作为一个字符串而已。
<checkbox checked="{{false}}"> </checkbox>
//不要直接写 checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。
运算结果绑定:可以在 {{表达式}} 内进行运算,将结果绑定到页面。
运算支持:
三目运算:conditions ? val1 : val2
算术运算:+-*/
比较运算:> < == 等
点运算符:对象.属性
索引运算:数组对象[index]
组合成数组:{{[var...]}}
组合成对象:{{属性1:值,属性2:值,属性3:值...}}
展开一个对象:{{...object}} //用 ... 运算符将对象展开成 键值对 的形式
【特别注意:花括号和引号之间如果有空格,将最终被解析成为字符串。】
2)wxs渲染控制语句
2.1)条件控制语句:
//条件语句是在view属性中定义的,当条件成立时,该view就被绘制
<view wx:if="{{条件1}}"> 内容</view>
<view wx:elif="{{条件2}}"> 内容</view>
<view wx:else> 内容 </view>
如果要一次性判断多个组件标签,可以使用一个 <block/>
标签将多个组件包装起来,并在block标签使用 wx:if
控制属性:
<block wx:if="{{条件}}">
<view> view1 </view>
<view> view2 </view>
</block>
wx:if vs hidden 因为 wx:if 之中的模板也可能包含数据绑定,所有当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。 同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。 相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。 一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。
2.2)循环语句
组件上使用 wx:for
控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
//默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
<view wx:for="{{array}}">
{{index}}: {{item}}
</view>
也可以使用 wx:for-item
可以指定数组当前元素的变量名,使用 wx:for-index
可以指定数组当前下标的变量名:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName}}
</view>
重复渲染多个组件,可以用一个block标签把他们组成块:
<block wx:for="{{array}}">
<view> {{index}}: </view>
<view> {{item}} </view>
</block>
优化:使用wx:key避免被重新绘制、丢失状态。
如果view数组的view组件数量会动态增减或者view组件位置会动态变化,这些变化会引起view数组重新绘制,那么某个被重绘的view组件当前的状态可能会丢失(如:input接收的输入、switch开关的状态)。
若想要保持住这些状态数据,可以使用 wx:key 来避免组件被重绘。当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
wx:key 的值以两种形式提供:
字符串:使用array中item 的某个属性值,该属性值需要是数组中唯一的字符串或数字,且不能动态改变。
保留关键字*this:使用item本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
//使用 item 的属性值作key
<switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch> objectArray: [
{id: 5, unique: 'unique_5'}, //每个item的unique属性值均唯一
{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'},
], //使用 *this 作为key
<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch> numberArray: [1, 2, 3, 4]
3)WXML模版
对于可以在不同页面出现的页面结构,我们可以提取成为一个WXML模版,然后在不同的wxml文件引入这个模版并为模版传具体值,就可以复用这个页面结构了。
【注意区分:wxml模版是界面结构的重用;自定义组件则是功能结构的重用】
3.1)模版定义:
可以新建一个template目录,专门用于存放wxml模版文件。模版文件也是wxml文件,以wxml为后缀名。模版部分界面结构用 template 括住:
//header.wxml 页面头部模版文件示例
<template name="header">
<view class="left">
左边内容
</view>
<view class="center">
中间内容
</view>
<view class="right">
右边内容
</view>
</template>
在模版文件中,也可以使用wxs语法进行组件的条件渲染、列表渲染。
3.2)使用模版
使用 is 属性声明需要的使用的模板,然后将模板所需要的 data 传入。data的格式需要符合模板中数据绑定的格式(类型、变量名都要对应上)
<import src="模板文件相对路径"/> //导入模板
<template is="模板名" data="{{模板需要的数据}}" /> //传递数据,适用模板
is 属性可以使用 Mustache 语法,动态决定具体需要渲染哪个模板:
<template is="{{条件 ? '模版名1' : '模板名2'}}"/>
4)引用
WXML 提供两种文件引用方式import
和include
。
4.1)import
可以在该文件中使用目标文件定义的template,上面模板使用已经示范过了。
4.2)include
可以将目标文件除了 <template/>
<wxs/>
外的整个代码引入,相当于是拷贝到 include
位置。
5)视图层事件
5.1)事件分为冒泡事件和非冒泡事件:
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
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 动画完成时触发 |
注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如<form/>
的submit
事件,<input/>
的input
事件,<scroll-view/>
的scroll
事件。
5.2)事件的绑定
事件绑定的写法同组件的属性,以 key、value 的形式。
- key 以
bind
或catch
开头,然后跟上事件的类型,如bindtap
、catchtouchstart
。bind
和catch
后可以紧跟一个冒号再跟事件类型,其含义不变,如bind:tap
、、catch:touchstart
。 - value 是一个字符串,需要在对应的 Page 中定义同名的事件处理函数。
bind
事件绑定不会阻止冒泡事件向上冒泡,catch
事件绑定可以阻止冒泡事件向上冒泡。
5.3)事件处理的流程
事件处理可以包括两个阶段:事件捕获阶段(从界面父节点向组件子节点传递,被捕获)、事件处理阶段(冒泡的事件会从组件子节点开始处理,逐层向父节点传播,被处理【除非被catch阻止了】)
捕获事件可以采用capture-bind
、capture-catch
关键字,后者将中断捕获阶段和取消冒泡阶段。
5.4)事件处理函数
当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象,根据事件类型的不同,事件对象携带的信息也不同。
BaseEvent 基础事件对象属性列表:
属性 | 类型 | 说明 |
---|---|---|
type | String | 事件类型 |
timeStamp | Integer | 事件生成时的时间戳 |
target | Object | 触发事件的组件的一些属性值集合 |
currentTarget | Object | 当前组件的一些属性值集合 |
CustomEvent 自定义事件对象属性列表(继承 BaseEvent):
属性 | 类型 | 说明 |
---|---|---|
detail | Object | 额外的信息 |
TouchEvent 触摸事件对象属性列表(继承 BaseEvent):
属性 | 类型 | 说明 |
---|---|---|
touches | Array | 触摸事件,当前停留在屏幕中的触摸点信息的数组 |
changedTouches | Array | 触摸事件,当前变化的触摸点信息的数组 |
其中的几个Object类型参数主要包含信息如下:
target:触发事件的源组件。
属性 | 类型 | 说明 |
---|---|---|
id | String | 事件源组件的id |
tagName | String | 当前组件的类型 |
dataset | Object | 事件源组件上由data- 开头的自定义属性组成的集合 |
currentTarget:事件绑定的当前组件。
属性 | 类型 | 说明 |
---|---|---|
id | String | 当前组件的id |
tagName | String | 当前组件的类型 |
dataset | Object | 当前组件上由data- 开头的自定义属性组成的集合 |
Touch 对象
属性 | 类型 | 说明 |
---|---|---|
identifier | Number | 触摸点的标识符 |
pageX, pageY | Number | 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴 |
clientX, clientY | Number | 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴 |
二:WXS:WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构。
【wxs 的运行环境和其他 javascript 代码是隔离的,wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API。】
WXS 代码可以编写在 wxml 文件中的 <wxs>
标签内,或以 .wxs
为后缀名的文件内。
2.1)模块
每一个 .wxs
文件和 <wxs>
标签都是一个单独的模块,一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports
实现。
2.2)WXS文件中定义module
每个 wxs
模块均有一个内置的 module
对象,用于导出模块内数据与函数。
var ref = require("./ref.wxs"); //引用其他wxs模块 var foo = 定义变量;
var bar = function (param) {
ref.var; //调用引用模块的变量
ref.func();//调用引用模块的函数
方法体;
}
module.exports = { //导出变量、函数,并且指明导出名(用于调用)
FOO: foo,
bar: bar,
};
在wxml中使用wxs模块文件:
<wxs src="./../ref.wxs" module="ref" /> //定义module标签,创建一个module;并且通过src属性指明module的定义源文件路径 <view> {{ref.var}} </view> //通过module名调用数据、函数
<view> {{ref.func(param)}} </view>
2.3)wxs标签中定义module
module 属性是当前 <wxs>
标签的模块名。
<wxs module="模块名"> //1:通过 wxs 标签创建模块
var 变量 =值; //2:在模块内定义变量、函数
module.exports = {
导出名 : 变量, //3:导出模块内容
}
</wxs>
<view> {{模块名.变量/函数}} </view> //4:调用模块内容
-
<wxs>
模块只能在定义模块的 WXML 文件中被访问到。使用<include>
或<import>
时,<wxs>
模块不会被引入到对应的 WXML 文件中。 -
<template>
标签中,只能使用定义该<template>
的 WXML 文件中定义的<wxs>
模块。
2.4)语句
if语句:
// if ... if (表达式) 语句; if (表达式)
语句; if (表达式) {
代码块;
} // if ... else if (表达式) 语句;
else 语句; if (表达式)
语句;
else
语句; if (表达式) {
代码块;
} else {
代码块;
} // if ... else if ... else ... if (表达式) {
代码块;
} else if (表达式) {
代码块;
} else if (表达式) {
代码块;
} else {
代码块;
}
switch语句:
switch (表达式) {
case 变量:
语句;
case 数字:
语句;
break;
case 字符串:
语句;
default:
语句;
}
for语句:
for (语句; 语句; 语句)
语句; for (语句; 语句; 语句) {
代码块;
}
while语句:
while (表达式)
语句; while (表达式){
代码块;
} do {
代码块;
} while (表达式)
2.5)数据类型
number : 数值
string :字符串
boolean:布尔值
object:对象(无序键值对,用 {} 来定义)
function:函数
array : 数组
date:日期
regexp:正则
//函数的两种定义方式
function a (x) {
return x;
} //方法 2
var b = function (x) {
return x;
}
2.6)基础类库
console类库:控制台类库,可以调用log方法打印信息。
Math类库:数学常量、函数。
Json类库:Json与字符串互相转换。
Number类库:最大最小数字常量。
Date类库:日期相关。
Global类库:类型转换函数、判断有效值等。
三:WXSS样式文件
3.1)选择器
.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 组件前边插入内容
3.2)定义wxss文件
选择器 {
样式定义(键值对);
...
}
3.3)wxml文件中使用样式【小程序根据 同名 规则,将同名的 wxml、wxss、js文件自动引用,无需导入,只需使用相关名称来调用即可】
<view style="样式属性定义;" />
<view class="某种已经定义好样式的类选择器" />
3.4)wxss文件之间的引用
我们在定义某个wxss文件时,如果某些样式已经在别处定义过,那么可以将别处的样式导入进来,无需重复定义。
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
@import "./../路径/名字.wxss";
小程序学习笔记三:页面文件详解之视图层WXML、WXS、WXSS文件的更多相关文章
-
微信小程序学习笔记四 页面的生命周期
1. 生命周期 1.1 对应阶段说明 onLOad(Object query) 1.1 页面加载时触发, 一个页面只会调用一次, 可以在 onLoad的参数中获取打开当前页面路径中的参数 1.2 参数 ...
-
微信小程序学习笔记三 路由的基本使用
小程序中路由的使用 1.1 页面路由 在小程序中, 所有页面的路由全部由框架进行管理 1.2 页面栈 框架以栈的形式维护了当前的所有页面, 当发生路由切换的时候, 页面栈的表现如下: 1.3 获取当前 ...
-
[读书笔记]C#学习笔记三: C#类型详解..
前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...
-
【微信小程序学习笔记】入门与了解
[微信小程序学习笔记(一)] IDE 下载安装 下载地址 官方工具:https://mp.weixin.qq.com/debug/w … tml?t=1476434678461 下载可执行文件后,可按 ...
-
微信小程序学习笔记二 数据绑定 + 事件绑定
微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...
-
微信小程序学习笔记
一.文件结构解析 pages文件夹: 书写各个页面代码以及组件.内部js文件书写js ; wxml文件为HTML ; wxss文件为css样式 : json文件为配置当前页面的默认项,如titl ...
-
微信小程序学习笔记一 小程序介绍 &; 前置知识
微信小程序学习笔记一 1. 什么是小程序? 2017年度百度百科十大热词之一 微信小程序, 简称小程序, 英文名 Mini Program, 是一种不需要下载安装即可使用的应用 ( 张小龙对其的定义是 ...
-
IP2——IP地址和子网划分学习笔记之《子网掩码详解》
2018-05-04 16:21:21 在学习掌握了前面的<进制计数><IP地址详解>这两部分知识后,要学习子网划分,首先就要必须知道子网掩码,只有掌握了子网掩码这部分内容 ...
-
微信小程序 使用腾讯地图SDK详解及实现步骤
信小程序 使用腾讯地图SDK详解及实现步骤 微信小程序JavaScript SDK: 官方文档:http://lbs.qq.com/qqmap_wx_jssdk/index.html 步骤: 1 ...
随机推荐
-
HANS123
//策略:HANS123//周期:日内//类别:趋势突破 作为外汇市场上广为流行的一种突破交易策略,HANS123以其简洁的开盘后N根K线的高低点突破,作为交易信号触发的评判标准.这也是一种入场较早的 ...
-
hdu 2089 不要62--数位dp入门
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Des ...
-
C# List<;T>;的详细用法
所属命名空间:System.Collections.Generic List<T>类是 ArrayList 类的泛型等效类.该类使用大小可按需动态增加的数组实现 IList<T> ...
-
iOS 日历控件
近期需要写一个交互有点DT的日历控件,具体交互细节这里略过不表. 不过再怎么复杂的控件,也是由基础的零配件组装起来的,这里最基本的就是日历控件. 先上图: 从图中可以看出日历控件就是由一个个小方块组成 ...
-
vue.js如何在标签属性中插入变量参数
html的标签的属性,比如id.class.href需要动态传递参数,拼接字符串,查了一些资料,并没有找到合适的解决方法,琢磨了一上午,终于试出了方法: v-bind:属性=" '字符串'+ ...
-
利用python对excel进行数据剔除
需求分析: 判断excel2表中的某个唯一字段是否满足条件,如果满足条件,就在excel1中进行查询,若存在excel中,就将该数据进行剔除. python脚本的实现: from __future__ ...
-
【iOS】swift-如何理解 if let 与guard?
著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:黄兢成 链接:http://www.zhihu.com/question/36448325/answer/68614858 ...
-
微信小程序错误码参考大全
开发过程中,会遇到很多微信返回的状态码,鬼知道代表什么意思,现在好了,整理总结了一份状态码,方便大家. 转载:http://www.yiyongtong.com/archives/view-1856- ...
-
easyui的datagrid为何无法显示json数据
因为easyui的datagrid要求数据JSON必须是如下格式:{"total":0,"rows":[]}其中total表示总的数据行数,rows是当前页的数 ...
-
寒假训练——搜索 E - Bloxorz I
Little Tom loves playing games. One day he downloads a little computer game called 'Bloxorz' which m ...