|
导读微信小程序,简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。小程序是一种不用下载就能使用的应用,也是一... 微信小程序,简称小程序,英文名Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用。小程序是一种不用下载就能使用的应用,也是一项门槛非常高的创新,经过将近两年的发展,已经构造了新的小程序开发环境和开发者生态。 WXMLWXML(WeiXin Markup Language)是微信的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。 (小安娜:好像很厉害的样子,那基础组件、事件系统是什么?感觉更厉害,因为必须结合它们。),基础组件类似HTML中的标签,事件系统是JavaScript中的事件,可处理逻辑反应到界面上;wxml只是一个文件格式,如果没有组件和事件它没任何用处,又如果把组件、事件写在txt文档里面也没任何用处,所以没有谁更厉害,相辅相成的关系。(小安娜:嗦嘎,就好像ap、ad、adc的关系,一起才最强) 用以下一些简单的例子来看看 WXML 具有什么能力: 数据绑定WXML 中的动态数据均来自对应 Page 的 data 对象。 简单绑定数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于以下: (小安娜:等等,有没有点诚意,Mustache是什么都不知道!),Mustache是基于JavaScript实现的模板解析引擎,等等...总之它非常方便和好用。(小安娜:我去,你自己也不知道是什么吧) 内容<view> {{ message }} </view>Page({
data: {
message: 'Hello MINA!'
}
})显示结果:
显示结果 (小安娜: 组件属性(需要在双引号之内)<view id="item-{{id}}">id="item-{{id}}"</view>Page({
data: {
id: 0
}
})显示结果:
显示结果 控制属性(需要在双引号之内)<view wx:if="{{condition}}">你看得见我吗?</view>Page({
data: {
condition: true
}
})显示结果:
显示结果 (小安娜:我刚刚试了,condition改成false就看不见我了!),是的,改成 关键字(需要在双引号之内)
<checkbox checked="{{false}}" />默认没选中特别注意:不要直接写 (小安娜:那这个 所以显示结果:
显示结果 运算可以在 三元运算三元运算是:条件 ? 结果1 : 结果2;条件为ture时结果1否则结果2。 <view hidden="{{flag ? true : false}}"> 看得见吗? </view>(小安娜: 显示结果:
显示结果 算数运算<view> {{a + b}} + {{c}} + d </view>Page({
data: {
a: 1,
b: 2,
c: 3
}
})这次就先不说结果了,小安娜,你来猜猜看结果是什么?(小安娜:恩~,a=1,b=2,a+b就等于3,c=3,咦~,d没定义啊?),结果其实是:3 + 3 + d,d不是没定义,而它本来就是一个文字d,不参与任何计算。(小安娜:我这么认真回答,你居然这样坑我!!!) 显示结果:
显示结果 字符串运算<view>{{"hello " + name}}</view>Page({
data:{
name: 'MINA2'
}
})显示结果:
显示结果 数据路径运算如果data对象中包含了子对象,例如: Page({
data: {
object: {
key: 'Hello '
},
array: ['MINA3']
}
})可以这样访问: <view>{{object.key}} {{array[0]}}</view>显示结果:
显示结果 这个应该没问题吧?(小安娜:没问题,就是点操作嘛,一个是JSON对象操作,一个是数组操作),OK继续。 组合也可以在 Mustache 内直接进行组合,构成新的对象或者数组。 数组<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>Page({
data: {
zero: 0
}
})(小安娜:等等,这里我看了很久还是理解不了,再细讲解下),好,首先我们在data对象中定义zero变量并赋值为0,然后使用view组件的 显示结果:
显示结果 条件渲染wx:if
<view wx:if="{{condition}}">你看得见我吗?</view>也可以用 <view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>Page({
data: {
length: 10
}
})界面显示结果:1 block wx:if因为 <block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>这里的 (小安娜:我记得你说view可以看成p,那block呢,HTML中没这种控制标签?),没错啦, 列表渲染wx:for在组件上使用 默认的当前项下标变量名为: <view wx:for="{{array}}">
{{index}}:{{item.message}}
</view>Page({
data: {
array: [{
message: 'foo',
}, {
message: 'bar'
}]
}
})显示结果:
显示结果 不使用默认可以使用 <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>输出结果一样。 block wx:for类似 <block wx:for="{{['a', 'b', 'c']}}">
<view> {{index}}:{{item}}</view>
</block>显示结果:
显示结果 wx:key(可以选择跳过,但,是很重要的重点)(小安娜:突然有种想打你的冲动,又是重点又可以跳过,下课操场见!!!),冷静、冷静,官方文档我看到这时,也是没理解这是什么意思,后来就跳过这段了,但是也完成了B站的首页,(小安娜:哈~,原来是自己傻看不懂,别把我们的智商和你比好吧!),当写到这时再去多看了一遍(小安娜:绝对不止一遍),把官方例子运行调试之后,才发现微信官方设计 如果列表中的项目位置会改变或者有新的项目添加到列表中,为了项目保持自己的属性和状态(如
是不是完全理解不了什么意思?(小安娜:我觉得这不是重点,重点是案例你还没讲) 案例1: <switch wx:for="{{objectArray}}" wx:key="unique" style="display: block;"> {{item.id}} </switch>
<button bindtap="switch"> 改变顺序 </button>
<button bindtap="addToFront"> 添加到前面 </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'},
]
},
// 随机改变列表项目顺序
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
})
}
})(小安娜:天了噜,一大波代码来袭,看不懂了啦),所有函数真可以不用看懂内部实现,只需知道干什么用就行(内心的杰尔夫君:其实我知道只有她看不懂,大家照顾照顾她,假装看不懂)(小安娜:阿丘~谁在说我坏话!)。 显示结果(①:初始化状态;②:打开项目2的开关;③:改变顺序后项目2依然是打开状态;④:在最前面添加项目6,项目2依然是打开状态),这就是
显示结果 案例2: <switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;"> {{item}} </switch>
<button bindtap="addNumberToFront">添加到前面</button>Page({
data: {
numberArray: [1, 2, 3, 4]
},
// 添加项目到前面
addNumberToFront: function(e){
this.data.numberArray = [ this.data.numberArray.length + 1 ].concat(this.data.numberArray)
this.setData({
numberArray: this.data.numberArray
})
}
})显示结果:
显示结果 模板WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。 使用模板
<template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template>
<!-- 这里代表把item对象传入模板 -->
<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>显示结果:
显示结果 恩~~,这里有什么问题吗?(小安娜:恩~~就是呢,不知道模板可以用在什么地方?),当你网站很多地方都用到同一种结构的时候就可以用了,例如我们要做的B站首页: (小安娜:↓↓↓蓝色区域第二张图,不谢)
B站首页 可以看出绿、红、蓝色区域的结构都一样,改变的只是内容,这样的结构就很适合用模板实现。(小安娜:那其他页面也有这种结构呢?例如B站的直播页也有这种结构,顺便问一下为什么绿色在最前面XD),像这种需求我们就需要创建单独的模板文件,在需要的地方导入模板文件就行,接下来就细讲这个。 导入模板WXML 提供两种文件引用方式 带作用域的import
<!-- item.wxml -->
<template name="item">
<text>{{text}}</text>
</template>在 index.wxml 中引用了 item.wxml,就可以使用item模板: <import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
(小安娜:显示结果是:forbar,对吧?),没错啦,厉害了我的小姐姐;还有就是 <!-- a.wxml --> <template name="A"> <text> A template </text> </template> <!-- b.wxml --> <import src="a.wxml"/> <template name="B"> <text> B template </text> </template> <!-- index.wxml --> <import src="b.wxml"/> <template is="A"/> <!-- Error! Can not use template when not import A. --> <template is="B"/> 显示结果:B template;程序这样写编译会通过,但会在控制台(Console)报运行时警告(Runtime warn),还请注意。(小安娜:这么大个坑,那不是debug时很难找出问题?),是啊,的确很难避免,很容易出错而且找不到问题所在,但显示结果又不对,所以我们开发的时候要多注意调试控制台(Console)输出的错误和异常信息。(小安娜:开发果然是个细心活,同志们一起加油啦)。 头部和底部的include
<!-- header.wxml -->
<view>{{header}}</view><!-- footer.wxml -->
<view>{{footer}}</view><!-- index.wxml --> <include src="header.wxml"/> <view> body </view> <include src="footer.wxml"/> 等同于 === : <!-- index.wxml -->
<view>{{header}}</view>
<view> body </view>
<view>{{footer}}</view>// index.js
Page({
data: {
header: "header",
footer: "footer"
}
})显示结果:
显示结果 (小安娜:发现了,它可以直接使用index.js的数据),没错,所以这种更适合头部和底部数据不会随着页面不同而改变,而 事件事件是视图层(wxml)到逻辑层(js)的通讯方式,可以绑定在组件上,当触发事件,就会执行逻辑层中对应的事件处理函数。 事件分类
绑定事件格式为: <!-- index.wxml --> <button bindtouchstart="ontouchstart" bindtouchmove="ontouchmove" bindtouchend="ontouchend" bindtap="ontap" bindlongtap="onlongtap">点击我<button/> Page({
ontouchstart: function() {
console.log( "touchstart" );
},
ontouchmove: function() {
console.log( "touchmove" );
},
ontouchend: function() {
console.log( "touchend" );
},
ontap: function() {
console.log( "tap" );
},
onlongtap: function() {
console.log( "longtap" );
}
})当点击(\<=350ms)的时候,执行顺序:
当长按(>350ms)的时候,执行顺序:
我们发现点击是我们想象中的那样,但是长按执行一次 Page({
data: {
islongtap: false
},
ontouchstart: function() {
this.islongtap = false;
console.log( "touchstart" );
},
ontap: function() {
if( this.islongtap ) return ;
console.log( "tap" );
},
onlongtap: function() {
this.islongtap = true;
console.log( "longtap" );
}
})(小安娜:perfect,运行了下完美解决) 像js的事件一样,小程序事件也分为冒泡事件和非冒泡事件: <view id="outter" bindtap="handleTap1">
<view id="middle" bindtap="handleTap2">
<button id="inner" bindtap="handleTap3">
操作按钮
</button>
</view>
</view>Page({
handleTap1: function() {
console.log( "handleTap1" );
},
handleTap2: function() {
console.log( "handleTap2" );
},
handleTap3: function() {
console.log( "handleTap3" );
}
})这是一个常用的结构,一个大的层包含内部很多小层,小层内部有个操作按钮,当我们点击操作按钮:
发现所有父组件的点击事件都执行了,这就是冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。非冒泡事件就是不会向父节点传递。当然这很多时候不是件好事情,怎么避免呢? 小程序除了提供 <view id="outter" bindtap="handleTap1">
<view id="middle" bindtap="handleTap2">
<button id="inner" catchtap="handleTap3">
操作按钮
</button>
</view>
</view>输出结果:handleTap3,达到我们的效果了。(小安娜:我觉得把父组件的绑定事件去掉更好) 事件参数event当组件触发事件时,处理函数会收到一个事件对象参数。 Page({
handleTap3: function(event) {
console.log( event );
}
})控制台输出的结果: {
// 代表事件的类型
"type": "tap",
// 页面打开到触发事件所经过的毫秒数
"timeStamp": 2239,
// 触发事件的源组件
"target": {
// 事件源组件的id
"id": "inner",
// 距离左方或上层控件的位置(官方文档未说明)
"offsetLeft": 0,
// 距离上方或上层控件的位置(官方文档未说明)
"offsetTop": 0,
// 事件源组件上由data-开头的自定义属性组成的集合
"dataset": {}
},
// 事件绑定的当前组件,数据格式同 target
"currentTarget": {
"id": "inner",
"offsetLeft": 0,
"offsetTop": 0,
"dataset": {}
},
// 额外的数据信息
"detail": {
"x": 280,
"y": 18
},
// touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。 表示当前停留在屏幕上的触摸点。
"touches": [
{
// 触摸点的标识符
"identifier": 0,
// 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴
"pageX": 280,
// 距离文档左上角的距离,文档的左上角为原点 ,纵向为Y轴
"pageY": 18,
// 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴
"clientX": 280,
// 距离页面可显示区域(屏幕除去导航条)左上角距离,纵向为Y轴
"clientY": 18
}
],
// changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)。
"changedTouches": [
{
"identifier": 0,
"pageX": 280,
"pageY": 18,
"clientX": 280,
"clientY": 18
}
]
}每个参数具体什么意思,我们放在以后B站项目中去讲解,(小安娜:噗~,我好多问题准备问了,现在又憋回去了,听你讲东西真心累),毕竟太多了,每个都讲到估计可以写几篇文章了,用到什么再回头来看看,然后再配合案例这样最容易理解了。(小安娜:好像也是,总感觉哪里不对,等等...要是你不用到呢),这个保证不会,因为有我们常用的 WXSS
与 CSS 相比增加的特性有:
尺寸单位rpxrpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。(小安娜:真啰嗦,也就是1px = 2rpx嘛)
所以:我们设计/开发微信小程序时都应该用 iPhone6s 作为视觉稿的标准。(小安娜:所以,看你教程是不是有福利,会给我们发iPhone 6s吗?) 样式导入使用 /* common.wxss */
.header,
.footer {
padding: 20rpx 0;
text-align: center;
font-size: 50rpx;
}/* index.wxss */
@import "common.wxss";
.content {
line-height: 50rpx;
}<view class="header">header</view> <view class="content" style="color:#e64340;">和小安娜一块去超市买东西,小安娜:“好想吃泡面,可是怕上火啊”;我:“那就不要买了”;小安娜:“不行,再去买一罐加多宝吧”;我:...</view> <view class="footer">footer</view> 这样就在
显示结果 (小安娜:你怎么?不过用加多宝泡泡面还真挺好吃。喂,快说正事啦,我发现你使用了行内样式 目前支持的选择器
注意:结果笔者开发试验,暂时还不支持*选择器(所有元素),例如我们经常会设置所有组件的 * {
box-sizing: border-box;
}使用之后会发现所有 记得官方文档了解到这,基础知识终于告一段落了,下一篇开始实战,开发时更多组件知识请参考官方文档。
小安娜有问题WXML是什么?杰尔夫君:WXML(WeiXin Markup Language)是一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。和HTML相似。 WXML组件怎么绑定数据?杰尔夫君:WXML中的动态数据均来自对应 Page 的 data。数据绑定使用 Mustache 语法(双大括号)将变量包起来。例如: Page({
data: {
message: 'Hello MINA!'
}
})<!-- 绑定Page中的data.message -->
<view> {{ message }} </view>什么是Mustache?杰尔夫君:Mustache 是一个 logic-less (轻逻辑)模板解析引擎。在小程序里主要关注小程序的语法。详细了解前往:www.open-open.com/lib/view/open1416792564461.html WXML中怎么使用条件判断?杰尔夫君:在框架中,我们用 <view wx:if="{{condition}}"> True </view>也可以用 <view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>如果想一次性判断多个组件标签,我们可以使用一个 <block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>WXML怎么循环列表?杰尔夫君:在组件上使用 <view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
{{idx}}: {{itemName.message}}
</view>等等,怎么感觉你从头到尾都有问题啊,感觉没学过一样?(小安娜:没办法啦,这次讲太多了,本小姐记忆不太好,都不记得学了什么),好吧好吧,也正好总结一下,继续你的问题。(小安娜:你别打断啊!) WXML怎么使用模板?杰尔夫君:用 <template name="msgItem">
<view>
<text> {{index}}: {{msg}} </text>
<text> Time: {{time}} </text>
</view>
</template><!-- 参数传入Page中的data.item -->
<template is="msgItem" data="{{...item}}"/>Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})也可以把模板定义在单独文件中,通过 <!-- import -->
<!-- item.wxml -->
<template name="item">
<text>{{text}}</text>
</template>
<!-- index.wxml -->
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/><!-- include --> <!-- header.wxml --> <view> header </view> <!-- footer.wxml --> <view> footer </view> <!-- index.wxml --> <include src="header.wxml"/> <view> body </view> <include src="footer.wxml"/>
WXML中怎么使用事件?杰尔夫君:使用 什么是WXSS?杰尔夫君:WXSS(WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。WXSS 具有 CSS 大部分特性。 同时为了更适合开发微信小程序,对 CSS 进行了扩充以及修改了:尺寸单位、样式导入。 尺寸单位rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。以iPhone6为例:1rpx = 0.5px,1px = 2rpx。 样式导入使用 @import "common.wxss";
.middle-p {
padding:15px;
}以上就是微信小程序中wxml和wxss文件详解的详细内容,更多请关注php中文网其它相关文章! 小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。 |
温馨提示:喜欢本站的话,请收藏一下本站!