小程序学习笔记整理

微信小程序

关于此学习的测试项目都暂时保存在https://github.com/ForeManWang/wxapp-study

微信小程序账号与工具

在线文档:https://mp.weixin.qq.com/debug/wxadoc/dev/

小程序开发者账号注册

微信公众平台:https://mp.weixin.qq.com/

小程序开发者账号注册:https://mp.weixin.qq.com/wxopen/waregister?action=step1

微信开发者工具

微信开发者工具:https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html

小程序在线Demo

微信小程序文件结构

主体文件结构

主体部分由三个文件组成,必须放在项目的根目录,如下:

文件 必填 作用
app.js 小程序逻辑
app.json 配置文件——小程序公共设置,主要界面外观设置
app.wxss 小程序公共样式表

页面文件结构

通过开发者工具快速创建了一个 QuickStart 项目。可以留意到这个项目里边生成了不同类型的文件:

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML(Wei Xin Markup Language) 模板文件
  3. .wxss 后缀的 WXSS(Wei Xin Style Sheets) 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

接下来我们分别看看这4种文件的作用。

页面由四个文件组成,分别是:

文件类型 必填 作用
js 页面逻辑 ( 微信小程序没有window和document对象 )
wxml 页面结构 ( XML语法,不是HTML语法 )
wxss 页面样式表 ( 拓展了rpx尺寸单位,微信专属响应式像素 )
json 页面配置 ( 不能写注释,否则编译报错 )

fileTree

微信小程序全局配置

app.json 配置项列表

app.json 是当前小程序的全局配置,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。可以看到生成的app.json配置内容如下:

1
2
3
4
5
6
7
8
9
{
  "pages": ["pages/index/index", "pages/logs/logs"],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "black"
  }
}

app.json配置各项的含义

属性 类型 必填 描述 最低版本
pages String Array 描述当前小程序所有页面路径,通常文件名和页面各文件名都相同  
window Object 定义小程序所有页面的顶部背景颜色,文字颜色定义等。  
tabBar Object 底部 tab 栏的表现  
networkTimeout Object 网络超时时间  
debug Boolean 是否开启 debug 模式,默认关闭  
functionalPages Boolean 是否启用插件功能页,默认关闭 2.1.0
subpackages Object Array 分包结构配置 1.7.3
workers String Worker 代码放置的目录 1.9.90
requiredBackgroundModes String Array 需要在后台使用的能力,如「音乐播放」  
plugins Object 使用到的插件 1.9.6
preloadRule Object 分包预下载规则 2.3.0
resizable Boolean iPad 小程序是否支持屏幕旋转,默认关闭 2.3.0
navigateToMiniProgramAppIdList String Array 需要跳转的小程序列表,详见 wx.navigateToMiniProgram 2.4.0
usingComponents Object 全局自定义组件配置 开发者工具 1.02.1810190
permission Object 小程序接口权限相关设置 微信客户端 7.0.0

pages

用于指定小程序由哪些页面组成,每一项都对应一个页面的 路径+文件名 信息。文件名不需要写文件后缀,框架会自动去寻找对于位置的 .json.js.wxml.wxss 四个文件进行处理。

例如app.json中,此时数组中第一项为默认首页,即index是首页

1
2
3
{
  "pages": ["pages/index/index", "pages/logs/logs"]
}

window

用于设置小程序的状态栏、导航条、标题、窗口背景色。

注意:页面的.json只能设置 window 相关的配置项,以决定本页面的窗口表现,所以无需写 window 这个键。

属性 类型 默认值 描述 最低版本
navigationBarBackgroundColor HexColor #000000 导航栏背景颜色,如 #000000  
navigationBarTextStyle String white 导航栏标题颜色,仅支持 black / white  
navigationBarTitleText String   导航栏标题文字内容  
navigationStyle String default 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮。参见注2。 微信客户端 6.6.0
backgroundColor HexColor #ffffff 窗口的背景色  
backgroundTextStyle String dark 下拉 loading 的样式,仅支持 dark / light  
backgroundColorTop String #ffffff 顶部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
backgroundColorBottom String #ffffff 底部窗口的背景色,仅 iOS 支持 微信客户端 6.5.16
enablePullDownRefresh Boolean false 是否开启当前页面的下拉刷新。 详见 Page.onPullDownRefresh  
onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom  
pageOrientation String portrait 屏幕旋转设置,仅支持 auto / portrait 详见 响应显示区域变化 微信客户端 6.7.3
  • 注1:HexColor(十六进制颜色值),如”#ff00ff”
  • 注2:关于navigationStyle
  • 客户端 7.0.0 以下版本,navigationStyle 只在 app.json 中生效。
  • 客户端 6.7.2 版本开始,navigationStyle: custom 对 组件无效
  • 开启 custom 后,低版本客户端需要做好兼容。开发者工具基础库版本切到 1.7.0(不代表最低版本,只供调试用)可方便切到旧视觉

如 app.json :

1
2
3
4
5
6
7
8
9
{
  "window": {
    "navigationBarBackgroundColor": "#ffffff",
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "微信接口功能演示",
    "backgroundColor": "#eeeeee",
    "backgroundTextStyle": "light"
  }
}

微信接口功能演示

config

tabBar

如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。

属性 类型 必填 默认值 描述 最低版本
color HexColor   tab 上的文字默认颜色,仅支持十六进制颜色  
selectedColor HexColor   tab 上的文字选中时的颜色,仅支持十六进制颜色  
backgroundColor HexColor   tab 的背景色,仅支持十六进制颜色  
borderStyle String black tabbar上边框的颜色, 仅支持 black / white  
list Array   tab 的列表,详见 list 属性说明,最少2个、最多5个 tab  
position String bottom tabBar的位置,仅支持 bottom / top  
custom Boolean false 自定义 tabBar,见详情 2.5.0
  1. tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。

属性说明

