微信小程序开发学习笔记(二)——小程序框架、组件、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&nbsp;2 &gt; &lt;</text>
</view>

示例:

<view>
  <text user-select="true" decode="true">Hello&nbsp;&nbsp;&nbsp;TEXT! &lt;
    <text>
      嵌套text
    </text>
  </text>
  <text>1</text><text>2</text>
</view>

结果:

原样输出,加上decode会编码。

  1. tip: decode可以解析的有 &nbsp; &lt; &gt; &amp; &apos; &ensp; &emsp;
  2. tip: 各个操作系统的空格标准并不一致。
  3. tip:text 组件内只支持 text 嵌套。
  4. tip: 除了文本节点以外的其他节点都无法长按选中。
  5. 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>

 

  1. tip: nodes 不推荐使用 String 类型,性能会有所下降。
  2. tiprich-text 组件内屏蔽所有节点的事件。
  3. tip: attrs 属性不支持 id ,支持 class 。
  4. tip: name 属性大小写不敏感。
  5. tip: 如果使用了不受信任的HTML节点,该节点及其所有子节点将会被移除。
  6. tip: img 标签仅支持网络图片。
  7. 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
 
合法值说明最低版本
contact 打开客服会话,如果用户在会话中点击消息卡片后返回小程序,可以从 bindcontact 回调中获得具体信息,具体说明 (*小程序插件中不能使用*) 1.1.0
share 触发用户转发,使用前建议先阅读使用指引 1.2.0
getPhoneNumber 获取用户手机号,可以从bindgetphonenumber回调中获取到用户信息,具体说明 (*小程序插件中不能使用*) 1.2.0
getUserInfo 获取用户信息,可以从bindgetuserinfo回调中获取到用户信息 (*小程序插件中不能使用*) 1.3.0
launchApp 打开APP,可以通过app-parameter属性设定向APP传的参数具体说明 1.9.5
openSetting 打开授权设置页 2.0.7
feedback 打开“意见反馈”页面,用户可提交反馈内容并上传日志,开发者可以登录小程序管理后台后进入左侧菜单“客服反馈”页面获取到反馈内容 2.1.0
chooseAvatar 获取用户头像,可以从bindchooseavatar回调中获取到头像信息 2.21.2

 

<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
 
合法值说明最低版本
scaleToFill 缩放模式,不保持纵横比缩放图片,使图片的宽高完全拉伸至填满 image 元素  
aspectFit 缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。  
aspectFill 缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。  
widthFix 缩放模式,宽度不变,高度自动变化,保持原图宽高比不变  
heightFix 缩放模式,高度不变,宽度自动变化,保持原图宽高比不变 2.10.3
top 裁剪模式,不缩放图片,只显示图片的顶部区域  
bottom 裁剪模式,不缩放图片,只显示图片的底部区域  
center 裁剪模式,不缩放图片,只显示图片的中间区域  
left 裁剪模式,不缩放图片,只显示图片的左边区域  
right 裁剪模式,不缩放图片,只显示图片的右边区域  
top left 裁剪模式,不缩放图片,只显示图片的左上边区域  
top right 裁剪模式,不缩放图片,只显示图片的右上边区域  
bottom left 裁剪模式,不缩放图片,只显示图片的左下边区域  
bottom right 裁剪模式,不缩放图片,只显示图片的右下边区域  
  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 的值以两种形式提供

  1. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
  2. 保留关键字 *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
    })
  }
})

