微信小程序开发学习笔记(二)——小程序框架、组件、WXML
一、整体认识小程序框架
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言 WXML
和 WXSS
,以及基于 JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
1.1、响应的数据绑定
框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
通过这个简单的例子来看:
<!-- This is our View -->
<view> Hello {{name}}! </view>
<button bindtap="changeName"> Click me! </button>
// This is our App Service.
// This is our data.
var helloData = {
name: 'Weixin'
}
// Register a Page.
Page({
data: helloData,
changeName: function(e) {
// sent data change to view
this.setData({
name: 'MINA'
})
}
})
- 开发者通过框架将逻辑层数据中的
name
与视图层的name
进行了绑定,所以在页面一打开的时候会显示Hello Weixin!
; - 当点击按钮的时候,视图层会发送
changeName
的事件给逻辑层,逻辑层找到并执行对应的事件处理函数; - 回调函数触发后,逻辑层执行
setData
的操作,将data
中的name
从Weixin
变为MINA
,因为该数据和视图层已经绑定了,从而视图层会自动改变为Hello MINA!
。
pages/counter/index.wxml
<!--pages/counter/index.wxml--> <view class="counter"> <view class="title"><text>计数器</text></view> <view>{{count}}</view> <view> <button type="primary" bindtap="onCount">点击count++</button> </view> </view>
pages/counter/index.wxss
/* pages/counter/index.wxss */ .counter { font-size: 60rpx; text-align: center; padding: 30rpx; } .counter view{ margin: 20rpx 0; } .counter .title{ color:red; }
pages/counter/index.js
// pages/counter/index.js Page({ /** * 页面的初始数据 */ data: { count:100 }, onCount(){ this.setData({count:this.data.count+1}); } })
运行效果:
1.2、页面管理
框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。
1.3、基础组件
框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。
1.4、丰富的 API
框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。
1.5. 小程序文件结构和传统web对比
结构 | 传统web | 微信小程序 |
---|---|---|
结构 | HTML | WXML |
样式 | CSS | WXSS |
逻辑 | Javascript | Javascript |
配置 | 无 | JSON |
通过以上对比得出,传统web 是三层结构。而微信小程序 是四层结构,多了一层 配置.json
二、组件
小程序中的组件是由宿主环境提供的,主要分为9大类:
视图容器、基础内容、表单组件、导航组件、媒体组件、map地图组件、canvas画布组件、开放能力、无障碍访问
2.0、单位
2.0.1、响应式单位rpx
在使用 CSS 进行移动端的网页开发时,由于不同手机设备的屏幕比,在换算像素单位时会遇到很多麻烦。为了方便开发人员适配各种屏幕WxSS 中加入了新的尺寸单位 rpx 即(responsive pixel,响应式像素)。
rpx 说明
rpx: 规定不管屏幕为多少px , 100%的屏幕宽度就是750rpx
100% 屏幕的宽度 = 750rpx
rpx响应单位
-
rpx是微信小程序独有的,解决屏幕自适应的尺寸单位
-
可以根据屏幕宽度进行自适应,不论大小屏幕,规定屏幕宽为750rpx
-
通过 rpx 设置元素和字体的大小,小程序在不同尺寸的屏幕下,可以实现自动适配
rpx 和 px之间的换算
-
在普通网页开发中 , 最常见的像素单位是px
-
在小程序开发中推荐使用 rpx这种响应式的像素单位进行开发
-
如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px
<view class="rpxDemo"> Hello rpx! </view>
.rpxDemo { width: 375rpx; height: 375rpx; background: yellow; font-size:80rpx; }
运行在iphone5上:
更大屏幕的iphone6
字体与view都相应响应式变大。
2.0.2、其它单位
px 绝对单位,页面按精确像素展示
em 相对单位,相对于它的父节点字体进行计算
rem 相对单位,相对根节点html的字体大小来计算
% 一般来说就是相对于父元素
vh 视窗高度,1vh等于视窗高度的1%
vw 视窗宽度,1vw等于视窗宽度的1%
.box { display:flex; justify-content: center; align-items: center; height: 100vh; } .box view{ background: lightcoral; height: 50vh; line-height: 50vh; width: 50vw; text-align: center; }
<view class="box"> <view> Hello rpx! </view> </view>
示例2:
<view class="mybox"> <view class="demo"> Hello Applet! </view> </view>
.mybox { display: flex; justify-content: center; align-items: center; background: gray; height: 100vh; } .demo{ background: oldlace; width: 50vw; height: 50vh; text-align: center; line-height: 50vh; font-size: 7vw; }
运行效果:
2.1、view组件
在微信小程序开发中,view就相当于html5中的div,也是块状元素
官方文档给出的解释呢就是:视图容器
我们在编写html5页面所用的div呢,在开发小程序中就改成view即可
属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
hover-class | string | none | 否 | 指定按下去的样式类。当 hover-class="none" 时,没有点击态效果 |
1.0.0 |
hover-stop-propagation | boolean | false | 否 | 指定是否阻止本节点的祖先节点出现点击态 | 1.5.0 |
hover-start-time | number | 50 | 否 | 按住后多久出现点击态,单位毫秒 | 1.0.0 |
hover-stay-time | number | 400 | 否 | 手指松开后点击态保留时间,单位毫秒 | 1.0.0 |
<view>Hello wx</view>
view类似div,这里主要学会使用view+flex布局 https://www.cnblogs.com/best/p/6136165.html#_label1
示例:
<view hover-class="bgcolor" class="box"> <view>Tom</view> <view>Jack</view> <view>Rose</view> </view>
.bgcolor{ background: lightcyan; } .box{ display: flex; flex-direction: row; background: oldlace; justify-content:space-around } .box view{ height: 80rpx; line-height: 80rpx; text-align: center; } .box view:nth-child(1){ background: #ddeeff; } .box view:nth-child(2){ background: #99ddee; width: 200rpx; } .box view:nth-child(3){ background: #6699dd; }
结果:
示例:
<view hover-class="bgcolor" class="box"> <view>Tom</view> <view>Jack</view> <view>Rose</view> </view>
.bgcolor{ background: lightcyan; } .box{ display: flex; flex-direction: row; background: oldlace; height: 50vh; /* align-items: flex-end; */ /* align-items: flex-start; */ /* align-items:center; */ /* align-items: stretch; */ align-items: baseline; } .box view{ height: 80rpx; text-align: center; } .box view:nth-child(1){ background: #ddeeff; } .box view:nth-child(2){ background: #99ddee; width: 200rpx; font-size: 100rpx; } .box view:nth-child(3){ background: #6699dd; }
结果:
示例:
.bgcolor{ background: lightcyan; } .box{ display: flex; flex-direction: row; background: oldlace; height: 50vh; } .box view{ height: 80rpx; text-align: center; } .box view:nth-child(1){ background: #ddeeff; flex-grow: 0; } .box view:nth-child(2){ background: #99ddee; flex-grow: 1; } .box view:nth-child(3){ background: #6699dd; flex-grow: 0; }
结果:
2.2、scroll-view
可滚动视图区域。使用竖向滚动时,需要给scroll-view一个固定高度
说白了其实就是一个可以 允许滚动的容器,只需要设置最大高度即可
属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
scroll-x | boolean | false | 否 | 允许横向滚动 | 1.0.0 |
scroll-y | boolean | false | 否 | 允许纵向滚动 | 1.0.0 |
upper-threshold | number/string | 50 | 否 | 距顶部/左边多远时,触发 scrolltoupper 事件 | 1.0.0 |
lower-threshold | number/string | 50 | 否 | 距底部/右边多远时,触发 scrolltolower 事件 | 1.0.0 |
scroll-top | number/string | 否 | 设置竖向滚动条位置 | 1.0.0 | |
scroll-left | number/string | 否 | 设置横向滚动条位置 | 1.0.0 | |
scroll-into-view | string | 否 | 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 | 1.0.0 | |
scroll-with-animation | boolean | false | 否 | 在设置滚动条位置时使用动画过渡 | 1.0.0 |
enable-back-to-top | boolean | false | 否 | iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只支持竖向。自 2.27.3 版本开始,若非显式设置为 false,则在显示尺寸大于屏幕 90% 时自动开启。 | 1.0.0 |
enable-flex | boolean | false | 否 | 启用 flexbox 布局。开启后,当前节点声明了 `display: flex` 就会成为 flex container,并作用于其孩子节点。 | 2.7.3 |
scroll-anchoring | boolean | false | 否 | 开启 scroll anchoring 特性,即控制滚动位置不随内容变化而抖动,仅在 iOS 下生效,安卓下可参考 CSS `overflow-anchor` 属性。 | 2.8.2 |
enable-passive | boolean | false | 否 | 开启 passive 特性,能优化一定的滚动性能 | 2.25.3 |
refresher-enabled | boolean | false | 否 | 开启自定义下拉刷新 | 2.10.1 |
refresher-threshold | number | 45 | 否 | 设置自定义下拉刷新阈值 | 2.10.1 |
refresher-default-style | string | "black" | 否 | 设置自定义下拉刷新默认样式,支持设置 `black | white | none`, none 表示不使用默认样式 | 2.10.1 |
refresher-background | string | "#FFF" | 否 | 设置自定义下拉刷新区域背景颜色 | 2.10.1 |
refresher-triggered | boolean | false | 否 | 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 | 2.10.1 |
enhanced | boolean | false | 否 | 启用 scroll-view 增强特性,启用后可通过 ScrollViewContext 操作 scroll-view | 2.12.0 |
bounces | boolean | true | 否 | iOS 下 scroll-view 边界弹性控制 (同时开启 enhanced 属性后生效) | 2.12.0 |
show-scrollbar | boolean | true | 否 | 滚动条显隐控制 (同时开启 enhanced 属性后生效) | 2.12.0 |
paging-enabled | boolean | false | 否 | 分页滑动效果 (同时开启 enhanced 属性后生效) | 2.12.0 |
fast-deceleration | boolean | false | 否 | 滑动减速速率控制, 仅在 iOS 下生效 (同时开启 enhanced 属性后生效) | 2.12.0 |
binddragstart | eventhandle | 否 | 滑动开始事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft } | 2.12.0 | |
binddragging | eventhandle | 否 | 滑动事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft } | 2.12.0 | |
binddragend | eventhandle | 否 | 滑动结束事件 (同时开启 enhanced 属性后生效) detail { scrollTop, scrollLeft, velocity } | 2.12.0 | |
bindscrolltoupper | eventhandle | 否 | 滚动到顶部/左边时触发 | 1.0.0 | |
bindscrolltolower | eventhandle | 否 | 滚动到底部/右边时触发 | 1.0.0 | |
bindscroll | eventhandle | 否 | 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} | 1.0.0 | |
bindrefresherpulling | eventhandle | 否 | 自定义下拉刷新控件被下拉 | 2.10.1 | |
bindrefresherrefresh | eventhandle | 否 | 自定义下拉刷新被触发 | 2.10.1 | |
bindrefresherrestore | eventhandle | 否 | 自定义下拉刷新被复位 | 2.10.1 | |
bindrefresherabort | eventhandle | 否 | 自定义下拉刷新被中止 | 2.10.1 |
wxml:
<!--pages/hello/index.wxml--> <scroll-view class="box" scroll-x="true" scroll-y="true"> <view class="innerbox"> 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 内容内容内容内容内容内容内容内容内容内容内容内容内容 </view> </scroll-view>
wxcss:
.innerbox{
width: 500px;
height: 100px;
background-color: lightblue;
}
结果:
2.3、swiper与swiper-item
滑块视图容器。其中只可放置swiper-item组件
通俗点讲呢,就是轮播图组件,微信小程序中,轮播图我们不用在自己去写
可以用它自带的swiper组件与swiper-view共同来完成
swiper属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
indicator-dots | boolean | false | 否 | 是否显示面板指示点 | 1.0.0 |
indicator-color | color | rgba(0, 0, 0, .3) | 否 | 指示点颜色 | 1.1.0 |
indicator-active-color | color | #000000 | 否 | 当前选中的指示点颜色 | 1.1.0 |
autoplay | boolean | false | 否 | 是否自动切换 | 1.0.0 |
current | number | 0 | 否 | 当前所在滑块的 index | 1.0.0 |
interval | number | 5000 | 否 | 自动切换时间间隔 | 1.0.0 |
duration | number | 500 | 否 | 滑动动画时长 | 1.0.0 |
circular | boolean | false | 否 | 是否采用衔接滑动 | 1.0.0 |
vertical | boolean | false | 否 | 滑动方向是否为纵向 | 1.0.0 |
previous-margin | string | "0px" | 否 | 前边距,可用于露出前一项的一小部分,接受 px 和 rpx 值 | 1.9.0 |
next-margin | string | "0px" | 否 | 后边距,可用于露出后一项的一小部分,接受 px 和 rpx 值 | 1.9.0 |
snap-to-edge | boolean | false | 否 | 当 swiper-item 的个数大于等于 2,关闭 circular 并且开启 previous-margin 或 next-margin 的时候,可以指定这个边距是否应用到第一个、最后一个元素 | 2.12.1 |
display-multiple-items | number | 1 | 否 | 同时显示的滑块数量 | 1.9.0 |
easing-function | string | "default" | 否 | 指定 swiper 切换缓动动画类型 | 2.6.5 |
bindchange | eventhandle | 否 | current 改变时会触发 change 事件,event.detail = {current, source} | 1.0.0 | |
bindtransition | eventhandle | 否 | swiper-item 的位置发生改变时会触发 transition 事件,event.detail = {dx: dx, dy: dy} | 2.4.3 | |
bindanimationfinish | eventhandle | 否 | 动画结束时会触发 animationfinish 事件,event.detail 同上 | 1.9.0 |
swiper-item属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
item-id | string | 否 | 该 swiper-item 的标识符 | 1.9.0 | |
skip-hidden-item-layout | boolean | false | 否 | 是否跳过未显示的滑块布局,设为 true 可优化复杂情况下的滑动性能,但会丢失隐藏状态滑块的布局信息 | 1.9.0 |
wxml
<swiper class="swiper-content" indicator-dots indicator-color="white" indicator-active-color="gray" autoplay="true" interval="2000" circular> <!-- circular:衔接滑动 --> <!-- 未激活的小圆点的颜色:indicator-color --> <!-- autoplay:自动轮播 --> <!-- indicator-dots:开启小圆点 --> <swiper-item> <view class="item">A</view> </swiper-item> <swiper-item> <view class="item">B</view> </swiper-item> <swiper-item> <view class="item">C</view> </swiper-item> </swiper>
wxss
.swiper-content{
height: 150px;
}
.item{
height: 100%;
line-height: 150px;
text-align: center;
}
swiper-item:nth-child(1) .item{
background-color: green;
}
swiper-item:nth-child(2) .item{
background-color: yellow;
}
swiper-item:nth-child(3) .item{
background-color: pink;
}
示例:
<swiper class="swiperContainer" autoplay="true" circular="true" indicator-dots="true" indicator-color="red" indicator-active-color="white" interval="500"> <swiper-item class="item a"> <view>Tom</view> </swiper-item> <swiper-item class="item b"> <view>Jack</view> </swiper-item> <swiper-item class="item c"> <view>Rose</view> </swiper-item> </swiper>
.item{ font-size: 100rpx; height: 300rpx; text-align: center; line-height: 300rpx; } .a{ background: lightgreen; } .b{ background: lightblue; color: red; } .c{ background: lightcoral; }
结果:
2.4、text
文本组件,类似与html中的span标签,是一个行内元素
属性说明:
<text>需求文档策划书</text> <!-- 长按选中效果需加上selectable -->
<view> <text>1 2 > <</text> </view>
示例:
<view> <text user-select="true" decode="true">Hello TEXT! < <text> 嵌套text </text> </text> <text>1</text><text>2</text> </view>
结果:
原样输出,加上decode会编码。
tip
: decode可以解析的有
<
>
&
'
 
 
tip
: 各个操作系统的空格标准并不一致。tip
:text 组件内只支持 text 嵌套。tip
: 除了文本节点以外的其他节点都无法长按选中。bug
: 基础库版本低于2.1.0
时, text 组件内嵌的 text style 设置可能不会生效。
2.5、rich-text
富文本组件,支持把HTML字符串渲染为WXML结构
属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 | |
---|---|---|---|---|---|---|
nodes | array/string | [] | 否 | 节点列表/HTML String | 1.4.0 | |
space | string | 否 | 显示连续空格 | 2.4.1 | ||
user-select | boolean | false | 否 | 文本是否可选,该属性会使节点显示为 block | 2.24.0 |
<rich-text nodes="<h1 style='color: green;'>标题一</h1>"></rich-text>
tip
: nodes 不推荐使用 String 类型,性能会有所下降。tip
:rich-text
组件内屏蔽所有节点的事件。tip
: attrs 属性不支持 id ,支持 class 。tip
: name 属性大小写不敏感。tip
: 如果使用了不受信任的HTML节点,该节点及其所有子节点将会被移除。tip
: img 标签仅支持网络图片。tip
: 如果在自定义组件中使用rich-text
组件,那么仅自定义组件的 wxss 样式对rich-text
中的 class 生效
<view> <text>{{"<hr/>"}}</text> <rich-text nodes="{{'<hr/>'}}"> </rich-text> <view>123</view> <rich-text nodes="<hr/>"> </rich-text> </view>
<view> <text> {{"原样输出:<hr/>"}} </text> <rich-text nodes="解析成HTML:<hr/>"> </rich-text> <rich-text nodes="{{mynodes}}"> </rich-text> </view>
// pages/hello/index.js Page({ /** * 页面的初始数据 */ data: { mynodes:[{ name:"div", attrs:{ class:"blue" }, children:[{ type:"text", text:"Hello Nodes!" }] }] }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { } })
.blue{ color:blue }
结果:
2.6、button
按钮组件
相对于html的button,更加丰富,可以通过属性type来改变按钮的不同样式
微信小程序的button按钮可以调用很多功能(通过open-type可以调用客服,转发,获取用户信息,获取用户授权等)
属性说明:
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 |
---|---|---|---|---|---|
size | string | default | 否 | 按钮的大小 | 1.0.0 |
type | string | default | 否 | 按钮的样式类型 | 1.0.0 |
plain | boolean | false | 否 | 按钮是否镂空,背景色透明 | 1.0.0 |
disabled | boolean | false | 否 | 是否禁用 | 1.0.0 |
loading | boolean | false | 否 | 名称前是否带 loading 图标 | 1.0.0 |
form-type | string | 否 | 用于 form 组件,点击分别会触发 form 组件的 submit/reset 事件 | 1.0.0 | |
open-type | string | 否 | 微信开放能力 | 1.1.0 | |
hover-class | string | button-hover | 否 | 指定按钮按下去的样式类。当 `hover-class="none"` 时,没有点击态效果 | 1.0.0 |
hover-stop-propagation | boolean | false | 否 | 指定是否阻止本节点的祖先节点出现点击态 | 1.5.0 |
hover-start-time | number | 20 | 否 | 按住后多久出现点击态,单位毫秒 | 1.0.0 |
hover-stay-time | number | 70 | 否 | 手指松开后点击态保留时间,单位毫秒 | 1.0.0 |
lang | string | en | 否 | 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。 | 1.3.0 |
session-from | string | 否 | 会话来源,open-type="contact"时有效 | 1.4.0 | |
send-message-title | string | 当前标题 | 否 | 会话内消息卡片标题,open-type="contact"时有效 | 1.5.0 |
send-message-path | string | 当前分享路径 | 否 | 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效 | 1.5.0 |
send-message-img | string | 截图 | 否 | 会话内消息卡片图片,open-type="contact"时有效 | 1.5.0 |
app-parameter | string | 否 | 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效 | 1.9.5 | |
show-message-card | boolean | false | 否 | 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,用户点击后可以快速发送小程序消息,open-type="contact"时有效 | 1.5.0 |
bindgetuserinfo | eventhandle | 否 | 用户点击该按钮时,会返回获取到的用户信息,回调的 detail 数据与wx.getUserInfo返回的一致,open-type="getUserInfo"时有效 | 1.3.0 | |
bindcontact | eventhandle | 否 | 客服消息回调,open-type="contact"时有效 | 1.5.0 | |
bindgetphonenumber | eventhandle | 否 | 获取用户手机号回调,open-type=getPhoneNumber时有效 | 1.2.0 | |
binderror | eventhandle | 否 | 当使用开放能力时,发生错误的回调,open-type=launchApp时有效 | 1.9.5 | |
bindopensetting | eventhandle | 否 | 在打开授权设置页后回调,open-type=openSetting时有效 | 2.0.7 | |
bindlaunchapp | eventhandle | 否 | 打开 APP 成功的回调,open-type=launchApp时有效 | 2.4.4 | |
bindchooseavatar | eventhandle | 否 | 获取用户头像回调,open-type=chooseAvatar时有效 | 2.21.2 |
<button>普通按钮</button> <button type="primary">主色调按钮</button> <button type="warn">警告按钮</button> <button size="mini">普通按钮</button> <button type="primary" size="mini">主色调按钮</button> <button type="warn" size="mini">警告按钮</button>
open-type | string | 否 | 微信开放能力 | 1.1.0 | |||||||||||||||||||||||||||||
|
<view> <button type="default">默认</button> <button type="primary">确定</button> <button type="warn">警告</button> </view> <view> <button type="primary" size="mini">打印</button> <button type="warn" size="mini">删除</button> </view> <view> <button type="primary" plain="true">镂空</button> </view> <view> <button type="primary" loading="true">加载中</button> </view> <view> <button open-type="chooseAvatar">获取头像</button> </view>
点击获取头像时的效果:
data: { "avatarUrl":"https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0" }, onChooseavatar(e){ let {avatarUrl}=e.detail; this.setData({avatarUrl}); },
2.7、image
图片组件。支持 JPG、PNG、SVG、WEBP、GIF 等格式
相比与html的image,可以通过mode属性更加灵活的改变图片样式
属性说明
属性 | 类型 | 默认值 | 必填 | 说明 | 最低版本 | ||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
src | string | 否 | 图片资源地址 | 1.0.0 | |||||||||||||||||||||||||||||||||||||||||||||||
mode | string | scaleToFill | 否 | 图片裁剪、缩放的模式 | 1.0.0 | ||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
webp | boolean | false | 否 | 默认不解析 webP 格式,只支持网络资源 | 2.9.0 | ||||||||||||||||||||||||||||||||||||||||||||||
lazy-load | boolean | false | 否 | 图片懒加载,在即将进入一定范围(上下三屏)时才开始加载 | 1.5.0 | ||||||||||||||||||||||||||||||||||||||||||||||
show-menu-by-longpress | boolean | false | 否 | 长按图片显示发送给朋友、收藏、保存图片、搜一搜、打开名片/前往群聊/打开小程序(若图片中包含对应二维码或小程序码)的菜单。 | 2.7.0 | ||||||||||||||||||||||||||||||||||||||||||||||
binderror | eventhandle | 否 | 当错误发生时触发,event.detail = {errMsg} | 1.0.0 | |||||||||||||||||||||||||||||||||||||||||||||||
bindload | eventhandle | 否 | 当图片载入完毕时触发,event.detail = {height, width} | 1.0.0 |
<image src="/images/rocket_top.png" mode="aspectFit" style="border: 1px red solid;"/>
更多标签见官方文档:https://developers.weixin.qq.com/miniprogram/dev/framework/
<view> <image src="/images/haha.jpg" mode="heightFix" show-menu-by-longpress="true"></image> </view> <view style="height: 2000px; background: red;"> </view> <view> <image src="https://res.wx.qq.com/wxdoc/dist/assets/img/0.4cb08bb4.jpg" lazy-load="true"></image> </view>
结果
2.8、input
输入框
更多:https://developers.weixin.qq.com/miniprogram/dev/component/input.html
<form> <view> <label for="txtId">帐号:</label> <input id="txtId" value="{{userId}}" bindinput="inputHandle" placeholder="请输入帐号" auto-focus="true"/> </view> <view> <label for="txtPhone">电话:</label> <input id="txtPhone" type="number"/> </view> <view> <label for="txtPassword">密码:</label> <input id="txtPassword" password="true"/> </view> <view> {{userId}} </view> </form>
const page={ data:{ userId:"" }, inputHandle(e){ console.log(e.detail.value,e.detail.cursor,e.detail.keyCode); this.setData({userId:e.detail.value}) //当用户输入2个11时自动变成1个2 return this.data.userId.replace(/11/igm,'2'); } }; Page(page)
2.9、checkbox,checkbox-group
多选项目。
更多:https://developers.weixin.qq.com/miniprogram/dev/component/checkbox.html
<form bindsubmit="submitHandle"> <view> <checkbox-group bindchange="checkboxChange"> 爱好: <label> <checkbox value="阅读" name="hobby" checked="true" color="orange"/>阅读 </label> <label> <checkbox value="健身" name="hobby"/>健身 </label> <label> <checkbox value="电影" name="hobby"/>电影 </label> <label> <checkbox value="其它" name="hobby" disabled/> </label> </checkbox-group> </view> <view> <button form-type="submit" type="primary">提交</button> </view> </form>
const page={
submitHandle(e){
console.log(e.detail);
},
checkboxChange(e){
console.log(e.detail);
}
};
Page(page)
2.10、radio,radio-group
单选项目
更多:https://developers.weixin.qq.com/miniprogram/dev/component/radio.html
<radio-group bindchange="radioChange"> 性别: <label> <radio value="男" checked="true"></radio>男 </label> <label> <radio value="女"></radio>女 </label> </radio-group>
const page={
radioChange(e){
console.log(e.detail.value);
}
};
Page(page)
2.11、slider
滑动选择器
<view> <slider bindchange="sliderChange1" show-value="true" max="200" min="100" step="5"/> </view> <view> <slider bindchange="sliderChange2" bindchanging="changingHandle" show-value="true"/> </view> <view> <slider bindchange="sliderChange3" show-value="true"/> </view> <view> <slider bindchange="sliderChange4" show-value="true"/> </view>
const page={ }; /*解决方法1 */ // for(var i=1;i<5;i++){ // (function(n){ // page[`sliderChange${n}`]=function(e){ // console.log(`第${n}个滑块,当前值:${e.detail.value}`); // } // })(i); // } /*解决方法2 */ for(let i=1;i<5;i++){ page[`sliderChange${i}`]=function(e){ console.log(`第${i}个滑块,当前值:${e.detail.value}`); } } page.changingHandle=function(e){ console.log(e.detail.value); } Page(page)
2.12、form
表单
表单。将组件内的用户输入的switch input checkbox slider radio picker 提交。
当点击 form 表单中 form-type 为 submit 的 button 组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
<form bindsubmit="submitHandle" bindreset="resetHandle"> <view> <label for="txtId">帐号:</label> <input name="userId" id="txtId" value="{{userId}}" bindinput="inputHandle" placeholder="请输入帐号" auto-focus="true"/> </view> <view> <label for="txtPhone">电话:</label> <input name="userPhone" id="txtPhone" type="number"/> </view> <view> <label for="txtPassword">密码:</label> <input name="userPwd" id="txtPassword" password="true"/> </view> <view> <button type="primary" form-type="submit" size="mini">提交</button> <button type="warn" form-type="reset" size="mini">重置</button> </view> <view> {{userId}} </view> </form>
const page={ data:{ userId:"" }, inputHandle(e){ console.log(e.detail.value,e.detail.cursor,e.detail.keyCode); this.setData({userId:e.detail.value}) //当用户输入2个11时自动变成1个2 return this.data.userId.replace(/11/igm,'2'); }, submitHandle(e){ console.log(e); }, resetHandle(e){ console.log(e); } }; Page(page)
三、WXML
3.1、整体介绍
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
用以下一些简单的例子来看看 WXML 具有什么能力:
3.1.1、数据绑定
<!--wxml-->
<view> {{message}} </view>
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
3.1.2、列表渲染
<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})
3.1.3、条件渲染
<!--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'
}
})
<view> <label for="name">姓名首字母:</label> <input id="name" value="{{name}}" bindinput="inputHandle"/> {{name}} <view wx:if="{{name==='t'}}">tom</view> <view wx:elif="{{name==='j'}}">jack</view> <view wx:else>请输入姓名的首字母,比如t,j</view> </view>
const page={ data:{ arr1:[1,2,3,4,5], name:"" }, inputHandle(e){ this.setData({name:e.detail.value}); } }; Page(page)
3.1.4、模板
<!--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'}
}
})
示例:
<template name="staff"> <view> <view>员工名片</view> <view>姓名:{{firstname}} {{lastname}} </view> </view> </template> <template is="staff" data="{{...staffA}}" ></template> <template is="staff" data="{{...staffB}}" ></template> <template is="staff" data="{{...staffC}}" ></template>
const page={ data:{ staffA:{firstname:"jack",lastname:"ma"}, staffB:{firstname:"rose",lastname:"li"}, staffC:{firstname:"mark",lastname:"liu"}, }, }; Page(page)
结果:
3.2、数据绑定
WXML 中的动态数据均来自对应 Page 的 data。
3.2.1、简单绑定
数据绑定使用 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 类型后代表真值。
3.2.2、运算
可以在 {{}}
内进行简单的运算,支持的有如下几种方式:
三元运算
<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']
}
})
3.2.3、组合
也可以在 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>
3.3、列表渲染
3.3.1、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>
<scroll-view scroll-x="true"> <view wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="i" class="item"> <view wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="j" class="exp"> <text wx:if="{{j<=i}}"> {{j}}x{{i}}={{i*j}}</text> </view> </view> </scroll-view>
.item { display: flex; } .exp{ width: 150rpx; }
从小程序基础库版本 2.3.0 开始,在 iPad 上运行的小程序可以支持屏幕旋转。使小程序支持 iPad 屏幕旋转的方法是:在 app.json 中添加 "resizable": true 。
3.3.2、block wx:for
类似 block wx:if
,也可以将 wx:for
用在<block/>
标签上,以渲染一个包含多节点的结构块。例如:
<block wx:for="{{[1, 2, 3]}}">
<view> {{index}}: </view>
<view> {{item}} </view>
</block>
3.3.3、wx:key
如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用 wx:key
来指定列表中项目的唯一的标识符。
wx:key
的值以两种形式提供
- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。
如不提供 wx:key
,会报一个 warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
3.3.4、示例代码
<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
})
}