属性 类型 必填 说明
pagePath String 页面路径,必须在 pages 中先定义
text String tab 上按钮文字
iconPath String 图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px,当 postion 为 top 时,此参数无效
selectedIconPath String 选中时的图片路径,icon 大小限制为40kb,建议尺寸为 81px * 81px ,当 postion 为 top 时,此参数无效

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
  "pages":[
    "pages/index/index",
    "pages/logs/logs"
  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle":"black",
  },
  "debug": true,
  "tabBar": {
    "color": "#444",
    "backgroundColor": "#e0e0e0",
    "SelectedColor": "#219be3",
    "boderStyle": "black",
    "position": "bottom",
    "list": [
      {
        "text": "Home",
        "PagePath": "pages/index/index",
        "iconPath": "icons/grid-01.png"
      },
      {
        "text": "logs",
        "PagePath": "pages/logs/logs",
        "iconPath": "icons/grid-02.png"
      }
    ]
  }
}

图示:

tabBar.pnguploading.4e448015.gif转存失败重新上传取消tabBar.pnguploading.4e448015.gif转存失败重新上传取消tabBar.pnguploading.4e448015.gif转存失败重新上传取消tabBar

networkTimeout

各类网络请求的超时时间,单位均为毫秒。

属性 类型 必填 默认值 说明
request Number 60000 wx.request 的超时时间,单位:毫秒。
connectSocket Number 60000 wx.connectSocket 的超时时间,单位:毫秒。
uploadFile Number 60000 wx.uploadFile 的超时时间,单位:毫秒。
downloadFile Number 60000 wx.downloadFile 的超时时间,单位:毫秒。

debug

可以在开发者工具中开启 debug 模式,在开发者工具的控制台面板,调试信息以 info 的形式给出,其信息有Page的注册,页面路由,数据更新,事件触发等。可以帮助开发者快速定位一些常见的问题。

functionalPages

基础库 2.1.0 开始支持,低版本需做兼容处理

启用插件功能页时,插件所有者小程序需要设置其 functionalPages 为 true

subpackages

微信客户端 6.6.0 ,基础库 1.7.3 及以上版本支持。

启用分包加载时,声明项目分包结构。

写成 subPackages 也支持。

workers

基础库 1.9.90 开始支持,低版本需做兼容处理

使用 Worker 处理多线程任务时,设置 Worker 代码放置的目录。

requiredBackgroundModes

微信客户端 6.7.2 及以上版本支持。

申明需要后台运行的能力,类型为数组。目前支持以下项目:

  • audio: 后台音乐播放

如:

1
2
3
4
{
  "pages": ["pages/index/index"],
  "requiredBackgroundModes": ["audio"]
}

注:在此处申明了后台运行的接口,开发版和体验版上可以直接生效,正式版还需通过审核。

plugins

基础库 1.9.6 开始支持,低版本需做兼容处理

声明小程序需要使用的插件

preloadRule

基础库 2.3.0 开始支持,低版本需做兼容处理

声明分包预下载的规则。

resizable

基础库 2.3.0 开始支持,低版本需做兼容处理

在 iPad 上运行的小程序可以设置支持屏幕旋转

navigateToMiniProgramAppIdList

基础库 2.4.0 开始支持,低版本需做兼容处理

当小程序需要使用 wx.navigateToMiniProgram 接口跳转到其他小程序时,需要先在配置文件中声明需要跳转的小程序 appId 列表,最多允许填写 10 个。

usingComponents

开发者工具 1.02.1810190 及以上版本支持。

在此处声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。

permission

微信客户端 7.0.0 及以上版本支持

小程序接口权限相关设置。字段类型为 Object,结构为:

属性 类型 必填 默认值 描述
scope.userLocation PermissionObject   位置相关权限声明

PermissionObject 结构

属性 类型 必填 默认值 说明
desc string   小程序获取权限时展示的接口用途说明。最长30个字符

如:

1
2
3
4
5
6
7
8
{
  "pages": ["pages/index/index"],
  "permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序位置接口的效果展示"
    }
  }
}

allow

微信小程序页面配置

每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置。

页面的配置只能设置 app.json 中部分 window 配置项的内容,页面中配置项会覆盖 app.json 的 window 中相同的配置项。

配置示例

1
2
3
4
5
6
7
{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "微信接口功能演示",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light"
}

页面配置项列表

属性 类型 默认值 描述 最低版本
navigationBarBackgroundColor HexColor #000000 导航栏背景颜色,如 #000000  
navigationBarTextStyle String white 导航栏标题颜色,仅支持 black / white  
navigationBarTitleText String   导航栏标题文字内容  
navigationStyle String default 导航栏样式,仅支持以下值: default 默认样式 custom 自定义导航栏,只保留右上角胶囊按钮 微信客户端 7.0.0
backgroundColor HexColor #ffffff 窗口的背景色  
backgroundTextStyle String dark 下拉 loading 的样式,仅支持 dark / light  
enablePullDownRefresh Boolean false 是否全局开启下拉刷新。 详见 Page.onPullDownRefresh  
onReachBottomDistance Number 50 页面上拉触底事件触发时距页面底部距离,单位为px。 详见 Page.onReachBottom  
disableScroll Boolean false 设置为 true 则页面整体不能上下滚动。 只在页面配置中有效,无法在 app.json中设置  
disableSwipeBack Boolean false 禁止页面右滑手势返回 微信客户端 7.0.0

页面的.json只能设置 window 相关的配置项,以决定本页面的窗口表现,所以无需写 window 这个属性。

逻辑层App Service

小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发者 JavaScript 代码的运行环境以及微信小程序的特有功能。

逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。

逻辑层的JavaScript

  1. 小程序不是运行在Web的浏览器中,所以没有BOMDOM对象,就意味着没有documentwindow
  2. 在小程序中有一些额外的全局成员
    1. App 方法,用于定义应用实例对象
    2. Page 方法,用于定义页面对象
    3. getApp方法,用于获取全局应用程序实例对象
    4. getCurrentPages方法,用于获取当前页面的调用栈,
    5. 说明:历史栈指的是当前调用的页面和历史页面的栈,尝试打印console.log(getCurrentPage())打印出来是一个数组,意味着返回值是一个数组,然后this指向当前的页面,是当前页面的调用栈
    6. wx对象:丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力
    7. 每个页面有独立的作用域,并提供模块化能力。
    8. 小程序的JS是支持CommonJS规范的,也就是说可以通过require载入模块,通过module.exports导出模块,但不支持exports.xxx