<switch wx:for="{{objectArray}}" style="display: block;" wx:key="unique">{{item.id}}</switch>
<button bindtap="switchHandle" type="primary">切换</button>
<button bindtap="addToFront" type="primary">在最前面添加对象</button>
<switch wx:for="{{numberArray}}" wx:key="*this">{{item}}</switch>
<button bindtap="addNumberToFront" type="primary" >在最前面添加数字</button>
const 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:[3,2,1]
  },
  switchHandle(e){
    let length=this.data.objectArray.length;
    for(let i=0;i<length;i++){
      let x=Math.floor(Math.random()*length);
      let y=Math.floor(Math.random()*length);
      let 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(e){
    let length=this.data.objectArray.length;
    this.data.objectArray=[{id:length,unique:"unique_"+length}].concat(this.data.objectArray);
    this.setData({objectArray:this.data.objectArray});
  },
  addNumberToFront(e){
    let length=this.data.numberArray.length;
    this.data.numberArray=[length+1].concat(this.data.numberArray);
    this.setData({numberArray:this.data.numberArray});
  }
};

Page(page)

3.3.5、注意事项

当 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>

 3.4、条件渲染

3.4.1、wx:if

在框架中,使用 wx:if="" 来判断是否需要渲染该代码块:

<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>
<view>
  成绩:<input value="{{mark}}" bindinput="inputHandle"/>
  成绩是:{{mark}}
</view>
<view>
  等级是:
  <text wx:if="{{mark>=90}}">优秀</text>
  <text wx:elif="{{mark<90 && mark>=75}}">良好</text>
  <text wx:elif="{{mark<75 && mark>=60}}">及格</text>
  <text wx:else>不及格</text>
</view>
const page={
  data:{
    users:[{id:1001,name:"jack",age:18},
    {id:1002,name:"mark",age:17},
    {id:1003,name:"rose",age:20},
    {id:1004,name:"lili",age:15},
    {id:1005,name:"lucy",age:22}],
    isShow:true,
    array1:[1,2,3,4,5,6,7,8,9],
    mark:0
  },
  tapHandle(e){
    this.setData({isShow:!this.data.isShow});
  },
  inputHandle(e){
    this.setData({mark:e.detail.value})
  }
};

Page(page);

3.4.2、block wx:if

因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。

<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

3.4.3、wx:if vs hidden

因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。

同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。

相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。

一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。

<view wx:if="{{isShow}}">
  你可以看到我wx:if
</view>
<view hidden="{{!isShow}}">
  你可以看到我hidden
</view>
<view>
  <button bindtap="toggleIsShow">切换isShow的值={{isShow}}</button>
</view>
const page={
  data:{
    isShow:true
  },
  toggleIsShow(e){
    this.setData({isShow:!this.data.isShow})
  }
};

Page(page)

 3.5、模板

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。

3.5.1、定义模板

使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:

<!--
  index: int
  msg: string
  time: string
-->
<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>

<template name="card">
  <view class="card">
    <view>编号:{{id}}</view>
    <view>姓名:{{name}}</view>
    <view>年龄:{{age}}</view>
  </view>
</template>

<template is="card" data="{{id:1006,name:'张三',age:88}}"></template>
<template is="card" data="{{...user1}}"></template>
const page={
  data:{
    users:[{id:1001,name:"jack",age:18},
    {id:1002,name:"mark",age:17},
    {id:1003,name:"rose",age:20},
    {id:1004,name:"lili",age:15},
    {id:1005,name:"lucy",age:22}],
    isShow:true,
    array1:[1,2,3,4,5,6,7,8,9],
    user1:{id:1007,name:'李四',age:18}
  },
  tapHandle(e){
    this.setData({isShow:!this.data.isShow});
  },
};

Page(page);

3.5.2、使用模板

使用 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>
const page={
  data:{
    users:[{id:1001,name:"jack",age:18},
    {id:1002,name:"mark",age:17},
    {id:1003,name:"rose",age:20},
    {id:1004,name:"lili",age:15},
    {id:1005,name:"lucy",age:22}]
  }
};
Page(page);
<template name="cardA">
  <view class="card">
    <view>编号:{{id}}</view>
    <view>姓名:{{name}}</view>
    <view>年龄:{{age}}</view>
  </view>
</template>

<template name="cardB">
  <view class="card bgGreen">
    <text>编号:{{id}}</text>
    <text>姓名:{{name}}</text>
    <text>年龄:{{age}}</text>
  </view>
</template>

<view wx:for="{{users}}" wx:key="id">
  <template is="{{index%2===1?'cardA':'cardB'}}" data="{{...item}}"></template>
</view>
view{
  margin: 10rpx;
}
.card{
  background: oldlace;
  border-radius: 20rpx;
  padding: 16rpx;
  border: 2px solid orangered;
}
.bgGreen{
  background: lightgreen;
}

3.5.3、模板的作用域

模板拥有自己的作用域,只能使用 data 传入的数据以及模板定义文件中定义的 <wxs /> 模块。

 3.6、引用

WXML 提供两种文件引用方式importinclude

3.6.1、import

import可以在该文件中使用目标文件定义的template,如:

在 item.wxml 中定义了一个叫itemtemplate

<!-- item.wxml -->
<template name="item">
  <text>{{text}}</text>
</template>

在 index.wxml 中引用了 item.wxml,就可以使用item模板:

<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>

3.6.2、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"/>

3.6.3、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>

 

五、uni-app

5.1:什么是uni-app

uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS、Android、Web(响应式)、以及各种小程序(微信/支付宝/百度/头条/飞书/QQ/快手/钉钉/淘宝)、快应用等多个平台。

官方文档:https://uniapp.dcloud.net.cn/

5.2:uni-app的特点

优点

1、跨平台发行,运行体验更好
2、与小程序的组件、API一致;
3、兼容weex原生渲染,增加了开发效率高,但是由于weex坑比较多,建议还是使用局部渲染优化;
4、通用前端技术栈,学习成本更低
5、支持vue语法,微信小程序API
6、内嵌mpvue
7、开发生态,组件更丰富
8、支持通过npm安装第三方包
9、支持微信小程序自定义组件及JS SDK
10、兼容mpvue组件及项目(内嵌mpvue开源框架)
11、App端支持和原生混合编码
12、插件丰富,DCloud将发布插件到市场

缺点

1.、兼容性不够好:uni-app 对于不同平台的兼容性不够好,有些功能在不同平台上可能会有差异。

2.、文档不够完善:uni-app 的文档不够完善,有些功能的使用方法不够清晰,需要开发者自己去摸索。

5.3:创建uni-app

一、开始之前,开发者需先下载安装如下工具:HBuilderX

官网下载地址:https://www.dcloud.io/hbuilderx.html

二、打开HbuilderX,在点击工具栏里的文件 -> 新建 -> 项目

三、选择uni-app类型,输入工程名,选择模板,点击创建,即可成功创建。

四:配置uni-app的相关路径以及微信小程序的AppID

配置路径

 

配置AppID

 

五、一切准备就绪后,我们就可以在HBuilderX中启动我们的微信小程序了

初次编译可能会多耗费点时间

5.4:使用uni-app

首先我们来了解一下uni-app的目录结构

了解完了目录结构后,我们就可以根据需求来进行编码

在HBbuiltX中保存后,微信小程序会自动更新代码

5.5:使用uni-app的组件

假设我们现在需要用一个日历的组件

第一步:打开官网,选择组件,找到日历组件

 直接copy代码到我们的HBuildX中,即可

5.6:微信小程序底部导航栏

还记得我们前面所描述的,需要修改或添加我们的底部导航栏,只需要修改app.json即可

但在uni-app中,pages.json就相当于微信小程序中的app.json

申明一个"tabBar":他与pages同级,

示例:

"tabBar": {
        "color": "#999",//字体颜色
        "selectedColor": "#000000",//选中后的字体颜色
        "backgroundColor": "#FFF",//背景颜色
        "list": [{//组件集合
          "pagePath": "pages/index/index",//路径
          "text": "组件",//名称
          "iconPath": "static/c1.png",//图标
          "selectedIconPath": "static/c1.png"//选中后的图标
        }, {
          "pagePath": "pages/text/text",
          "text": "接口",
          "iconPath": "static/c2.png",
          "selectedIconPath": "static/c2.png"
        }]
      }
    }

