小程序学习笔记三:页面文件详解之视图层WXML、WXS、WXSS文件

时间:2022-09-02 09:56:53

  视图层: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 提供两种文件引用方式importinclude

4.1)import可以在该文件中使用目标文件定义的template,上面模板使用已经示范过了。

4.2)include 可以将目标文件除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置。

5)视图层事件

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

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

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 以bindcatch开头,然后跟上事件的类型,如bindtapcatchtouchstartbindcatch后可以紧跟一个冒号再跟事件类型,其含义不变,如bind:tap、、catch:touchstart
  • value 是一个字符串,需要在对应的 Page 中定义同名的事件处理函数。

  bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。

5.3)事件处理的流程

事件处理可以包括两个阶段:事件捕获阶段(从界面父节点向组件子节点传递,被捕获)、事件处理阶段(冒泡的事件会从组件子节点开始处理,逐层向父节点传播,被处理【除非被catch阻止了】)

捕获事件可以采用capture-bindcapture-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.1 对应阶段说明 onLOad(Object query) 1.1 页面加载时触发, 一个页面只会调用一次, 可以在 onLoad的参数中获取打开当前页面路径中的参数 1.2 参数 ...

  2. 微信小程序学习笔记三 路由的基本使用

    小程序中路由的使用 1.1 页面路由 在小程序中, 所有页面的路由全部由框架进行管理 1.2 页面栈 框架以栈的形式维护了当前的所有页面, 当发生路由切换的时候, 页面栈的表现如下: 1.3 获取当前 ...

  3. &lbrack;读书笔记&rsqb;C&num;学习笔记三&colon; C&num;类型详解&period;&period;

    前言 这次分享的主要内容有五个, 分别是值类型和引用类型, 装箱与拆箱,常量与变量,运算符重载,static字段和static构造函数. 后期的分享会针对于C#2.0 3.0 4.0 等新特性进行. ...

  4. 【微信小程序学习笔记】入门与了解

    [微信小程序学习笔记(一)] IDE 下载安装 下载地址 官方工具:https://mp.weixin.qq.com/debug/w … tml?t=1476434678461 下载可执行文件后,可按 ...

  5. 微信小程序学习笔记二 数据绑定 &plus; 事件绑定

    微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...

  6. 微信小程序学习笔记

    一.文件结构解析 pages文件夹: 书写各个页面代码以及组件.内部js文件书写js ;  wxml文件为HTML ;   wxss文件为css样式 : json文件为配置当前页面的默认项,如titl ...

  7. 微信小程序学习笔记一 小程序介绍 &amp&semi; 前置知识

    微信小程序学习笔记一 1. 什么是小程序? 2017年度百度百科十大热词之一 微信小程序, 简称小程序, 英文名 Mini Program, 是一种不需要下载安装即可使用的应用 ( 张小龙对其的定义是 ...

  8. IP2——IP地址和子网划分学习笔记之《子网掩码详解》

    2018-05-04 16:21:21   在学习掌握了前面的<进制计数><IP地址详解>这两部分知识后,要学习子网划分,首先就要必须知道子网掩码,只有掌握了子网掩码这部分内容 ...

  9. 微信小程序 使用腾讯地图SDK详解及实现步骤

    信小程序 使用腾讯地图SDK详解及实现步骤    微信小程序JavaScript SDK: 官方文档:http://lbs.qq.com/qqmap_wx_jssdk/index.html 步骤: 1 ...

随机推荐

  1. HANS123

    //策略:HANS123//周期:日内//类别:趋势突破 作为外汇市场上广为流行的一种突破交易策略,HANS123以其简洁的开盘后N根K线的高低点突破,作为交易信号触发的评判标准.这也是一种入场较早的 ...

  2. hdu 2089 不要62--数位dp入门

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Des ...

  3. C&num; List&lt&semi;T&gt&semi;的详细用法

    所属命名空间:System.Collections.Generic List<T>类是 ArrayList 类的泛型等效类.该类使用大小可按需动态增加的数组实现 IList<T&gt ...

  4. iOS 日历控件

    近期需要写一个交互有点DT的日历控件,具体交互细节这里略过不表. 不过再怎么复杂的控件,也是由基础的零配件组装起来的,这里最基本的就是日历控件. 先上图: 从图中可以看出日历控件就是由一个个小方块组成 ...

  5. vue&period;js如何在标签属性中插入变量参数

    html的标签的属性,比如id.class.href需要动态传递参数,拼接字符串,查了一些资料,并没有找到合适的解决方法,琢磨了一上午,终于试出了方法: v-bind:属性=" '字符串'+ ...

  6. 利用python对excel进行数据剔除

    需求分析: 判断excel2表中的某个唯一字段是否满足条件,如果满足条件,就在excel1中进行查询,若存在excel中,就将该数据进行剔除. python脚本的实现: from __future__ ...

  7. 【iOS】swift-如何理解 if let 与guard&quest;

    著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:黄兢成 链接:http://www.zhihu.com/question/36448325/answer/68614858 ...

  8. 微信小程序错误码参考大全

    开发过程中,会遇到很多微信返回的状态码,鬼知道代表什么意思,现在好了,整理总结了一份状态码,方便大家. 转载:http://www.yiyongtong.com/archives/view-1856- ...

  9. easyui的datagrid为何无法显示json数据

    因为easyui的datagrid要求数据JSON必须是如下格式:{"total":0,"rows":[]}其中total表示总的数据行数,rows是当前页的数 ...

  10. 寒假训练——搜索 E - Bloxorz I

    Little Tom loves playing games. One day he downloads a little computer game called 'Bloxorz' which m ...