视图层View

框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。

将逻辑层的数据反应成视图,同时将视图层的事件发送给逻辑层。

WXML(WeiXin Markup language) 用于描述页面的结构。

WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

WXSS(WeiXin Style Sheet) 用于描述页面的样式。

组件(Component)是视图的基本组成单元。

WXML

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件事件系统,可以构建出页面的结构。

数据绑定

将数据动态渲染到页面中

简单数据绑定

  1. 数据在哪?

    1. data:页面的初始数据,给页面供数据的,就是界面和逻辑之间的桥梁
    2. 示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    Page({
        ...
        data: {
            ...
            message: "hello wxxcx",
            ...
        }
         ...
    })
    
  1. 绑定到哪?

    1. 通过双大括号的形式,绑定数据到想要输出的位置
    2. <text></text>
  2. 简单数据绑定

    1. 绑定给页面中的text文本节点
    2. 绑定给class,为元素添加样式或者拼接样式
    3. 以字面量的形式或者简单的逻辑运算符(简单的运算或者三元表达式等)直接输出
    4. 双大括号的语法
      1. innerHTML
      2. 元素的属性上
      3. 不能用在标签名和属性名上
    5. 注意:若判断布尔类型时,要将true或者false包裹在双大括号内进行解析,防止被JS误解为字符串

列表渲染

将数组中的数据在页面中循环渲染

  1. index.js文件的data中定义一个数组,数组中的每一个成员都是一个对象
  2. index.wxml中利用wx:for=""遍历输出,注意这里的wx:for中间不能有空格
1
2
3
4
5
person: [
      { name: 'zhangsan', age: 18, adult: true },
      { name: 'wangwu', age: 20, adult: true },
      { name: 'zhaoliu', age: 16, adult: false }
    ]
1
2
3
4
<view wx:for="{
       
       { person }}">
   <checkbox checked='{
       
       { item.adult }}'></checkbox>
   <text>{
       
       { item.name }}</text>
</view>
  1. 如果全局属性中有一个item关键词,解决方法可以直接在循环的属性后面加上wx:for-item="项目名称缩写",那么下面遍历的时候也需要用你起的别名进行遍历,看下面示例
1
2
3
4
<view wx:for="{
       
       { person }}" wx:for-item="wx">
      <checkbox checked='{
       
       { wx.adult }}'></checkbox>
      <text>{
       
       { wx.name }}</text>
</view>
  1. 用 拿序号,但若关键字冲突,可以通过wx:for-index="i"去拿,那么下面拿序号的时候,就要用拿
1
2
3
4
5
<view wx:for="{
       
       { person }}" wx:for-item="wx" wx:for-index="i">
      <text>{
       
       { i }}</text>
      <checkbox checked='{
       
       { wx.adult }}'></checkbox>
      <text>{
       
       { wx.name }}</text>
</view>
  1. 另外wx:for的值在下面是可以点出来legth值的,我在代码中试了试
1
2
3
4
5
6
<view wx:for="{
       
       { person }}" wx:for-item="wx" wx:for-index="i">
      <text>{
       
       { i }}</text>
      <checkbox checked='{
       
       { wx.adult }}'></checkbox>
      <text>{
       
       { wx.name }}</text>
      <text>{
       
       { person.length }}</text>
</view>
  1. wx:for 也可以嵌套,下边是一个九九乘法表 ,我们将这个乘法口诀代码粘贴到自己的测试项目中看一下
1
2
3
4
5
<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>
  1. 渲染一个包含多节点的结构块: 可以将 wx:for 用在<block/>标签上
1
2
3
4
<block wx:for="{
       
       {[1, 2, 3]}}">
  <view>{
       
       {index}}:</view>
  <view>{
       
       {item}}</view>
</block>
  1. 使用 wx:key 来指定列表中项目的唯一的标识符
    1. 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如<input>中的输入内容,<switch>的选中状态)
    2. wx:key 的值以两种形式提供
      1. 作用:当数据发生改变时,快速定位更新的值,防止顺序错乱
      2. 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
      3. 保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字 ,如当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率
      4. 如不提供 wx:key,会报一个 warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
      5. 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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(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(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(e) {
    this.data.numberArray = [this.data.numberArray.length + 1].concat(this.data.numberArray)
    this.setData({
      numberArray: this.data.numberArray
    })
  }
})
1
2
3
4
5
6
7
8
9
10
<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>
  1. 注意:wx:for="string"的时候,会把字符串解析为数组,例如下面两个等价的代码
1
2
3
<view wx:for="hello">{
       
       {item}}</view>
// 等同于
<view wx:for="{
       
       { ['h', 'e', 'l', 'l', 'o'] }}">{
       
       {item}}</view>

​2. 注意:花括号和引号之间如果有空格,将最终被解析成为字符串

1
2
3
<view wx:for="{
       
       {[1,2,3]}} ">{
       
       {item}}</view>
// 等同于
<view wx:for="{
       
       {[1,2,3] + ' '}}">{
       
       {item}}</view>

条件渲染

  1. 当判断是否需要去渲染一个代码块的时候,就需要用到wx:if , 当需要判断是否添加一个代码块的时候,要用到wx:elif或者wx:else

示例:用在wx:for章节的代码,跟着后面添加了几句判断

1
2
3
<view wx:if="{
       
       { person.length > 5 }}">2</view>
<view wx:elif="{
       
       { person.length < 5 }}">3</view>
<view wx:else>1</view>
  1. 如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
1
2
3
4
<block wx:if="{
       
       {true}}">
  <view>view1</view>
  <view>view2</view>
</block
  1. 注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

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

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

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

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

模板

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

定义模板

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

1
2
3
4
5
6
7
8
9
10
11
<!--
  index: int
  msg: string
  time: string
-->
<template name="msgItem">
  <view>
    <text>{
       
       {index}}: {
       
       {msg}}</text>
    <text>Time: {
       
       {time}}</text>
  </view>