效果图:

5.7:接口

前言:作为一个合格的程序员,哪有不会对接第三方接口的道理,那么微信小程序官方,也为我们开发者贴心的准备了很多有用的接口给大家,供大家参考

官方接口地址:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.pluginLogin.html

实例演示:wx.getUserProfile

注:微信更新到8.0.29版本以后,wx.getUserProfile 就不弹出授权窗口了。8.0.29版本的基础库为2.27.2

完整代码:

<template>
    <view>
        <view class="login-bg">
            <view class="login-body" open-type="getUserInfo" @click="getUser">
                微信授权登陆
            </view>
        </view>
    </view>
</template>

<script>
    export default {
        data() {
            return {}
        },
        methods: {
            getUser(e) {
                wx.getUserProfile({
                    desc: '用于完善会员资料',
                    success: (res) => {
                        console.log(res)
                    }
                })
            },
        }
    }
</script>

<style>
</style>

效果图:

 

四、视频

【微信小程序开发】 https://www.bilibili.com/video/BV1pv4y1n7Zg/?share_source=copy_web&vd_source=475a31f3c5d6353a782007cd4c638a8a

五、作业

(1)、完成微信发现页的页面布局

 注意选项卡、与分组,尽量把信息存放在一个数组中,通过for属性遍历出内容。

(2)、完成下面的页面布局

(3)、完成一个猜数字游戏

首页是菜单选择页,共包含3个按钮,具体内容解释如下:
开始游戏:点击跳转到游戏页面;
游戏规则:点击跳转到游戏规则页面;
关于我们:点击跳转到关于我们页面。

posted @ 2023-04-19 16:19  张果  阅读(629)  评论(0编辑  收藏  举报
AmazingCounters.com