</template>

使用模板

使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:

1
<template is="msgItem" data="{
       
       {...item}}" />
1
2
3
4
5
6
7
8
9
Page({
  data: {
    item: {
      index: 0,
      msg: 'this is a template',
      time: '2016-09-15'
    }
  }
})

is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:

1
2
3
4
5
6
7
8
9
10
<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>

模板的作用域

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

事件

事件是视图层到逻辑层的通讯方式。

事件可以将用户的行为反馈到逻辑层进行处理。

事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。

事件对象可以携带额外信息,如 id, dataset, touches

事件的使用方式

  1. 在组件中绑定事件处理函数
1
2
3
<view class="container">
  <button bindtap='buttonTap'>点击我哦</button>
</view>
1
2
3
4
5
6
7
Page({
    ...
    buttonTap() {
    console.log('123')
  },
    ...
})
  1. buttonTap函数传参,但是微信开发中绑定事件函数的时候,明确的规定不能直接在后面加括号传参的,不然会报错,这时候和H5开发的时候一样,需要给元素添加自定义属性data-xxx,在逻辑层通过dataset拿到数据
1
<button bindtap='buttonTap' data-hello='事件传参'>点击我哦</button>
1
2
3
4
5
6
7
8
Page({
    ...
    buttonTap(e) {
    console.log(e)
    console.log(e.target)
  },
    ...
})
  1. 可以看到e对象里面有很多属性和方法方便以后使用

tap

  1. 看到e.target对象是这样的

事件传参

事件分类

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

  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 动画完成时触发  
touchforcechange 在支持 3D Touch 的 iPhone 设备,重按时会触发 1.9.90

注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如的submit事件,的input事件,的scroll事件,(详见各个组件)

事件绑定和冒泡

事件绑定的写法同组件的属性,以 key、value 的形式 :

  • key 以bindcatch开头,然后跟上事件的类型,如bindtapcatchtouchstart。自基础库版本 1.5.0 起,在非原生组件中,bindcatch后可以紧跟一个冒号,其含义不变,如bind:tapcatch:touchstart
  • value 是一个字符串,需要在对应的 Page 中定义同名的函数,不然当触发事件的时候会报错
1
2
3
4
5
6
7
<view id="outer" style='width: 200px; height: 200px; background-color:red'  bindtap="handleTap1">
  我是他爷爷
  <view id="middle" style='width: 100px; height: 100px; background-color:yellow'  bindtap="handleTap2">
    我是他爸爸
    <view id="inner" style='width: 50px; height: 50px; background-color:blue'  bindtap="handleTap3">我是他儿子</view>
  </view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
Page({
    ...
    handleTap1() {
    console.log('我是他爷爷')
    },
    handleTap2() {
      console.log('我是他爸爸')
    },
    handleTap3() {
      console.log('我是他儿子')
    },
    ...
})

实际上熟悉JS事件冒泡的对于这个都不难理解,就是子元素的事件会向上冒泡给相同事件的父元素

阻止事件冒泡

cstch + xxx阻止冒泡

将上面的案例中的其中一个父元素绑定一下阻止冒泡的事件,观察下

1
2
3
4
5
6
7
<view id="outer" style='width: 200px; height: 200px; background-color:red'  bindtap="handleTap1">
  我是他爷爷
  <view id="middle" style='width: 100px; height: 100px; background-color:yellow'  catchtap="handleTap2">
    我是他爸爸
    <view id="inner" style='width: 50px; height: 50px; background-color:blue'  bindtap="handleTap3">我是他儿子</view>
  </view>
</view>

这样的话,事件冒泡到我是他爸爸这个盒子之后就不会再冒泡了

事件捕获

自基础库版本 1.5.0 起,触摸类事件支持捕获阶段。捕获阶段位于冒泡阶段之前,且在捕获阶段中,事件到达节点的顺序与冒泡阶段恰好相反。需要在捕获阶段监听事件时,可以采用capture-bindcapture-catch关键字,后者将中断捕获阶段和取消冒泡阶段。

在下面的代码中,点击 inner view 会先后调用handleTap2handleTap4handleTap3handleTap1

1
2
3
4
<view id="outer" style='width: 200px; height: 200px; background-color:red'  bind:tap="handleTap1" capture-bind:tap="handleTap2">
    我是他爸爸
    <view id="middle" style='width: 100px; height: 100px; background-color:yellow' bind:tap="handleTap3" capture-bind:tap="handleTap4"> 我是我自己</view>
  </view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Page({
    ...
    handleTap1() {
    console.log('我是handleTap1')
    },
    handleTap2() {
      console.log('我是handleTap2')
    },
    handleTap3() {
      console.log('我是handleTap3')
    },
    handleTap4() {
      console.log('我是handleTap4')
    },
    ...
})

%E4%BA%8B%E4%BB%B6%E6%8D%95%E8%8E%B7.pnguploading.4e448015.gif转存失败重新上传取消%E4%BA%8B%E4%BB%B6%E6%8D%95%E8%8E%B7.pnguploading.4e448015.gif转存失败重新上传取消%E4%BA%8B%E4%BB%B6%E6%8D%95%E8%8E%B7.pnguploading.4e448015.gif转存失败重新上传取消事件捕获

如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2

事件对象

如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象

BaseEvent 基础事件对象属性列表:

属性 类型 说明
type String 事件类型
timeStamp Integer 事件生成时的时间戳
target Object 触发事件的组件的一些属性值集合
currentTarget Object 当前组件的一些属性值集合

CustomEvent 自定义事件对象属性列表(继承 BaseEvent):

属性 类型 说明
detail Object 额外的信息

TouchEvent 触摸事件对象属性列表(继承 BaseEvent):

属性 类型 说明
touches Array 触摸事件,当前停留在屏幕中的触摸点信息的数组
changedTouches Array 触摸事件,当前变化的触摸点信息的数组

特殊事件: 中的触摸事件不可冒泡,所以没有 currentTarget。

type

代表事件的类型

timeStamp

页面打开到触发事件所经过的毫秒数

target

触发事件的源组件

属性 类型 说明
id String 事件源组件的id
tagName String 当前组件的类型
dataset Object 事件源组件上由data-开头的自定义属性组成的集合

currentTarget

事件绑定的当前组件

属性 类型 说明
id String 当前组件的id
tagName String 当前组件的类型
dataset Object 当前组件上由data-开头的自定义属性组成的集合

说明: target 和 currentTarget 可以参考前面的例子

dataset

这个在前面传参中也有提到过

在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE。 书写方式: 以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写)如data-element-type,最终在 event.currentTarget.dataset 中会将连字符转成驼峰elementType

示例

1
2
3
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap">
  DataSet Test
</view>
1
2
3
4
5
6
Page({
  bindViewTap(event) {
    event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
    event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
  }
})

touches

touches 是一个数组,每个元素为一个 Touch 对象(canvas 触摸事件中携带的 touches 是 CanvasTouch 数组)。 表示当前停留在屏幕上的触摸点

Touch 对象

属性 类型 说明
identifier Number 触摸点的标识符
pageX, pageY Number 距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴
clientX, clientY Number 距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴

CanvasTouch 对象

属性 类型 说明 特殊说明
identifier Number 触摸点的标识符  
x, y Number 距离 Canvas 左上角的距离,Canvas 的左上角为原点 ,横向为X轴,纵向为Y轴

changedTouches

changedTouches 数据格式同 touches。 表示有变化的触摸点,如从无变有(touchstart),位置变化(touchmove),从有变无(touchend、touchcancel)

detail

自定义事件所携带的数据,如表单组件的提交事件会携带用户的输入,媒体的错误事件会携带错误信息,详见组件定义中各个事件的定义

点击事件的detail 带有的 x, y 同 pageX, pageY 代表距离文档左上角的距离

引用

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

import

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

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

1
2
3
4
<!-- item.wxml -->
<template name="item">
  <text>{
       
       {text}}</text>
</template>

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

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

import 的作用域

import 有作用域的概念,即只会 import 目标文件中定义的 template,而不会 import 目标文件 import 的 template

如:C import B,B import A,在C中可以使用B定义的template,在B中可以使用A定义的template,但是C不能使用A定义的template

1
2
3
4
<!-- A.wxml -->
<template name="A">
  <text>A template</text>
</template>
1
2
3
4
5
<!-- B.wxml -->
<import src="a.wxml" />
<template name="B">
  <text>B template</text>
</template>
1
2
3
4
5
<!-- C.wxml -->
<import src="b.wxml" />
<template is="A" />
<!-- Error! Can not use tempalte when not import A. -->
<template is="B" />

include

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

1
2
3
4
5
6
7
8
<!-- index.wxml -->
<include src="header.wxml" />
<view>body</view>
<include src="footer.wxml" />
<!-- header.wxml -->
<view>header</view>
<!-- footer.wxml -->
<view>footer</view>

单向数据流

由于微信小程序框架中没有像Angular中的ngMoudel或者Vue中的v-model的双向数据绑定,所以默认微信小程序中的数据流只有单向数据流

1
2
3
4
5
6
7
8
9
10
11
12
Page({
    ...
    inputHandle(e) {
    // console.log(e.detail.value)
    // console.log(this.data.message)
    // this.data.message = e.detail.value 
    this.setData({
      message: e.detail.value
    }) 
  },
  ...
})
1
2
<input value='{
       
       { message }}' bindinput='inputHandle'></input>
<text>{
       
       { message }}</text>

发现只有内存中的数据改变了,页面却不能跟随变化

双向数据绑定

利用setData()这个内部方法进行双向数据绑定

1
2
3
4
5
6
7
8
9
Page({
    ...
    inputHandle(e) {
    // console.log(e.detail.value)
    // console.log(this.data.message)
    this.data.message = e.detail.value    
  },
  ...
})

这样实现内存和页面中数据同步更新

WXSS 样式

WXSS(WeiXin Style Sheets)是一套样式语言。

与 CSS 相比,WXSS 扩展以下2个特性:

  • 尺寸单位 rpx ( responsive pixel 响应式像素) ,750rpx充满屏幕
  • 样式导入 @import “样式表路径”;

微信小程序组件(标签)

组件文档:https://developers.weixin.qq.com/miniprogram/dev/component/

常用布局标签

1
2
3
4
5
<view></view>				视图容器,相当于    <div></div>
<text></text>				相当于    <span></span>  
<image></image>				相当于    <img />
<navigator></navigator>		相当于    <a></a>
<block></block>				区块标签,不会渲染到页面

注意:image组件默认宽度300px、高度225px,很多时候我们都不需要这个默认宽高,记得手动设置宽高

flex布局

参考文档https://qqqww.com/Flex%E5%B8%83%E5%B1%80/

页面间跳转(navigator)

新建页面小技巧

当我们新建页面的时候,自己去新建一个页面,每个页面还要新建好几个文件,很麻烦,这里其实不需要直接新建,在配置app.json的时候,微信开发者工具会自动帮我们创建好,看下图,我左侧是没有demo4这个页面的,但是右边配置中写上了"pages/demo4/deom4",那么ctrl+s保存之后,可以看到,左边的页面以及需求的文件都被自动创建出来了

%E4%BF%9D%E5%AD%98%E5%89%8D.pnguploading.4e448015.gif转存失败重新上传取消%E4%BF%9D%E5%AD%98%E5%89%8D.pnguploading.4e448015.gif转存失败重新上传取消%E4%BF%9D%E5%AD%98%E5%89%8D.pnguploading.4e448015.gif转存失败重新上传取消保存前

保存后

如何做页面跳转

语法

  1. 在当前页面设置跳转
1
<navigator url="想去到达页面的相对路径"></navigator>
  1. 配置json,不然页面跳转无法显示
1
2
3
{
  "usingComponents": {}
}

页面间传值

以往通过?或者请求体进行传值

在小程序中,页面间的传值,也可以利用?传参,在需要使用的传过来的数的时候,在该页面的js文件的onLoad生命周期的时候通过options去接受参数

1
2
3
// demo1.wxml
<navigator url="../demo2/demo2?name=小明&age=18">小明</navigator>
<navigator url="../demo2/demo2?name=小红">小红</navigator>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// pages/demo2/demo2.js
Page({
  data:{},
  onLoad:function(options){
    // 页面初始化 options为页面跳转所带来的参数
    console.log(options)
  },
  onReady:function(){
    // 页面渲染完成
  },
  onShow:function(){
    // 页面显示
  },
  onHide:function(){
    // 页面隐藏
  },
  onUnload:function(){
    // 页面关闭
  }
})

页面导航模式

通过redirect进行重定向,类型时布尔类型

1
2
// demo1.wxml
<navigator url="../demo2/demo2" redirect>跳转过去(不回来了)</navigator>

导航元素点击高亮

利用hover-class控制点击时添加自定义的高亮的类

1
2
3
// demo1.wxml
<navigator hover-class="my-hover">点我点我</navigator>
<navigator hover-class="none">点我点我</navigator>
1
2
3
4
// demo1.wxss
.my-hover {
    color: red;
}

cursor pointer 的方式是一个小技巧,可以让任何元素点击时高亮

1
2
// demo1.wxml
<image class="hover-demo" src="../../images/poster.jpg"></image>
1
2
3
4
// demo1.wxss
.hover-demo {
    cursor: pointer;
}

页面导航API

可以利用wx.navigateTo进行跳转,并可以在url中添加链接,?后面接收参数

1
2
// demo1.wxml
<button type="primary" bindtap="tapHandle">跳转过去</button>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// demo1.js
Page({
    tapHandle: function () {
        // 当我们点击按钮 系统会自动执行这里的代码
        // console.log(1111)
        wx.navigateTo({
          url: '../demo2/demo2?id=123'
        })

        // 相当于加上redirect的 navigator
        // wx.redirectTo({
        //   url: '../demo2/demo2'
        // })
    }
})

基础内容

组件名 说明
icon 图标
text 文字,可以嵌套,支持换行
rich-text 富文本
progress 进度条

icon

属性名 类型 默认值 说明
type String   icon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clear
size Number / String 23px icon的大小,单位px(2.4.0起支持rpx)
color Color   icon的颜色,同css的color
aria-label String   无障碍访问,(属性)元素的额外描述 2.5.0

属性type

  • 用于定义图标类型,只能是规定范围的类型,除了这些内置图标,其他的图标必须通过图片的方式使用
1
<icon type="success"></icon>

属性size

  • size用于指定图标大小,默认是 23px
1
<icon type="success" size="60"></icon>

属性color

  • color用于指定图标颜色,取值和css取值一样
1
<icon type="success" size="60" color="red"></icon>

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 生效。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<view class="page-body">
  <view class="page-section">
    <view class="page-section-title">传入html字符串</view>
    <view class="rich-text-wrp">
      <rich-text nodes="{
       
       {html}}" bindtap="tap"></rich-text>
    </view>
  </view>

  <view class="page-section">
    <view class="page-section-title">传入节点列表</view>
    <view class="rich-text-wrp">
      <rich-text nodes="{
       
       {nodes}}" bindtap="tap"></rich-text>
    </view>
  </view>
</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
rich-text {
  width: 700rpx;
  padding: 25rpx 0;
}

.rich-text-wrp {
  padding: 0 25rpx;
  background-color: #fff;
}

.page-section{
  width: 100%;
  margin-bottom: 60rpx;
}

.page-section:last-child{
  margin-bottom: 0;
}

.page-section-title{
  font-size: 28rpx;
  color: #999999;
  margin-bottom: 10rpx;
  padding-left: 30rpx;
  padding-right: 30rpx;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Page({
  data: {
    html: '<div class="div_class" style="line-height: 60px; color: red;">Hello&nbsp;World!</div>',
    nodes: [{
      name: 'div',
      attrs: {
        class: 'div_class',
        style: 'line-height: 60px; color: red;'
      },
      children: [{
        type: 'text',
        text: 'Hello&nbsp;World!'
      }]
    }]
  },
  tap() {
    console.log('tap')
  }
})

progress

  • 这个直接写代码到页面上是不会出现进度条的,原因在于其父元素的设置了flexalign-item:center导致没有宽度,需要自己加宽度才能显示,看下图,修改了控制台内其父元素的样式之后就可以了

progress

  • 加上active属性,有一个从左到右的进度条动画
  • 其他属性
属性名 类型 默认值 说明 最低版本
percent Float 百分比0~100  
show-info Boolean false 在进度条右侧显示百分比  
border-radius Number / String 0 圆角大小,单位px(2.4.0起支持rpx) 2.3.1
font-size Number / String 16 右侧百分比字体大小,单位px(2.4.0起支持rpx) 2.3.1
stroke-width Number / String 6 进度条线的宽度,单位px(2.4.0起支持rpx)  
color Color #09BB07 进度条颜色 (请使用 activeColor)  
activeColor Color   已选择的进度条的颜色  
backgroundColor Color   未选择的进度条的颜色  
active Boolean false 进度条从左往右的动画  
active-mode String backwards backwards: 动画从头播;forwards:动画从上次结束点接着播 1.7.0
bindactiveend EventHandle   动画完成事件 2.4.1
aria-label String   无障碍访问,(属性)元素的额外描述 2.5.0

常用表单标签

1
2
3
4
<button></button>
<input type="text" />				
<checkbox />
<radio/>

button

button参考文档

type有效值

1
2
3
<button type='warn'>这是一个红色按钮</button>
<button type='primary'>这是一个绿色按钮</button>
<button type='default'>这是一个白色按钮</button>

size有效值

1
2
3
<button type='warn' size='default'>这是一个红色按钮</button>
<button type='primary' size='mini'>这是一个小尺寸绿色按钮</button>
<button type='default'>这是一个白色按钮</button>

form-type 有效值

说明
submit 提交表单
reset 重置表单

hover-class

当按钮按下去,将hover-class指向想要展示出来的类

1
<button hover-class='btn-active'>hover-class</button>
1
2
3
.btn-active {
  background: red;
}

演示图片

button.pnguploading.4e448015.gif转存失败重新上传取消button.pnguploading.4e448015.gif转存失败重新上传取消button.pnguploading.4e448015.gif转存失败重新上传取消button

checkbox

多选框

checkbox-group

多项选择器,内部由多个checkbox组成。

属性名 类型 默认值 说明
bindchange EventHandle   <checkbox-group>中选中项发生改变时触发 change 事件,detail = {value:[选中的checkbox的value的数组]}

checkbox

多选项目。

属性名 类型 默认值 说明 最低版本
value String   标识,选中时触发的 change 事件,并携带 的 value  
disabled Boolean false 是否禁用  
checked Boolean false 当前是否选中,可用来设置默认选中  
color Color   checkbox的颜色,同css的color  
aria-label String   无障碍访问,(属性)元素的额外描述 2.5.0

演示图片

form

类似于HTML的form,将一些需要在表单中呈现的元素框起来

区别

这里的form事件绑定方式是通过:bindsubmit提交,和bindreset重置

注意

表单,将组件内的用户输入的<switch>、<input>、<checkbox>、<slider>、<radio>、<picker>提交。

当点击<form>表单中 form-type 为 submit 的<button>组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<form bindsubmit="formSubmit" bindreset="formReset">
  <view class="section section_gap">
    <view class="section__title">switch</view>
    <switch name="switch" />
  </view>
  <view class="section section_gap">
    <view class="section__title">slider</view>
    <slider name="slider" show-value></slider>
  </view>

  <view class="section">
    <view class="section__title">input</view>
    <input name="input" placeholder="please input here" />
  </view>
  <view class="section section_gap">
    <view class="section__title">radio</view>
    <radio-group name="radio-group">
      <label>
        <radio value="radio1" />
        radio1
      </label>
      <label>
        <radio value="radio2" />
        radio2
      </label>
    </radio-group>
  </view>
  <view class="section section_gap">
    <view class="section__title">checkbox</view>
    <checkbox-group name="checkbox">
      <label>
        <checkbox value="checkbox1" />
        checkbox1
      </label>
      <label>
        <checkbox value="checkbox2" />
        checkbox2
      </label>
    </checkbox-group>
  </view>
  <view class="btn-area">
    <button form-type="submit">Submit</button>
    <button form-type="reset">Reset</button>
  </view>
</form>
1
2
3
4
5
6
7
8
Page({
  formSubmit(e) {
    console.log('form发生了submit事件,携带数据为:', e.detail.value)
  },
  formReset() {
    console.log('form发生了reset事件')
  }
})

input

input在线文档

和原生基本类似,体验

1
<input class='input1' placeholder='请输入...' placeholder-class='input-placeholder'></input>
1
2
3
4
5
6
7
.input1 {
  border: 1px solid #c0c0c0;
}

.input-placeholder {
  color: red;
}

label

基本和HTML差不多

用来改进表单组件的可用性,使用for属性找到对应的id,或者将控件放在该标签下,当点击时,就会触发对应的控件。

for优先级高于内部控件,内部有多个控件的时候默认触发第一个控件。

目前可以绑定的控件有:[button checkbox radio switch

属性名 类型 说明
for String 绑定控件的 id

picker

支持滚动的选择器,类似下图这样

目前picker支持五类选择器,普通选择器,多列选择器,时间选择器(一天内的时间),日期选择器(年月日),省市选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<view class="section">
  <view class="section__title">普通选择器</view>
  <picker bindchange="bindPickerChange" value="{
       
       {index}}" range="{
       
       {array}}">
    <view class="picker">
      当前选择:{
       
       {array[index]}}
    </view>
  </picker>
</view>
<view class="section">
  <view class="section__title">多列选择器</view>
  <picker mode="multiSelector" bindchange="bindMultiPickerChange" bindcolumnchange="bindMultiPickerColumnChange" value="{
       
       {multiIndex}}" range="{
       
       {multiArray}}">
    <view class="picker">
      当前选择:{
       
       {multiArray[0][multiIndex[0]]}},{
       
       {multiArray[1][multiIndex[1]]}},{
       
       {multiArray[2][multiIndex[2]]}}
    </view>
  </picker>
</view>
<view class="section">
  <view class="section__title">时间选择器</view>
  <picker mode="time" value="{
       
       {time}}" start="09:01" end="21:01" bindchange="bindTimeChange">
    <view class="picker">
      当前选择: {
       
       {time}}
    </view>
  </picker>
</view>

<view class="section">
  <view class="section__title">日期选择器</view>
  <picker mode="date" value="{
       
       {date}}" start="2015-09-01" end="2017-09-01" bindchange="bindDateChange">
    <view class="picker">
      当前选择: {
       
       {date}}
    </view>
  </picker>
</view>
<view class="section">
  <view class="section__title">省市区选择器</view>
  <picker mode="region" bindchange="bindRegionChange" value="{
       
       {region}}" custom-item="{
       
       {customItem}}">
    <view class="picker">
      当前选择:{
       
       {region[0]}},{
       
       {region[1]}},{
       
       {region[2]}}
    </view>
  </picker>
</view>
1
2
3
4
5
6
// 这里注意需要现在`lib`文件夹中放入`weui.wxss`的依赖文件
@import "../lib/weui.wxss";
.picker{
    padding: 13px;
    background-color: #FFFFFF;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Page({
  data: {
    array: ['美国', '中国', '巴西', '日本'],
    objectArray: [
      {
        id: 0,
        name: '美国'
      },
      {
        id: 1,
        name: '中国'
      },
      {
        id: 2,
        name: '巴西'
      },
      {
        id: 3,
        name: '日本'
      }
    ],
    index: 0,
    multiArray: [['无脊柱动物', '脊柱动物'], ['扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'], ['猪肉绦虫', '吸血虫']],
    objectMultiArray: [
      [
        {
          id: 0,
          name: '无脊柱动物'
        },
        {
          id: 1,
          name: '脊柱动物'
        }
      ], [
        {
          id: 0,
          name: '扁性动物'
        },
        {
          id: 1,
          name: '线形动物'
        },
        {
          id: 2,
          name: '环节动物'
        },
        {
          id: 3,
          name: '软体动物'
        },
        {
          id: 3,
          name: '节肢动物'
        }
      ], [
        {
          id: 0,
          name: '猪肉绦虫'
        },
        {
          id: 1,
          name: '吸血虫'
        }
      ]
    ],
    multiIndex: [0, 0, 0],
    date: '2016-09-01',
    time: '12:01',
    region: ['广东省', '广州市', '海珠区'],
    customItem: '全部'
  },
  bindPickerChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      index: e.detail.value
    })
  },
  bindMultiPickerChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      multiIndex: e.detail.value
    })
  },
  bindMultiPickerColumnChange: function (e) {
    console.log('修改的列为', e.detail.column, ',值为', e.detail.value);
    var data = {
      multiArray: this.data.multiArray,
      multiIndex: this.data.multiIndex
    };
    data.multiIndex[e.detail.column] = e.detail.value;
    switch (e.detail.column) {
      case 0:
        switch (data.multiIndex[0]) {
          case 0:
            data.multiArray[1] = ['扁性动物', '线形动物', '环节动物', '软体动物', '节肢动物'];
            data.multiArray[2] = ['猪肉绦虫', '吸血虫'];
            break;
          case 1:
            data.multiArray[1] = ['鱼', '两栖动物', '爬行动物'];
            data.multiArray[2] = ['鲫鱼', '带鱼'];
            break;
        }
        data.multiIndex[1] = 0;
        data.multiIndex[2] = 0;
        break;
      case 1:
        switch (data.multiIndex[0]) {
          case 0:
            switch (data.multiIndex[1]) {
              case 0:
                data.multiArray[2] = ['猪肉绦虫', '吸血虫'];
                break;
              case 1:
                data.multiArray[2] = ['蛔虫'];
                break;
              case 2:
                data.multiArray[2] = ['蚂蚁', '蚂蟥'];
                break;
              case 3:
                data.multiArray[2] = ['河蚌', '蜗牛', '蛞蝓'];
                break;
              case 4:
                data.multiArray[2] = ['昆虫', '甲壳动物', '蛛形动物', '多足动物'];
                break;
            }
            break;
          case 1:
            switch (data.multiIndex[1]) {
              case 0:
                data.multiArray[2] = ['鲫鱼', '带鱼'];
                break;
              case 1:
                data.multiArray[2] = ['青蛙', '娃娃鱼'];
                break;
              case 2:
                data.multiArray[2] = ['蜥蜴', '龟', '壁虎'];
                break;
            }
            break;
        }
        data.multiIndex[2] = 0;
        console.log(data.multiIndex);
        break;
    }
    this.setData(data);
  },
  bindDateChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      date: e.detail.value
    })
  },
  bindTimeChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      time: e.detail.value
    })
  },
  bindRegionChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      region: e.detail.value
    })
  }
})

picker-view

和picker类似

radio

单项选择器,用法同html

slider

滑动选择器

switch

开关选择器

textarea

多行输入框,和html一样

操作组件

通过方法调用来呈现组件(交互操作组件必须通过调用API的方式来调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Page({
  data: {

  },
  btnTodo() {
    // 当点击按钮触发
    // console.log('111')
    wx.showActionSheet({
      // 显示出来的项目列表
      itemList: ['a', 'b', 'c'],
      // 成功回调
      success: function (res) {
        if(!res.cancel) {
          console.log(res.tapIndex)
        }
      }
    })
  }
})
1
<button type='primary' bindtap='btnTodo'>你要点击我哦</button>

另外模态框和上面用法一致….

轮播图组件

1
2
3
4
5
6
7
8
<swiper indicator-dots="是否显示面板指示点" autoplay="是否自动切换" interval="自动切换时间间隔" duration="滑动动画时长">
	<swiper-item>
      	<image src="图片路径1" width="375" height="150"/>
    </swiper-item>
	<swiper-item>
      	<image src="图片路径2" width="375" height="150"/>
    </swiper-item>
</swiper>

探索:实现无缝轮播怎么办?

总结

  1. 组件的基本用法:
    1. 组件的语法问题
      1. 组件得使用是类似于HTML的方式,但是又有不同,组件使用的是严格的XML标准(例如结束标签问题要注意)
    2. 组件的分类
      1. 功能型组件(progress、checkbox、radio等具有具体功能的)
      2. 布局类型组件,用来完成页面结构
      3. API类型组件,例如wx.showModal,通过调用API来使用

微信小程序页面函数

生命周期函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Page({
  /** 页面的初始数据 */
  data: {
  },
  /** 生命周期函数--监听页面加载 */
  onLoad: function (options) {
  },
  /** 生命周期函数--监听页面初次渲染完成 */
  onReady: function () {
  },
  /** 生命周期函数--监听页面显示 */
  onShow: function () {
  },
  /** 生命周期函数--监听页面隐藏 */
  onHide: function () {
  },
  /** 生命周期函数--监听页面卸载 */
  onUnload: function () {
  }
})

页面相关事件处理函数

1
2
3
4
5
6
7
8
9
/** 页面相关事件处理函数--监听用户下拉动作 */
 onPullDownRefresh: function () {
 },
 /** 页面上拉触底事件的处理函数 */
 onReachBottom: function () {
 },
 /** 用户点击右上角分享 */
 onShareAppMessage: function () {
 }

WXS 脚本

WXS(WeiXin Script)是小程序的一套脚本语言,功能类似<script>标签,用于在视图层定义函数(比较少用)

1
2
3
4
5
6
7
8
9
10
<!--wxml-->
<wxs module="foo">
var sum = function(a,b){
  return a+b
}
// 这里可以导出一个对象,这个对象可以直接在界面上使用 
module.exports.sum = sum
</wxs>

<view> {
       
       {foo.sum}} </view>

猜你喜欢

转载自blog.csdn.net/qq_45555960/article/details/105718399