小程序开发

1、初识小程序

1.1、什么是微信小程序

微信小程序,小程序的一种,英文名Wechat Mini Program,是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或搜一下即可打开应用

2017年1月9日,张小龙在2017微信公开课Pro上发布的微信小程序正式上线。

2019年8月9日,微信向开发者发布新能力公测与更新公告,微信PC版新版本中,支持打开聊天中分享的微信小程序。

1.2、注册小程序账号

官方网站:https://mp.weixin.qq.com/cgi-bin/wx

按照页面的流程一步步进行注册

image-20200625145303875

1.3、开发环境准备

  1. 下载开发工具

    • 下载网站:https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html
    • 选择相应的电脑版本进行下载

    image-20200625150156548

  2. 获取小程序AppID和AppSecret密钥

  3. 下载完成之后可以进行登录

    • 登录界面

      image-20200625150646394

    • 新增项目,添加刚才获取的AppID

      image-20200625150859819

    • 现在可以正式开发了

      image-20200625150951101

1.4、第一个小程序

  1. 打开刚才新建的项目

  2. 修改index.wxml中的代码,<view>标签就是显示内容的。

    <view class="usermotto">
        <!-- 修改为“第一个小程序测试效果” -->
        <text class="user-motto">第一个小程序</text>
    </view>
  3. 完成之后按 Ctrl + S 保存,效果如下

    image-20200625151349228

  4. 可以通过点击预览按钮在手机端进行测试

    image-20200625151715417

至此,我们已经简单的了解了一个小程序的创建过程,但这还远远不够,还存在着许多的问题。

例如:

  • 小程序的启动入口在哪里?
  • index.wxml、index.wxss、index.js等文件各自的作用,能否进行重命名?
  • WXML、WXSS文件是什么?
  • 以及创建完成之后如何发布给别人使用?

2、小程序开发核心

本部分主要讲解小程序框架及核心内容。小程序框架可让开发者在微信中用尽可能简单、高效的方式开发出具有原生App体验的服务, 这套框架控制着小程序完整的生命周期, 负责页面的加载、渲染、销毁等工作, 它是小程序的核心, 学习小程序前, 我们一定要对这套框架有深入的了解。

本部分主要对小程序目录结构、文件类型进行详细分析, 重点介绍小程序视图层WXML、 MXSS, 逻辑层JS, 这些是小程序开发的核心内容,能对框架有个整体认识即可。

2.1、简介

小程序框架将整个系统划分为视图层和逻辑层

  • 视图层:由框架设计的标签语言WXML和用于描述WXML组件样式的WXSS组成。(类型HTML和CSS的关系)
  • 逻辑层:是一套运行在本地Javascript引擎的Javascript代码

小程序整体开发流程类似前端,但是没有DOM的概念,也没有window、document等对象。

image-20200625153532967

2.2、创建小程序

  1. 打开刚才创建的小程序项目

  2. 打开app.json,修改下面代码

    { 
        "pages":{ 
            /* 指定默认启动页面地址 */
            "mypages/index/index"
        } 
    } 
  3. 打开index.wxml,写入以下代码

    <view bindtap = "countClick">我是index页面,你点击了{{count}}次</view>
  4. 打开index.js文件,写入以下代码

    Page({ 
        data:{ 
            count: 0
        } ,
        countClick:function(){ 
            this.setData({ 
                count: this.data.count + 1
            } );
        } 
    } );
  5. 测试结果,点击文字的时候,数字会开始增加

    image-20200625155633893

  6. 项目结构图:也可以直接修改pages下面的index.js

    image-20200625155737286

2.3、框架主体文件App()

框架主体文件由app.json、app.js、app.wxss构成,这3个文件必须放置在项目根目录下,一个小程序只有一份,它们负责小程序整体的配置:

  • app.json:小程序的公共设置,配置小程序全局设置
  • app.js:小程序逻辑文件,主要用于注册小程序全局实例,编译时会和其他页面逻辑文件打包成一份JavaScript文件
  • app.wxss:小程序公共样式表,对所有页面的布局文件都有效

app.json和app.js是必须存在的,app.wxss不是必须创建的。

2.3.1、app.json

app.json是配置文件,编写时要严格遵循json的格式。

  • pages:设置页面路径,必填项
  • window:设置默认页面的窗口变化
  • tabBar:设置tab菜单栏的表现
  • networkTimeout:设置网络超时时间
  • debug:设置是否开启debug模式,默认关闭

app.json文件内容整体结构(使用逗号分隔,最后一个不需要写)

{ 
    // 页面路径设置
    "pages":[],
    // 默认页面的窗口设置
    "window":{ } ,
    // 底部tab设置
    "tabBar":{ } ,
    // 设置网络请求API的超时时间
    "networkTimeout":{ } ,
    // 是否为debug模式
    "debug":false
} 
  1. pages配置

    pages负责注册小程序页面 , 必须填写, value值为 一个包含页面路径的数组, 用来指定小程序由哪些页面构成, 每一项由页面“路径+文件名”组成, 如下所示

    { 
        "pages":[
            "mypages/index/index", 
            "mypages/page2/mypagefilename", 
            "otherpages/index/index" 
        ]
    } 

    pages数组中页面路径不需要填写文件后缀名, 渲染页面时框架会自动寻找路径 .json,.js, .wxml,.wxss四个文件进行整合 ,路径中的文件名可以和目录名不一致 ,但在项目过程中,为了便于管理 建议文件名和目录名保持一致。pages配置数组第一项代表小程序的初始页面。小程序中增加、删除页面,都需要对pages进行修改,并且保存项目。

  2. window配置

    window负责设置小程序状态栏、导航条、标题、窃口背景色等系统级样式。

    属性 类型 默认值 描述
    navigationBarBackgroundColor HexColor #000000 导航栏背景颜色,如”#000000”(十六进制颜色值)
    navigationBarTextStyle String white 导航栏标题颜色,仅支持 black/white
    navigationBarTitleText String 导航栏标题文字内容
    backgroundColor HexColor #ffffff 窗口的背景色
    backgroundTextStyle String dark 下拉背景字体、loading 图的样式,仅支持 dark/light
    enablePullDownRefresh Boolean false 是否开启下拉刷新,详见页面相关事件处理函数。
    pageOrientation string portrait 屏幕旋转设置,支持 auto(跟随手机)/ portrait(不可选中)/ landscape(横屏)

    image-20200625162639588

  3. tabBar设置

    用于设计程序顶部和底部的菜单栏(主要是list数组)

    属性列表

    属性 类型 默认值 必填 说明
    ext-class string 添加在组件内部结构的class,可用于修改组件内部的样式
    list array<object> Tabbar的项的数组,按照规范,至少要有2个Tabbar项
    current number 0 当前选中的Tabbar项的下标
    bindchange eventhandler Tabbar项发生改成的时候触发此事件,detail为{index, item},index是Tabbar下标,item是对应的Tabbar项的配置
    color String tab文字默认颜色
    selectedColor String tab文字被选中的颜色
    backgroundColor String tab背景颜色
    borderStyle String balck 上边框的颜色,只有black/white
    position String bottom tab在顶部或底部显示,可选bottom、top

    list属性是对象数组,每一项表示一个Tabbar项,其字段含义为

    字段名 类型 默认值 必填 说明
    text string Tabbar项的标题
    iconPath string Tabbar项的icon图片路径,建议使用绝对路径,相对路径要相对于组件所在目录的。
    selectedIconPath string Tabbar项选中时的icon,建议使用绝对路径,相对路径要相对于组件所在目录的。
    badge string 是否显示Tabbar的右上角的Badge
    pagePath String 显示页面的路径

    测试

    "tabBar":{ 
        "color": "#000000",
        "selectedColor": "#ff7f50",
        "backgroundColor": "#ffffff",
        "borderStyle": "black",
        "list": [{ 
            "pagePath": "pages/index/index",
            "text": "想法",
            "iconPath": "images/黑板.png",
            "selectedIconPath": "images/黑板2.png"
        } ,
        { 
          "pagePath": "pages/index/index",
          "text": "测试",
          "iconPath": "images/烧瓶.png",
          "selectedIconPath": "images/奶茶.png"
      } ],
        "position": "bottom"
    } ,

    效果(菜单栏必须是两个以上)

    image-20200625170917506

  4. networkTimeout配置

    • request: 设置wx. request的超时时间,单位毫秒。

    • connectSocket: 设置wx. connectSoc的超时时间,单位毫秒。

    • uploadFile: 设置wx. uploadFile的超时时间,单位毫秒。

    • downoadFile: 设置wx. downloadFi le的超时时间,单位毫秒。

    "networkTimeout":{ 
        "request": 60000,
        "connectSocket": 60000
    } ,
  5. debug配置

    此配置项控制是否开启 debug模式,默认是关闭的。开启 debug模式后,在开发者工具的控制面板,调试信息以info形式输出。其中信息有Page的注册、页面路由、数据更新、事件触发,可以帮助开发者快速定位一些常见问题。

    "debug": true

    测试结果,在开发者工具的控制面板,调试信息以info形式输出。

    image-20200625171753270

以上便是 app.json的5类配置项,这些配置项都是全局的,小程序中除了app.json这种全局配置文件还有页面配置文件,当路由到对应页面时,页面配置文件的配置项将会覆盖全局配置,页面配置文件将在后绩内容中进行详细介绍。

2.3.1、app.js

小程序中逻辑文件分为页面逻辑文件和小程序逻辑文件,app.js便是小程序逻辑文件,在这个文件中,我们可以通过App(函数注册小程序生命周期函数、全局方法和全局属性,已注册的小程序实例可以在其他逻辑层代码中通过getApp()获取。

  1. 注册小程序

    App()函数用于注册一个小程序,参数为一个 object对象,在这个参数对象中我们可以注册自定义方法和属性供全局使用,我们利用App()注册了用户登录信息App()函数必须在 app.js中注册,且不能注册多个,其参数属性如下:

    • onLaunch:生命周期函数,监听小程序初始化当小程序初始化完成时,就会触发onLaunch, onLoaunch事件全局只会触发一次
    • onShow:生命周期函数,监听小程序显示。当小程序启动,或者从后台进入前台显示时都会触发 on Show
    • onHide:生命周期函数,监听小程序隐藏。当小程序从前台进入后台会触发。
    • 其他:开发者可以添加任意的函数或数据到 Object参数中,这些属性会被注册到小程序对象中,其他逻辑文件可以通过 getApp()函数获取已注册的小程序实例。
  2. 小程序生命周期

    • 当启动一个小程序时,首先会先依次触发onLaunch、onShow和方法,然后通过app.json的 page属性注册相应的页面,最后根据默认路径加载首页;
    • 当用户点击左上角关闭,或者按了设备Home按钮离开微信时,小程序并没有直接销毁,而是进入了后台,这两种情况都会触发 onHide方法;
    • 当再次唤醒微信(针对点击Home按钮离开微信或再次从微信中打开小程序时,又会从后台进入前台,这时会触发 onShow方法。
    • 只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正销毁
  3. 注册小程序示例代码

    App({ 
        onLaunch: function (){ 
            //小程序初始化完成时执行
        } ,
        onShow: function (){ 
            //显示小程序时执行
        } ,
        onHide: function (){ 
            //隐藏小程序时执行
        } ,
        globalFunction:'我是全局函数',
        globalData:'我是全局属性'
    } )
  4. 获取小程序实例

    注册小程序后,在其他逻辑文件中,可以通过全局函数 getApp()获取小程序实例,例如:

    var app getApp();
    console.log(app.globalData);

    在App()注册的函数中,我们可以使用this接获取App实例,而不用getApp()方法。通过getApp()获取实例后,可以获取注册的属性、调用注册的方法,但不要私自调用生命周期函数(onLaunch、 onShow、 onHide),这样会打乱项目逻辑,除非你已经对它们很熟悉。

2.3.2、app.wxss

app.wxss是全局样式表,对项目中每个页面都有效,可将一些系统级别的统一样式风格写入这个文件,页面渲染时,框架页中的wxss文件样式会覆盖app.wxss中相同的选择器样式。WSS是小程序基于C拓展的一套样式语言,它实现了CSS大部分规则。小程序框架主体相关的文件app.json、app.js、app.wxss我们已经全部介绍完成,下面为大家介绍框架页面相关的文件。

2.4、框架页面文件Page()

小程序中一个框架页面包含4个文件,同一框架页面的这4个文件必须具有相同的路径与文件名,进入小程序时或页面跳转时,小程序会根据 app json配置的路径找到对应的资源进行渲染。

与框架主体文件相比框架页面文件多了一种页面结构文件,其余3个文件和框架主体文件的功能类同,下面我们一 一讲解每个文件作用。

  1. .js文件: 页面逻辑文件,必要项。

  2. .wxm文件: 页面结构文件,必要项

  3. wxss文件: 页面样式文件

  4. .json文件: 页面配置文件。

2.4.1、页面配置文件 json

页面配置文件和框架配置文件一样,是一个json文件,而不同的是,页面配置文件时非必要存在的,同时页面配置文件的配置项只有window,控制当前页面的窗口表现,window属性和app.json一致。

页面渲染的时候,页面中的window配置会覆盖app.json中的相同配置项。

由于只有window相关属性,所以编写时只需要直接写出属性,不用写window这个键。

{ 
    "navigationBarBackgroundColor": "#000000",
    "navigationBarTextStyle": "black",
    "navigationBarTitleText":"我的页面",
    "backgroundColor": "#efefef",
    "backgroundTextStyle": "light"
} 

2.4.2、页面的逻辑文件 js

(JavaScript)

页面逻辑文件主要功能有:设置初始化数据注册当前页面生命周期函数注册事件处理函数等。

小程序的逻辑层文件是 JavaScript文件,所有的逻辑文件包括 app.js,最终将会打包成一个js文件,在小程序启动时运行,直到小程序销毁。

由于avascript逻辑文件是运行在纯 JavaScript引擎中而并非运行在浏览器中,一些浏览器提供的特有对象,如 document、 window等,在小程序中都无法使用,同理,一些基于 document、 window的框架如: jQuery、 Zepto都不能在小程序中使用,同时我们不能通过操作DOM改变页面,这时需要我们将面向DOM操作的编程思跻转化为数据绑定和事件响应。

1、注册页面Page()

在页面逻辑文件中需要通过Page()函数注册页面,指定页面的初始数据、生命周期函数、事件处理函数等,参数为一个 Object对象,其属性如下:

data:页面的初始数据,数据格式必须是可转成JSON格式的对象类型。当页面第一次渲染时,data会以JSON的形式由逻辑层传至渲染层,渲染层可以通过WXML对数据进行绑定。

onLoad:生命周期函数,页面加载时触发。一个页面只会调用一次,接受页面参数,可以获取wx.navigateTo、wx. redirectTo以及中的 query参数

onShow:生命周期函数,页面显示时触发。每次打开页面都会调用一次。

onReady:生命周期函数,页面初次渲染完成时触发。一个页面生命周期中只会调用一次,代表当前页面已经准备安当,可以和视图层进行交互。一些对界面的设置,操作需要在页面准备妥当后调用,如wx. setNavigationBarTitleonReady,需要在之后设置。

onHide:生命周期函数,页面隐藏时触发。

onUnload:生命周期函数,页面卸载时触发。

onPullDownRefresh:页面相关时间处理函数,用户下拉时触发。使用时需要将app.json配置中 window enablePulDownRefresh属性设置为true。当处理完数据刷新后,可以调用wx. stopPul DownRefresh方法停止当前页面的下拉刷新。

onReachBottom:页面下拉触底事件的处理函数。

其他:开发者可以添加任意的函数或数据到 Object参数中,可以用this访问这些函数和数据。

示例代码

// 获取app实例
var app getApp();
Page({ 
    data:{         
        // 页面初始化数据
        count: 0
    } ,
    onLoad: function(){ 
        // 页面加载时执行
    } ,
    onShow: function (){ 
        // 页面打开时执行
        console.og(app.globalData)
    } ,
    onReady: function(){ 
        // 页面初次渲染完成执行,一个页面只会调用一次
    } ,
    onHide: function (){ 
        // 页面隐藏时执行
    } ,
    onUnload: function(){ 
        // 页面卸载时执行
    } ,
    onPullDownRefresh: function (){ 
        // 下拉刷新时执行
    } ,
    onReachBottom: function (){ 
        // 下拉触底时执行
    } ,
    // 自定义函数,可与渲染层中的组件进行事件绑定
    countclick: function(){ 
        // 触发视图层重新渲染
        this. setData({ 
            count: this.data.count +1
        } );
    } ,
    // 自定义数据
    customData:{ 
       name:'微信'
    } 
} )
2、生命周期
小程序初始化:默认页面入栈,依次触发默认页面onload、onShow、onReady方法。

打开新页面:新页面入栈,依次触发新页面 onload、onShow、onReady方法。

页面重定向:当前页面出栈并卸载,触发当前页面 onUnload方法,新页面入栈,触发新页面 onLoad、 onShow、onReady方法。

页面返回:页面不断出栈并卸载,触发当前弹出页面 onUnload方法,直到返回目标页面,新页面入栈,触发新页面onShow方法。

Tab切换:当前页面出栈但不卸载,仅触发 onside方法,新页面入栈,如果当前页面是新加载的,触发。 onload、onShow、onReady方法,如果当前页面已加载过,仅触发 onShow方法。

程序从前台到后台:触发当前页面onHide方法,触发App onHide方法。

程序从后台到前台:触发小程序onShow方法,触发页面onShow方法。

小结:

  • 在页面的生命周期中只会触发onShow和onLoad方法
  • 只有加载和卸载时才会触发onLoad、onReady和onUnload方法
  • 而触发页面卸载只有页面返回和页面重定向两种操作
3、获取当前页面栈

getcurrentPages()函数便是用于获取当前页面栈的实例,页面栈以数组形式按栈顺序给出,第一个元素为首页,最后一个元素为当前页面不要尝试修改页面栈,这会导致路由以及页面状态错误

/*获取页面栈*/
var pages getcurrentpages();

/*获取当前页面对象*/
var currentPage = pages[pages.length -1]
4、事件处理函数

页面对象中注册的函数可以和视图层中的组件进行绑定,当达到触发条件时,就会执行Page中定义的相应事件,这类自定义函数统称为事件处理函数。

小程序中组件的事件分为通用事件和特殊事件

  1. 添加事件

    bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数

    <view bindtap = "myevent">点击执行逻辑层事件</view>
  2. 事件处理方法

    Page({ 
        // 与上面定义的bintap的值对应
        myevent: function(){ 
            console.1og('点击了view')
        } 
    } )
5、触发视图层渲染
  • 页面首次加载时,框架会结合初始化数据渲染页面,在逻辑层中则需主动调用 Page. prototype. setData()方法,而不能直接修改Page的data值,这样不仅无法触发视图层渲染,还会造成数据不一致。
  • 当 Page. prototype. setData()被调用时,会将数据从逻辑层发送到视图层触发视图层重绘,同时会修改Page的data值。 setData()接受一个 Object对象参数,方法会自动将 this.data中的key对应的值变成 Object参数中key对应的值。
  • 当 Object参数key对应的值和 this.data中key对应的值一致时,将不会触发视图层渲染。在项目中我们一定要保证视图层和逻辑层的数据一致。
  1. 视图层 index.wxml
<view>{{text}}</view>
<button bindtap="changeText">修改普通数据</button>
<view>{{object.subObject.objectText}}</view>
<button bindtap="changeObjectText">修改对象数据</button>
<view>{{array[0].arrayText}}</view>
<button bindtap="changeArrayText">修改数组数据</button>
<view>{{newFile.newFileText}}</view>
<button bindtap="addNewData">添加新字段</button>
  1. 逻辑控制层 index.js
Page({ 
    data:{ 
        text: 'normal data',
        object:{ 
            subObject:{ 
                objectText: 'object data'
            } 
        } ,
        array:[
            { arrayText: 'array data'} 
        ]
    } ,
    changeText: function(){ 
        this.setData({ 
            // 普通索引
            text: 'new normal data'
        } );
    } ,
    changeObjectText: function (){ 
        this.setData({ 
            // 按路径索引
            'object.subObject.objectText': 'new object data'
        } );
    } ,
    changeArrayText:function (){ 
        this.setData({ 
            // 按路径索引
            'array[0].arrayText': 'new array data'
        } );
    } ,
    addNewData:function(){ 
        this.setData({ 
            /*修改一个已绑定,但未在data中定义的数据*/
            'newFile.newFileText': 'add new data'
        } );
    } 
} )
  1. 测试结果

    image-20200625192053617

6、页面生命周期

image-20200625183304075

线程启动后视图层和逻辑层相互监听

  • 当逻辑层线程触发onLoad、onShow方法后会把初始数据data传送给视图层线程,视图层完成第一次渲染后触发逻辑层 onReady方法,代表页面已经准备妥当,之后我们便可通过setData方法主动触发视图层渲染。

  • 当页面被调往后台时,触发 onHide方法,这时逻辑层线程并没有销毁,我们仍然可以通过代码控制视图层渲染,只是可能不会在界面上表现出来。

  • 当页面从后台回到前台时,触发 onshow方法,最后当页面销毁时,触发 onUnload方法。

  • 整体来看 onload、 onReady和 onUnload方法在生命周期中只会调用一次,生命周期内显示、隐藏页面都是触发 onshow和 onside方法。

  • 在路由方式中,只有页面重定向和页面返回会结束当前页面生命周期,当进入一个已加载的页面时只会触发 onshow方法,不会触发 onload和onReady方法。

2.4.3、页面结构文件WXML

WXML(WeiXin Markup Language) 是框架设计的一套标记语言,用于渲染界面,WXML的渲染原理和React Native思路一致,通过一套标记语言,在不同平台被解析为不同端的渲染文件。

image-20200625204931096

  • WXML语言最终会转译为宿主端对应的语言,所以WXML中所使用的标签一定是小程序定义的标签,不能使用自定义标签,这样才能保证页面能被正确转译。

  • 使用微信开发者工具开发时,在WXML中编写一些HTML标签或自定义标签仍然会被正常解析,这会给开发者造成一种小程序能直接支持HTM标签的误解。这是因为微信开发者工具内核是浏览器内核,同时小程序框架并没对WXML中的标签和wxss中的内容进行强验证,所以HTML和CS能直接被解析,但这种不合法的wxML在手机端微信中是不能正常显示的。开发过程中我们一定要拿真机进行测试,保证程序能正常运行。

  • WXML具有数据绑定、列表渲染、亲件渲染、模板、事件等能力。


1、数据绑定 data
  • 小程序中页面渲染时,框架会将WXML文件同对应Page的data进行绑定,在页面中我们可以直接使用data中的属性。小程序的数据绑定使用 Mustache语法(双大括号)将变量或简单的运算规则包起来,主要有以下几种渲染方式。

  • 使用`{{}}`可以获取data中的值。 - **简单绑定** 简单绑定是指我们使用双大括号将变量包起来,在模板中直接作为字符串输出使用,可作用于内容、组件属性、控制属性、关键字等输出,期中关键字输出是指将JavaScript中的关键字按其真值输出。 ```xml {{content}}

    {{border}}

    作为属性渲染

    
    ```js
    Page({ 
      data:{ 
            border:'solid lpx #000',
            id: 1,
            content: '内容',
            showContent: false
        } 
    } );
  • 运算

    在`{{}}`内可以做一些简单的运算,支持的运算有三元运算、算数运算、逻辑判断、字符串运算,这些运算均符合Javascript运算规则。 ```xml {{showContent ? '显示文本': '不显示文本'}}

    {{num1 + num2}} + 1 + {{num3}} = ?

    {{"name:" + name}}

    {{num3 > 0}}

    {{myObject.age}}:{{myArray[1]}}

    
    ```js
    Page({ 
        data:{ 
            showContent: false,
            num1: 1,
            num2: 2,
            num3: 3,
            name: 'weixin',
            myObject:{ 
                   age: 12
               } ,
            myArray: ['arr1', 'arr2']
        } 
    } );

    效果展示

    image-20200706154603867

  • 组合

    data中的数据可以在模板再次组合成新的数据结构,这种组合常常在数组或对象中使用。

    <view>{{[myValue, 2, 3, 'stringtype']}}</view>
    Page({ 
        data: { 
            myValue: 0
        } 
    } );

    最终页面组合成的对象为[0, 2, 3, ‘stringtype’]。

    对象组合有3种组合方式,这里我们以数据注入模板为例。

    • 直接将数据作为value值进行组合

      <template name="testTemp">
          <view>name = {{name}}</view>
        <view>age = {{age}}</view>
      </template>
      <template is="testTemp" data="{{name:myValue1, age:myValue2}}"></template>
      // 运算
      Page({ 
          data:{ 
            myValue1: 'value1',
              myValue2: 'value2'
        } 
      } );
      **效果展示**
    
    ![image-20200706155645054](.\小程序开发.assets\image-20200706155645054.png)
    
    - **通过"..."将第一个对象展开,把key-value值拷贝到新的结构中**
    
      ```xml
      <template name="testTemp">
          <view>key1 = {{key1}}</view>
          <view>key2 = {{key2}}</view>
          <view>key3 = {{key3}}</view>
          <view>key4 = {{key4}}</view>
          <view>key5 = {{key5}}</view>
          <view>key6 = {{key6}}</view>
      </template>
      <template is = "testTemp"
          data = "{{...myObject1, key5: 5, ...myObject2, key6: 6}}"></template>

    ```js
  Page({ 
        data:{ 
          myObject1:{ 
                key1: 1,
                key2: 2
            } ,
            myObject2:{ 
              key3: 3,
                key4: 4
            } 
        } 
    } );

效果展示

image-20200706155357767

  • 如果对象key和value相同,可以只写key值

    <template is = "testTemp"
        data = "{{key1, key2}}"></template>
    Page({ 
        data:{ 
            key1: 1,
            key2: 2
        } 
    } );

    这种写法最后组合成的对象是{key1: 1, key2: 2}

    注意:当一个组合中有相同的属性名时,后面的属性将会覆盖前面的属性。

2、条件和遍历
  • wx: if

    除了简单的数据绑定,我们常常会使用逻辑分支,这时候可以使用wx: if"{{判断条件}}"来进行条件渲染,当条件成立时渲染该代码块

    <view wx:if="{{showContent}}">内容</view>
    Page({ 
        data:{ 
            showContent: false
        } 
    } );

    示例中view代码块将不会渲染,只有当showContent的值为true时才渲染。和普通的编程语言一样,WXML也支持wx: elif 和wx: else

  • wx: elif、wx: else

    <view wx:if="{{false}}">1</view>
    <view wx:elif="{{false}}">2</view>
    <view wx:else>3</view>

    示例中页面只渲染最后一个。wx: elif、wx: else必须和wx: if配合使用,否则会导致页面解析出错。

  • block wx:if

    wx: if是一个控制属性,可以添置在任何组件标签上,但如果我们需要包装多个组件,又不想影响布局,这时就需要使用 <block/>标签将需要包装的组件放置在里面,通过wx: if作判断。

    <block/>不是一个组件,仅仅是一个包装元素。

    <block wx:if = "{{true}}">
        <view>view组件</view>
        <image/>
    </block>
  • wx: if 与 hidden

    除了wx:if 组件,也可以通过 hidden属性控制组件是否显示,开发者难免有疑问,这两种方式该怎样取舍,这里我们整理了两种方式的区别:

    • wx:if :控制是否渲染条件块内的模板,当其条件值切换时,会触发局部渲染以确保条件块在切换时销毁或重新渲染。wx:if是惰性的,如果在初始渲染条件为 false时,框架将什么也不做,在条件第一次为真时才局部渲染。
    • hidden :控制组件是否显示,组件始终会被渲染,只是简单控制显示与隐藏,并不会触发重新渲染和销毁。

    综合两个渲染流程可以看出,由于wx:if会触发框架局部渲染过程,在频繁切换状态的场景中,会产生更大的消耗,这时尽量使用 hidden;在运行时条件变动不大的场景中我们使用wx:if,这样能保证页面有更高效的渲染,而不用把所有组件都渲染出来。

3、列表渲染
  • wx: for

    组件的wx: for控制属性用于遍历数组,重复渲染该组件,遍历过程中当前项的下标变量名默认为index,数组当前变量名默认为item

    <view wx:for="{{myArray}}">
        {{index}}:{{item}}
    </view>
    Page({ 
        data:{ 
            myArray: ['value1', 'value2']
        } 
    } );

    通过遍历myArray,页面渲染了两个<view/>

    结果如下

    image-20200625230121128

  • wx: for-index 和 wx:for-item

    index、item变量名可以通过wx: for-index、wx: for-item属性修改

    <view wx:for="{{myArray}}" wx:for-index="myIndex" wx:for-item="myItem">
        {{myIndex}}:{{myItem.name}}
    </view>
    Page({ 
        data:{ 
            myArray:[
                { name:'value1'} ,
                { name:'value2'} 
            ]
        } 
    } );

    效果和上例一致

  • wx:for嵌套使用

    普通遍历中我们没必要修改index、item变量名,而在使用wx:for嵌套时,就有必要设置变量名,避免变量名冲突。(当然也可以不用重命名)

    <view wx:for="{{myArray}}" wx:for-index="myIndex" wx:for-item="myItem">
        <block wx:for="{{myItem}}" wx:for-index="subIndex" wx:for-item="subItem">
            {{subItem}}
        </block>
        <!-- 简写,效果相同 -->
        <!--
      <view wx:for="{{myArray}}" >
          <block wx:for="{{item}}">
        {{item}}
          </block>
      </view>
      -->
    </view>
    Page({ 
        data:{ 
            myArray:[
                [1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]
            ]
        } 
    } );

    输出结果:在本示例中,我们使用了<block/>标签,以渲染一个包含多个节点的结构快。

    image-20200625232230296

4、模板

在项目过程中,常常会遇到某些相同的结构在不同的地方重复出现,这时可以将相同的布局代码片段放置到一个模块中,在不同的地方传入对应的数据进行渲染,这样能避免重复开发,提高开发效率

  • 定义模板

    <template/>内定义代码片段,设置<template/>的name属性,指定模板名称即可。

    <template name="myTemplate">
        <view>内容</view>
        <view>{{content}}</view>
    </template>
  • 使用模板

    使用模板时,设置is属性指向需要使用的模板,设置data属性,将模板所需的变量传入。模板拥有自己的作用域,只能使用data属性传入的数据,而不是直接使用Page中的data数据,渲染时,<template/>标签将被模板中的代码块完全替代

    <template name="myTemplate">
        <view>内容</view>
        <view>{{content}}</view>
        <view>{{name}}</view>
        <view>{{myObj.key1}}</view>
        <view>{{key2}}</view>
    </template>
    <template is="myTemplate" data="{{content:'内容', name, myObj, ...myObj2}}"/>
    Page({ 
        data:{ 
            name: 'myTemplate',
            myObj:{ 
                key1: 'value1'
            } ,
            myObj2:{ 
                key2:'value2'
            } 
        } 
    } );

    测试结果:模板只能使用自己的data数据,注意属性和值之间是冒号分开

    image-20200626113841720

  • 嵌套使用模板:使用is进行引用模板

    <template name="bTemplate">
        <view>b template content</view>
    </template>
    <template name="aTemplate">
        <view>a template content</view>
        <template is="bTemplate"/>
    </template>
    <template is="aTemplate"/>
5、事件

WXML中的事件系统和HTML中DOM事件系统极其相似,也是通过在组件上设置“bind(或 catch)+事件名”属性进行事件绑定,当触发事件时,框架会调用逻辑层中对应的事件处理函数,并将当前状态通过参数传递给事件处理函数,由于小程序中没有DOM节点概念,所以事件只能通过XML绑定,不能通过逻辑层动态绑定。官方对WXML事件的定义如下:

1. 事件是视图层到逻辑层的通讯方式。
2. 事件可以将用户的行为反馈到逻辑层进行处理。
3. 事件可以绑定在组件上,当触发事件时,就会执行逻辑层中对应的事件处理函数。
4. 事件对象可以携带额外信息,如id、 dataset、 touches

  • 事件分类

    • 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。例如:bindtap
    • 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。例如:catchtap

    WXML冒泡事件如下:

    • touchstart:手指触摸动作开始
    • touchmove:手指触摸后移动
    • touchcancel:手指触摸动作被打断,如来电提示、弹窗
    • touchend:手指触摸动作结束
    • tap:手指触摸后马上离开
    • longtap:手指触摸后,超过350ms在离开

    对于冒泡事件每个组件都是默认支持的,除了上述事件之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如<form/>的submit事件,<scroll-view/>的scroll事件。

  • 事件绑定

    事件绑定的写法和组件的属性一样,以key、value形式组织。

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

    • key:以bind或catch开头,然后跟上事件类型,字母均小写,如bindtap、catchtouchstart。
    • value:时间函数名,对应Page中定义的同名函数。找不到同名函数会导致报错。
    <view bindtap="tap1">
        view1
        <view catchtap="tap2">
            view2
            <view bindtap="tap3">
                view3
            </view>
        </view>
    </view>

    点击view3会触发view2,而不会触发view1;点击view2也不会触发view1。

6、事件对象

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

<view bindtap="myEvent">view</view>
Page({ 
  myEven:function(e){ 
      console.log(e);
  } 
} );

image-20200626120743563

事件对象属性基本上可分为三类:

  • BaseEvent
  • CustomEvent
  • TouchEvent。
  1. BaseEvent为基础事件对象属性,包括:
    • type:事件类型
      • timeStamp:事件生成时的时间戳,页面打开到触发所经历过的毫秒数
      • target:出发事件原组件(即冒泡开始的组件)的相关属性集合,如下:
        • id:事件源组件的id
        • tagName:事件源组件的类型
        • dataset:事件源组件上由data-开头的自定义属性组成的集合
        • currentTarget:事件绑定的当前组件的相关属性集合,属性如下:
          • id:当前组件id
          • tagName:当前组件类型
          • dataset:当前组件上由data-开头的自定义属性组成的集合

<canvas/>中的触摸事件不可冒泡,所以没有currentTarget。dataset是组件的自定义数据,以data- 开头,由”-“ 连接,大写会被转为小写,两个单词以上最终被转为驼峰命名形式

<view bindtap="myevent" data-my-name="weixin" data-myAge="12">
    dataset示例
</view>
Page({ 
    myevent:function(e){ 
        console.log(e.currentTarget.dataset);
    } 
} );

测试结果输出自定义属性值

image-20200626122153987

  1. CustomEvnet为自定义事件对象(继承BaseEvent)

    • detail:额外信息,通常传递组件特殊信息。
  2. TouchEvent为触摸事件对象(继承BaseEvnet)

    • touches:触摸事件,当前停留在屏幕中的触摸点信息的数组。
    • changedTouches:触摸事件,当前变化的触摸点信息的数组,从无变有、从有变无、位置变化。

    支持多点触摸,所以touches和changedTouches都是数组格式,每个元素为一个Touch对象(canvas触摸事件中为CanvasTouch对象)

Touch对象相关属性如下:

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

CanvasTouch对象相关属性如下:

  • identifier:触摸点的标识符
  • x,y:距离Canvas左上角的距离,Canvas的左上角为原点

7、引用

一个WXML可以通过 import或include或引入其他WXML文件,两种方式都能引入WXML文件,区别在于

import引入WXML文件后只接受模板的定义,忽略模板定义之外的所有内容,而且使用过程中有作用域的概念。

include则是引入文件中除<template/>以外的代码直接拷贝到<include/>位置,与 import相反,。

整体来说,import是引入模板,include是引入组件。

  1. import(只引用了模板)

    <import/>的src属性是需要被引入文件的相对地址,<import/>引入会忽略引入文件中<tmplate/>定义以外的内容。

    • a.wxml
    <import src="b.wxml"/>
    <!-- 使用b.wxml中定义的模板 -->
    <template is="bTemplate" data=""/>
    • b.wxml
    <view>内容</view>
    <template name="bTemplate">
        <view>b template content</view>
    </template>
    <template is="bTemplate"/>
  2. include

    include引入会将模板定义标签之外的内容直接赋值替换<include/>

    • a.wxml
    <include src="b.wxml"/>
    <!-- 不能调用该模板 -->
    <template is="bTemplate"/>
    <!-- 但会显示出b.wxml中<view>的值 -->
    • b.wxml
    <!-- 会在a.wxml中显示 -->
    <view>内容</view>
    <template name="bTemplate">
        <view>b template content</view>
    </template>
    <!-- 会在a.wxml中显示 -->
    <template is="bTemplate"/>

    测试效果:可以显示出b.wxml中的所有内容。

    image-20200626131742354

8、初始化运行的事件
// 初始化运行
onLoad: function (options) { 
    this.setData({ 
        times:this.data.times1
    } )
} ,

2.4.4、页面样式文件WXSS

WXSS( WeiXin Style Sheets)是基于CSS拓展的样式语言,用于描述WXML的组件样式,具有CSS的大部分特性,在CSS基础上WXSS拓展了尺寸单位、样式导入特性,对CSS选择器属性上做了部分兼容。

本部分主要讲述WXSS和CSS的不同点,后续布局章节会讲解CSS盒子模型布局相关属性,不过在开发过程中我们一定要开启开发者工具中“开启上传代码时样式文件自动补全功能,这样小程序会自动补全其余一些样式的兼容性写法,保证在不同终端达到统一视觉效果。

  1. 尺寸单位

    • rpx

      在渲染过程中rpx会按比例转化为px,WXSS规定屏幕宽度为750rpx。如手机屏幕宽度为375px,即750rpx = 375px,那么在该手机中1rpx = 0.5px

    • rem

      与rpx一样,WXSS规定屏幕宽度为20rem。

    设备 rpx换算px (屏幕宽度/750) px换算rpx (750/屏幕宽度)
    iPhone5 1rpx = 0.42px 1px = 2.34rpx
    iPhone6 1rpx = 0.5px 1px = 2rpx
    iPhone6 Plus 1rpx = 0.552px 1px = 1.81rpx

    在设计界面时,要实现尺寸自适应,可以用iPhone6作为视觉标准,进行设计。

    注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。

  2. 选择器

    选择器 样例 样例描述
    .class .intro 选择所有拥有 class=”intro” 的组件
    #id #firstname 选择拥有 id=”firstname” 的组件
    element view 选择所有 view 组件
    element, element view, checkbox 选择所有文档的 view 组件和所有的 checkbox 组件
    ::after view::after 在 view 组件后边插入内容
    ::before view::before 在 view 组件前边插入内容

    示例

    /*选择所有class含myClass有的组件,并设置边框*/
    .myClass { border: solid 1px #000;} 
    
    /*选择所有view组件且class含 myClass有的组件,并设置边框*/
    view.myClass { border: solid 1px #000;} 
    
    /*选择所有view组件中子节点class含有myclas子节点含有的组件,并设置边框*/
    view .myclass{ border: solid 1px #000;} 
    
    /*选所有 class含有myContent组件中所有checkbox组件和radiobox组件,并设置它们的边框*/
    .myContent checkbox,
    .myContent radiobox { boder: solid 1px #000;} 
    
    /*选择所有view组件且class含有myClass且含有的组件,在其后面插入新内容,内容为new content*/
    view. myclass: after { content: 'new content'} 
  3. 内联样式

    跟HTML一样,可以通过style、class属性控制样式。

    <!-- 通过style动态设置样式 -->
    <view style="border:solid 1px #000; background-color:{{color}}"></view>
    
    <!-- 通过class选择器设置样式 -->
    <view class="myClassName1 myClassName"></view>
  4. 样式导入

    为了便于管理,会将WXSS按职能拆分为多个文件,这是需要使用@import语句导入其他WXSS文件,用 “ ; “表示语句结束

    .common-view{ border:solid 1px #000;} 
    @import "common.wxss";
    .page-container{ padding:10px} 

==至此,小程序框架页面相关的4个文件已经介绍完成了==


2.5、模块化

模块化主要解决JavaScript中命名冲突和文件依赖这两个问题

2.5.1、模块化简介

起初JavaScript将代码统一放在一个文件内,但随着代码量的增多出现了很多问题,为了避免全局冲突等问题,决定参考Java的方式,引入命名空间和闭包来解决变量冲突问题。

  • 起初代码

    var name = 'weixin',
        age = 12;
    function getName(){ 
        // 实现代码
    } 
    function getAge(){ 
        // 实现代码
    } 
  • 优化后

    (function(){ 
        // 定义全局命名空间
        myProject = myProject||{ } ;
        myProject.user = { } ;
        myProject.user.name = 'weixin';
        // 闭包内变量,外部不能访问
        var age = 12;
        myProject.user.getName = function(){ 
            // 实现代码
        } 
        myProject.user.getAge = function(){ 
            // 实现代码
        } 
    } )();

    此时可以通过myProject.user获取name,和使用getName、getAge方法,通过命名空间可以缓解大部分冲突,而user这个命名空间被我使用之后,别人就不能使用该空间,并且每次都需要记住一串命名空间,所以该方法依旧存在弊端。

    于是,模块化才正式诞生:

    • 模块化是一段javas代码,具有统一的基本书写格式
    • 模块之间通过基本交互规则,能彼此引用,协同工作

    目前模块化的规范不统一,大致可分为CommonJS 和 ES6两种规范。

2.5.2、文件作用域

小程序中一个JavaScript文件就是一个模块,在这个文件中声明的变量和函数只在该文件中有效,不同文件中的相同变量名和函数名是不会相互影响的。

模块可以调用一些全局的方法。

  • a.js中
App({ 
   // 在App中定义全局属性
   myGlobalData:{ 
       name: 'weixin'
   } 
} );
// 只能在该文件中使用的属性,并为其赋值
var myPrivateData = 'value1';
// 调用全局变量
var appData = getApp();
appData.myGlobalData.name += 'app';
  • b.js中
// 不会和a.js中同名变量冲突
var myPrivateData = 'value2';
// 同样可以调用全局变量,并为其赋值
var appData = getApp();
appData.myGlobalData.name += 'app';

2.5.3、模块的使用

JavaScript写完接口之后,需要将接口进行暴露。模块接口的暴露和引入十分简单:

  • 通过exports暴露接口
  • 通过require(path)引入依赖,path是需要引入的模块文件的相对路径

示例代码

  • a.js
var privateData = 'weixin';
function run(who){ 
    console.log(who + 'run');
} 
// 暴露接口
module.exports.run = run;
/**
    也可以写成
    module.exports = { 
        run:run
    } ;
*/
  • b.js
// 获取暴露的接口
var otherMod = require('a.js');
Page({ 
    onShow:function(){ 
        // 调用接口
        otherMod.run('somebody');
    } 
} );

2.5.4、其他

JavaScript运行环境

微信小程序逻辑代码运行在三端:ios、Android和用于调试的开发者工具,这三端是各自不同的三个解析引擎:

  • ios:小程序的JavaScript代码运行在JavaScriptCore中。
  • Android:小程序的JavaScript代码是通过X5内核来解析。
  • 开发者工具:运行在nwjs(chrome内核)中。

虽然环境相似,但一些语法、特性的支持还有一些区别。

2.6、小结

小程序框架是小程序开发的核心,小程序这种基于数据的编码方式和前端基于DOM的编码方式有很大不同,要着重了解熟悉框架,了解小程序运行原理之后,后续学习组件和API将会非常简单。

3、布局

WXSS实现了CSS布局相关的大部分规范,但在一些细节上有差异,这部分主要讲述CSS布局相关的一些基本知识,包裹盒子模型、浮动定位、绝对定位以及Flex布局。

全局属性:

Page{ 
  background: orange;
} 

3.1、基本知识

3.1.1、盒子模型

盒子模型是CSS布局的基础,每个元素框中心都有一个内容区(content),周围有内边距(padding)、边框(border)和外边框(margin),这些默认宽度为0。

image-20200626182801063

3.1.2、块级元素

元素按照显示方式主要可以分为块级元素和行内元素,元素的显示方式是由display属性控制,块级元素会默认占一行高度,一般一行内只有一个块级元素(浮动后除外),当再添加新的块级元素,新元素会自动换行显示。

一些元素默认就是块级元素,如<view/>组件,而一些是默认行内元素,可以通过修改元素display属性为block,将一个元素强制设置为块级元素。

块级元素的特点:

  • 总是再新行上开始
  • 宽度默认刚好等于父级元素内容区宽度,除非设定一个新宽度,这里需要注意,当设置块级元素宽度为100%时,如果当前块级元素存在padding、margin会导致块级元素溢出父元素
  • 盒子模型高度默认由内容决定
  • 盒子模型中高度、宽度及外边距和内边距都可控制
  • 可以容纳行内元素和其他块级元素

3.1.3、行内元素

除了块级元素,最常见的就是行内元素,通过设置display属性为inline可以将一个元素设置为行内元素。

例如<text/>就是一个行内组件。

行内元素的特点:

  • 和其他非块级元素都在一行上
  • 盒子模型中高度、宽度、上下margin、上下padding设置均为无效,只能设置左右margin和左右padding
  • 宽度就是文字或图片的宽度,不可改变
  • 行内元素宽度、高度都不能直接设置
  • 行内元素只能容纳文本或其他行内元素,再行内元素中放置块级元素会引起混乱
<!-- 通过设置将<view>变为行内元素 -->
<view style="display:inline">

3.1.4、行内块元素

行内块元素就是块级元素和行内元素的混合物,当display属性为inline-block时,元素就被设置为一个行内块元素,可以设置宽、高、内边距和外边距。

<view style="display:inline-block">

3.2、浮动和定位

定位的基本思想很简单,它允许定义元素框相对于其正常位置应该出现在哪,或者相对于父元素、另一个元素甚至浏览器窗口本身的位置。

浮动和定位时常用的布局方案,WXSS也支持Flex布局方案。

3.2.1、浮动

浮动不完全是定位,同时它也不是正常流布局,通过设置float属性,浮动的框可以向左或者向右移动,直到其外边缘碰到包含框或另一个浮动框的边框为止。

设置float属性,left为左浮动。

<view>文本文本文本文本文本文本文本文本</view>
<view style="display:block; float:left; border:solid 1px; margin:20px">浮动框</view>
文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本文本

测试效果

image-20200626190447825

3.2.1、清除浮动

在父级元素中使用浮动的时候,浮动元素不会出现在父级元素边框内,这时候就需要清除浮动影响:style=”clear:left;”(清除)。

当设置元素clear时,可以确保当前元素的左边、右边或左右两边同时不能出现浮动元素。

<!-- 父元素会包含清楚浮动元素 -->
<view style="border:solid 1px;">
    <view>其他元素</view>
    <view style="float:left;">浮动框</view>
    <!-- 设置当前元素左边不能出现浮动元素 -->
    <view style="clear:left;">清除浮动元素</view>
</view>

<!-- 利用伪属性在后面插入一个元素清除浮动 -->
<view style="border:solid 1px; margin-top:10px;" class="clearfix">
    <view>其他元素</view>
    <view style="float:left;">浮动框</view>
</view>

<!-- 不清除浮动的效果 -->
<view style="border:solid 1px; margin-top:10px;">
    <view>其他元素</view>
    <view style="float:left;">浮动框</view>
    <!-- 在浮动后面添加元素可以清除浮动,但不会换行 -->
    <view>不清除浮动</view>
</view>

<!-- 完全不清除浮动的效果 -->
<view style="border:solid 1px; margin-top:10px;">
    <view>其他元素</view>
    <view style="float:left;">浮动框</view>
</view>
  • 利用伪元素的时候需要在 .wxss中加上该语句
.clearfix:after { 
  display: block;
  height: 0;
  clear: both;
  content: ''
} 

测试效果

image-20200626194710242


3.2.2、定位

元素的定位由position属性控制,position有4种不同类型的定位,会影响元素框生成的方法。

  • static:元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中,static是position的默认值。
  • relative:元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
  • absolution:元素框从文档流中完全删除,并相对其包含块定位,包含块可能是文档中的另一个元素或者是初始包含块。
  • fixed:元素框的变现类似于将position设置为absolute,不过其包含块是视窗本身。

3.3、Flex布局

浮动和定位是基于盒子模型的传统布局解决方案,它在处理一些特殊布局时非常不方便,比如垂直居中。

2009年W3C提出了Flex布局,可以简单快速地完成各种伸缩性的设计。

Flex是Flexible Box的缩写,即为弹性盒子布局。

3.3.1、基本概念

Flex布局主要由容器和项目构成,采用Flex布局的元素,称为Flex容器(flexcontainer),它的所有直接子元素自动成为容器成员,称为Flex项目(flexitem)。

可以设置display:flex或 display: inline-flex将任何一个元素指定为flex布局

image-20200626201701397


3.3.2、容器属性

容器支持的属性有:

  • display: 通过设置 display属性指定元素是否为Flex布局
  • flex -direction:指定主轴方向,决定了项目的排列方式。
  • fex-wrap:排列换行设置。
  • fex-flow: flex-direction和flex-wrap的简写形式
  • justify-content:定义项目在主轴上的对齐方式。
  • align-items:定义项目在交叉轴上的对齐方式。
  • align-content:定义多根轴线的对齐方式,如果只有一根轴线,该属性不起作用。
1、display

用来指定该元素是否为Flex布局

.mybox{ display:flex | inline-flex;} 
  • flex:用于产生块级Flex布局
  • inline-flex:用于产生行内Flex布局
2、flex-direction

用于指定主轴的方向,即项目排列的方向

.mybox{ flex-direction:row | row-reverse | column | column-reverser;} 
  • row:主轴为水平方向
  • row-reverse:起点在右端的水平排列
  • column:在上沿的垂直方向
  • column-reverse:在下沿的垂直方向

image-20200627230139540

3、flex-wrap

当一条轴排列不下时使用

.mybox{ flex-wrap:nowrap | wrap | wrap-reverse} 
  • nowrap:不换行,默认值
  • wrap:换行,第一行在上方
  • wrap-reverse:换行,第一行在下方

image-20200627230436612

4、flex-flow

是flex-direction和flex-wrap的简写形式,默认值为row nowrap

.mybox{ flex-flow:<flex-direction> || <flex-wrap>} 
.mybox{ flex-flow:row-reverse wrap;} 
.mybox{ flex-flow:wrap row-reverse;}  /*与上一句相同*/
.mybox{ flex-flow:row-reverse;} 
.mybox{ flex-flow:wrap;} 
5、justify-content

定义项目在主轴的对齐方式

.mybox{ justify-content:flex-start | flex-end | center | space-between | space-around;} 
  • flex-start:左对齐,默认值
  • flex-end:右对齐
  • center:居中
  • space-between:两端对齐,项目之间的间隔都相等
  • space-around:每个项目两侧的间隔相等

image-20200627231741914

6、align-items

align-items指定项目在交叉轴上如何对齐

.mybox{ align-items:flex-start | flex-end | center | baseline | stretch;} 
  • flex-start:交叉轴的起点对齐
  • flex-end:交叉轴的终点对齐
  • center:交叉轴的中线对齐
  • baseline:项目根据它们第一行文字的基线对齐
  • stretch:在交叉轴方向拉伸填充整个容器,默认值

image-20200627232341708

7、align-content

定义项目多根轴线在交叉轴上的对齐方式,如果只有一根轴线则不起作用

.mybox{ align-content:flex-start | flex-end | center | space-between | space-around | stretch;} 
  • flex-start:与交叉轴的起点对齐
  • flex-end:与交叉轴的终点对齐
  • center:与交叉轴的中点对齐
  • space-between:与交叉轴两端对齐,间距平均
  • space-around:每根两侧的间距相等
  • stretch:轴线占满整个交叉轴,默认值

image-20200627232819069

3.3.3、项目属性

项目支持的属性有6个:

  • order:定义项目的排序顺序
  • flex-grow:定义项目的放大比例
  • flex-shrink:定义项目的缩小比例
  • flex-basis:分配多余空间之前,项目占据的主轴空间
  • flex:flex-grow、flex-shrink和flex-basis的简写
  • align-sele:用来设置单独的伸缩项目在交叉轴上的对齐方式
1、order

order属性定义项目的排列顺序,数值越小,排列越靠前,默认为0

.myitem{ order:<integer>;} 

image-20200627232819069

order示例

image-20200627232844528

2、flex-grow

定义项目的放大比例,默认为0,如果存在剩余空间也不放大,如果都为1的时候,则它们将等分剩余空间。

.myitem{ flex-grow:<number>;} 

image-20200627233113953

3、flex-shrink

flex-shrink定义了项目的缩小比例,默认为1,如果空间不足,该项目将缩小

.myitem{ flex:shrink:<number>;} 

image-20200627233242611

image-20200627233512585

4、flex-basis

定义伸缩项目的基准值,剩余的空间将按比例进行缩放,默认为auto

.myitem{ flex-basis:<length> | auto;} 
5、flex

是flex-grow、flex-shrink和flex-basis的简写,默认值为01autto

.myitem{ none | [<'flex-grow'> <'flex-shrink'> ? || <'flex-basis>']} 

该属性有两个快捷键:auto(11auto)和none(00aotu)

/* 上写两句相同 */
.myitem{ flex: 1 1 autp} 
.myitem{ flex: auto;} 

.myitem{ flex: 0 0 auto} 
.myitem{ flex: none;} 

.myitem{ flex: 1 auto} 
.myitem{ flex: 1 1;} 
6、align-self

设置单独的伸缩项目在交叉轴上的对齐方式

.myitem{ align-self:auto | flex-start | flex-end | center | baseline | stretch;} 
  • auto:没有父元素等同于stretch
  • flex-start:交叉轴的起点对齐
  • flex-end:交叉轴的终点对齐
  • center:交叉轴的中线对齐
  • baseline:项目根据第一行文字的基线对齐
  • stretch:项目将在交叉轴方向拉伸填充整个容器

image-20200627235234125

==好了,关于容器的内容就到这里了~==

4、组件

该部分内容建议边学边参考官方文档组件属性介绍

小程序定义了各种各样的组件,它们在WXML中起着各不相同的作用。与HTML元素一样,一个组件是指从组件开始标签到结束标签的所有代码,由于组件可能会被转译为不同端对应的代码,所以在页面创建过程中,不能使用小程序组件标签以外的标签

在本部分介绍小程序相关组件,包括视图容器、基础容器、表单组件、导航媒体组件、地图、画布、客服会话8大类。

4.1、组件的定义及属性

按类型可以将组件划分为七大类:视图容器、基础内容、表单、导航、多媒体、地图、画布

<tagname property="value">contens</tagname>

组件属性的名称都是小写的,以连字符“ - ”连接

  1. 组件共同类型
    • id:组件的唯一表示
    • class:样式类
    • style:内联样式
    • hidden:是否显示
    • data-*:自定义属性
    • bind*/catch*:组件的事件,bind为冒泡事件,catch为非冒泡事件
  2. 组件的属性类型
    • Boolean:布尔值
    • Number:数字
    • String:字符串
    • Array:数组
    • Object:对象
    • EventHandler:事件处理函数名
    • Any:任意属性

4.2、视图容器

像前端的<div/>没有任何语义和功能,仅作为容器元素的存在,在小程序中也有类似的容器组件,

例如<view/>、<scroll-view/>、<swiper>

4.2.1、view组件

<view/>是一个块级容器组件,没有特殊功能,主要用于布局展示,是最基本的UI组件,支持常用的CSS布局属性。

  • hover:是否启动点击态,默认为false
  • hover-class:指定按下去的样式。但class=“none”时,没有点击态效果,默认为none
  • hover-start-time:按住后多久出现点击态,默认50毫秒
  • hover-stay-time:手指松开后点击态保留时间,默认400毫秒
1、水平3栏布局

image-20200628110740293

<view style="display:flex;">
    <view style="background-color:red; flex-grow:1; height:80rpx;"></view>
        <view style="background-color:blue; flex-grow:1; height:80rpx;"></view>
        <view style="background-color:green; flex-grow:1; height:80rpx;"></view>
</view>
2、左右混合布局

image-20200628112855358

<!-- 左右布局 -->
<view style="display:flex; height:400rpx;">
  <view style="background-color:red; width:250rpx; color:#fff;">1</view>
  <view style="flex-grow:1; display:flex; flex-direction:column;">
    <view style="flex-grow:1; background-color:blue; color:#fff;">2</view>
    <view style="flex-grow:1; background-color:green; color:#fff;">3</view>
  </view>
</view>
3、上下混合布局

image-20200628112920047

<view style="display:flex; flex-direction:column; height:400rpx;">
    <view style="background-color:red; height:150rpx; color:#fff;">1</view>
    <view style="flex-grow:1; background-color:blue; color:#fff;">2</view>
    <view style="flex-grow:1; background-color:green; color:#fff;">3</view>
</view>

4.2.2、scroll-view滑动框

具备滑动能力的组件,使用<scroll-view>增加滚动相关属性

  • scroll-x:允许横向滚动,默认false
  • scroll-y:允许纵向滚动,默认false
  • upper-threshold:距顶部/左边多远时(单位px),触发scrolltoupper事件,默认50
  • lower-threshold:距底部/右边多远时触发scrolltolower事件,默认为50
  • scroll-top:设置竖向滚动条位置,number/string
  • scroll-left:设置横向滚动条位置, number/string
  • scroll-into-view:值应为某子元素id,滚动到该元素时,元素顶部对齐滚动区域顶部
  • bindscrolltoupper:滚动到顶部/左边,会触发scrolltoupper事件
  • bindscrolltolower:滚动到底部/右边,会触发scrolltolower事件
  • bindscroll:滚动时触发

目前,<textarea/>、<video/>、<map/>、<comvas/>不能在<scroll-view/>中使用

image-20200628115348863

<scroll-view class="scroll-container" upper-threshold="0" lower-threshold="100" scroll-into-view="{{toView}}" bindscroll="scroll" bindscrolltolower="scrollToLower" bindscrolltoupper="scrollToUpper" scroll-y="true" scroll-top="{{scrollTop}}">
    <view id="item-1" class="scroll-item bg-red">1</view>
    <view id="item-2" class="scroll-item bg-blue">2</view>
    <view id="item-3" class="scroll-item bg-red">3</view>
    <view id="item-4" class="scroll-item bg-blue">4</view>
    <view id="item-5" class="scroll-item bg-red">5</view>
    <view id="item-6" class="scroll-item bg-blue">6</view>
</scroll-view>
<view class="act">
    <button bindtap="scrollToTop">点击滚动到顶部</button>
</view>
Page({ 
    data:{ 
        toView:'item-3'
    } ,
    /* 
    生命周期回调—监听页面加载页面加载时触发。
    一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
    */
    onLoad: function (options) { 
        this.setData({ 
            toView: 'item-3'
        } )
    } ,
    scrollToUpper:function(){ 
        console.log('触发滚动顶部事件');
    } ,
    scrollToLower:function(){ 
        console.log('触发滚动到底部事件');
    } ,
    scroll:function(){ 
        console.log("触发了滚动事件");
    } ,
    scrollToTop:function(){ 
        this.setData({ 
            scrollTop:'0'
        } );
    } 
} )
/* 给予固定高度 */
.scroll-container{ 
    border:solid 1px;
    height:800rpx;
} 
.scroll-container .scroll-item{ 
    height:300rpx;
    width:120%;
} 
.bg-blue{ 
    background-color:#87CEFA;
} 
.bg-red{ 
    background-color:#FF6347;
} 
.act{ 
    padding:10px;
} 

4.2.3、滑块视图组件

滑块视图容器可以实现轮播图、滑动页面、图片预览等效果。由一个<swiper/><swiper-item/>组成。

<swiper/>只能放置<swiper-item/>

<swiper-item/>能放置任何组件

<swiper/>组件的属性:

  • indicator-dots: 是否显示面板指示点,默认为 false
  • autoplay: 是否自动切换,默认为 false
  • current: 当前所在页面的 index,默认为0
  • interval: 自动切换时间间隔,默认为5000
  • duration: 滑动动画时长,默认为1000
  • circular: 是否采用衔接滑动,默认值为 false
  • bindchange: current改变时会触发change事件,event.detail={current: current}
1、基本轮播图

image-20200628125207434

  • WXML文件
<!-- 基本轮播图 -->
<!-- 开启默认面板指示点,并设置为自动播放 -->
<!-- 
  interval 设置显示时间
  duration 设置切换时的时间
  bindchange 滑动时自动触发该事件
 -->
<swiper class="banner" indicator-dots="true" autoplay="{{autoplay}}" current="0" interval="3000" duration="1000" bindchange="change">
    <block wx:for="{{sliderList}}">
        <swiper-item class="{{item.className}}">
            {{item.name}}
        </swiper-item>
    </block>
</swiper>
<view>
    <button bindtap="play">暂停|播放</button>
</view>
  • WXSS文件
.banner{ height:400px; background-color:#ddd;} 
.bg-blue{ background-color:#87CEFA} 
.bg-red{ background-color:#FF6347} 
.bg-green{ background-color:#43CD80} 
  • js文件
Page({ 
    data:{ 
        autoplay:true,
        sliderList:[
            { className:'bg-red', name:'slider1'} ,
               { className:'bg-blue', name:'slider2'} ,
            { className:'bg-green', name:'slider3'} 
        ]
    } ,
    play:function(){ 
        this.setData({ 
            autoplay:!this.data.autoplay
        } );
    } ,
    change:function(){ 
        console.log('执行了滚动');
    } 
} );
2、自定义轮播图

通过bindchage事件实现自定面板

image-20200709194654445

  • wxml
<!-- 自定义轮播图 -->
<view class="customSwiper">
    <!-- 不开启默认面板 -->
    <swiper class="banner" autoplay="true" interval="2000" deration="300" bindchange="switchTab">
        <block wx:for="{{sliderList}}">
            <swiper-item>
                <image src="{{item.imageSource}}"></image>
            </swiper-item>
        </block>
    </swiper>
    <!-- 自定义面板构建 -->
    <view class="tab">
        <block wx:for="{{sliderList}}">
        {{item.selected}}:{{index+1}}
      </block>
    </view>
</view>
  • wxss
.customSwiper{ 
    height:379.5rpx;
    position:relative;
} 
.customSwiper swiper{ 
    height:100%;
} 
/* 自定义面板样式 */
.tab{ 
    height:70rpx;
    position:absolute;
    bottom:0;
    display:flex;
    width:100%;
    text-align:center;
    justify-content:center;
    align-items:center;
} 
.tab .tab-item{ 
    background-color:#ccc;
    height:50rpx;
    width:50rpx;
    line-height:50rpx;
    font-size:12rpx;
    color:#fff;
    border-radius:4px;
    margin-right:10px;
} 
.tab .tab-item.selected{ 
    background-color:red;
} 
  • js
// 自定义轮播图
Page({ 
  data:{ 
      sliderList:[
          { selected:true, imageSource:'../image/banner1.png'} ,
          { selected:false, imageSource:'../image/banner2.png'} ,
          { selected:false, imageSource:'../image/banner3.png'} ,
      ]
  } ,
  // 监听swiper滚动事件,并切换面板
  switchTab:function(e){ 
    console.log(e);
    var sliederList = this.data.sliderList;
    // 修改指定点选中态
    for(var i = 0; i < sliederList.length; i++){ 
      sliederList[i].selected = e.detail.current == i;
    } 
    this.setData({ 
        sliderList: sliederList
    } )
  } 
} )

4.3、基础组件

4.3.1、icon图标

<icon/>是页面中非常常用的组件,它通常用于表示状态,起到引导作用

  • type:icon的类型。

    有效值包括:success、success_no_circle、info、warn、waiting、cancel、download、search、clear

  • size:icon的大小,单位px。默认23px

  • color:icon的颜色

1、示例

image-20200628142358814

  • xml

    <!-- 小图标 -->
    <view class = "section size">
        <view class="title">图标大小展示</view>
        <view class="list">
            <block wx:for="{{sizeList}}">
                <view class="item">
                <icon type="success_no_circle" size="{{item}}"></icon>
                {{item}}
                </view>
            </block>
        </view>
    </view>
    <view class="section">
        <view class="title">图标类型展示</view>
        <ciew class="list">
            <block wx:for="{{typeList}}">
                <view class="item">
                    <icon type="{{item}}"></icon>
                  {{item}}
                </view>
            </block>
        </ciew>
    </view>
    <view class="section">
        <view class="title">图标颜色展示</view>
        <ciew class="list">
            <block wx:for="{{colorList}}">
                <view class="item">
                    <icon type="safe_success" color="{{item}}"></icon>
                  {{item}}
                </view>
            </block>
        </ciew>
    </view>
  • wxss

    .section{ 
        font-size:12px;
        padding:10px;
    } 
    .section .list{ 
        display:flex;
        flex-wrap:wrap;
    } 
    .section .list .item{ 
        width:300rpx;
        padding:5px 0;
        display:flex;
        flex-direction:column;
        justify-conntent:flex-end;
    } 
    .section .size .list .item{ 
        width:100rpx;
        padding:0;
    } 
    .section .list .item label{ 
        text-align:center;
    } 
    .section .list .item icon{ 
        text-align:center
    } 
  • js

    // 小图标
    Page({ 
      data:{ 
          sizeList:[
              '10px',
              '20px',
              '30px',
              '40px'
          ],
          typeList:[
              'success', 
              'success_no_circle',
              'safe_success', 
              'success_circle',
              'info', 
              'info_circle', 
              'waiting',
              'waiting_circle',
              'warn', 
              'safe_warn', 
              'circle', 
              'download', 
              'cancel', 
              'search', 
              'clear'
        ],
          colorList:['green', 'rgb(139, 101, 8)']
      } 
    } )
2、自定义样式图标组件

使用阿里的图标库:https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2

目前只能使用黑白颜色的图标

  • 将图标添加到购物车,然后添加到项目中

    image-20200628151131559

  • 生成相应的代码链接

    image-20200628151246058

  • 将代码导入到小程序项目中

    image-20200628151404173

  • 只需要在需要使用的页面的wxss文件中导入上面文件即可

    image-20200628151505695

  • 使用图标

    image-20200628151600087

4.3.2、text文本

<text>组件主要用于文本内容的展示,类似HTML中的<p/>标签。

在小程序中,只有<text>节点内部的内容可以被长按选中,同时文本内容支持转义字符” \ “

  • wxml

    <text>{{content}}</text>
  • js

    Page({ 
        data:{ 
            content:'我是内容\n我是内容\n我是内容'
        } 
    } );

4.3.3、progress进度条

用于显示进度状态,比如资源加载、用户资料完成度、媒体资源播放进度等。

  • percent:百分比显示
  • show-info:是否在进度条右侧显示百分比,默认false
  • stroke-width:进度条宽度,单位px,默认6
  • color:进度条颜色
  • active:是否显示从左到右的动画,默认false
<progress percent="20" show-info="true"></progress>
<progress percent="30" show-info="true"></progress>
<progress percent="40" stroke-width="40" show-info="true"></progress>
<progress percent="50" color="rgb(51, 216, 216)" show-info="true"></progress>
<progress percent="99" active="true" show-info="true"></progress>
  • 效果展示

image-20200628152944848

4.4、表单组件

表单是应用中获取用户输入的重要手段

4.4.1、radio单选

单项框可以用来生成一组单选按钮,供用户从一批固定的选项中做出选择。单选框使用<radio-group/><radio/>两个组件组成。

<radio>不能单独使用。

radio属性:

  • value<radio/>标识,当选中时,<radio-group>的change事件会携带<radio/>的value
  • checked:是否被中,一组中只能有一个,出现多个时,默认最后一个
  • disabled:是否禁用,默认false
  • color:radio的颜色

示例

<!-- 单选框 -->
<radio-group bindchange="changeChoosed">
    <view wx:for="{{radios}}">
        <radio value="{{item.value}}">{{item.text}}</radio>
    </view>
</radio-group>
//单选框
Page({ 
  data:{ 
      radios:[
          { value:'1', text:'选项1', checked:false} ,
          { value:'2', text:'选项2', checked:false} ,
          { value:'3', text:'选项3', checked:false} ,
          { value:'4', text:'选项4', checked:false} 
      ]
  } ,
  changeChoosed:function(event){ 
      console.log('你选中了:'  + event.detail.value);
  } 
} )

效果

image-20200628191807287

4.4.2、checkbox复选

与单选框一样,复选框需要<checkbox-group/><checkbox/>两个组件组成

checkbox的属性

  • value:触发时会携带的值
  • checked:是否选中
  • disabled:是否禁用

示例

<!-- 复选框 -->
<checkbox-group bindchange="checkboxChange">
    <view wx:for="{{countrys}}">
        <checkbox value="{{item.value}}" checked="{{item.checked}}" diable="{{item.diable}}">
        {{item.name}}
      </checkbox>
    </view>
</checkbox-group>
// 复选框
Page({ 
  data:{ 
      countrys:[
          { name:'中国', value:'1'} ,
          { name:'美国', value:'2', checked:true} ,
          { name:'日本', value:'3', disabled:true} ,
          { name:'韩国', value:'4'} ,
          { name:'俄罗斯', value:'5', checked:true} 
      ]
  } ,
  checkboxChange: function(e){ 
      console.log('你选中的选项有:' + e.detail.value);
  } 
} )

效果

image-20200628192919076

4.4.3、switch开关

<switch/>是一个开关选择器

  • checked:是否选中
  • type:UI样式,有效值有switch、checkbox、默认为switch
  • bindchange:checked改变时触发change事件

示例

<!-- 开关选择器 -->
<view wx:for="{{switchs}}">
  <switch type="{{item.type}}" checked="{{item.checked}}" bindchange="{{item.changeEventName}}">
    {{item.name}}
  </switch>
</view>
// 开关选择器
Page({ 
  data:{ 
      switchs:[
          { 
              name:'switch1',
              checked:false,
              type:'switch',
              changeEventName:'change'
          } ,
          { 
              name:'switch2',
              checked:true,
              type:'checkbox',
              changeEventName:'change'
          } 
      ]
  } ,
  // 修改开关选择器对象模型的选中值
  change:function(e){ 
    console.log(e);
  } 
} )

效果

image-20200628201115117

4.4.4、Label文字

用来改进表单组件的可用性,绑定for属性让用户点击<label/>时触发对应的控件,目前可以绑定<button/>、<checkbox/>、<radio/>、<switch/>

触发<label/>的两种规则

  • 内部控件:将控件放在标签内,当用户点击时触发第一个控件
  • 设置for属性点击时触发for属性对应的控件。for属性优先级高于内部控件,

示例

<!-- label组件的使用 -->
<view class="section">
    <checkbox-group bindchange="checkboxchange">
        <label>
            <checkbox value="value-1" />点击文案也能选中radio
        </label>
    </checkbox-group>
</view>

<view class="section">
    <label>
        <switch />点击文案也能切换开关
    </label>
</view>

<view class="section">
    <view class="title">选中元素内第一个</view>
    <checkbox-group>
        <label>
            <checkbox value="value-1" />第一个
            <checkbox value="value-1" />第二个
            <checkbox value="value-1" />第三个
            <checkbox value="value-1" />第四个
            <checkbox value="value-1" />第五个
        </label>
    </checkbox-group>
</view>

<view class="section">
    <view class="title">for属性优先级大于内部元素</view>
    <checkbox-group>
        <label for="mycheckbox">
            <checkbox />label内部元素
            <checkbox />label内部元素
        </label>
        <checkbox id="mycheckbox" />label外部元素
    </checkbox-group>
</view>
/* lable组件的使用 */
.section { 
  font-size: 12px;
  padding: 20px 10px;
  border-top: solid 1px #eee;
} 
// label组件的使用
Page({ 
  checkboxchange:function(e){ 
    console.log(e);
    console.log(e.detail.value[0]);
  } 
} )

效果:点击文案能够触发内部控件,当有多个控件的时候触发第一个,可以设置for数值指定点击时候触发哪个控件。

image-20200628203521554

4.4.5、slider滑动选择

滑动选择器 <slider/>,调节亮度、音量等

  • min:最小值,默认为0
  • max:最大值,默认为100
  • step:步长,默认为1
  • disabled:是否禁用
  • value:当前取值
  • color:背景条颜色
  • selected-color:已选择的颜色
  • show-value:是否在右侧显示当前value(不需要赋值)
  • bindchange:完成一次拖动后触发的事件

示例

<!-- 滑动选择器 -->
<view class="section incon-wrapper">
    <icon type="success" size="{{icon.size}}" style="opacity:{{icon.opacity/100}};"/>
</view>
<view class="section">
    <view>调整大小</view>
    <slider show-value selected-color="#00f" max="100" min="10" step="5" value="size" bindchange="changeSize"></slider>
</view>
<view class="section">
    <view>调整透明度</view>
    <slider show-value max="100" min="20" step="5" value="opacity" bindchange="changeOpacity"></slider>
</view>
// 滑动选择器
Page({ 
    data:{ 
        icon:{ 
            size:20,
            opacity:8
        } 
    } ,
   // 改变大小
    changeSize:function(e){ 
        this.data.icon.size=e.detail.value;
        this.setData(this.data);
    } ,
    // 改变透明度
    changeOpacity:function(e){ 
        this.data.icon.opacity=e.detail.value;
        console.log(this.data);
        this.setData(this.data);
    } 
} );

效果

image-20200629192634721

4.4.6、picker选择器

可以在屏幕底部弹出一个窗口,供用户在所提供的选项中选择一个

1、普通选择器
  • range:底部弹出选项的数组,默认为一个空数组,只有当mode为selector是,range属性才有效
  • rang-key:当range是一个Object Array时,通过rang-kty来指定Object中key的值作为选择器显示的内容
  • value:mode为selector时,value值时数字,表示选择了range中的第几个,从0开始
  • bindchange:value改变时触发change事件
  • disabled:是否禁用

示例

<picker value="selectedIndex" range="{{list}}" bindchange="change">
    <view class="picker">
        当前选中:{{list[selectedIndex]}}
    </view>
</picker>
.picker{ 
    border:solid 1px #ddd;
    background-color:#fafafa;
    padding:10px;
} 
Page({ 
    data:{ 
        // 创建对应选择项
        list:[
            '选项1',
            '选项2',
            '选项3'
        ],
        selectedIndex:0
    } ,
    change:function(e){ 
        // 修改选中文案
        this.setData({ 
            selectedIndex:e.detail.value
        } )
    } 
} );

效果

image-20200630111836516

2、时间选择器

在普通选择器的基础上,将mode属性值定义为time即可

  • value:表示选中的时间,字符串格式为“ hh:mm”
  • start:表示有效时间范围的开始
  • end:表示有效时间范围的结束
  • bindchange:value改变时触发change事件
  • disable:是否禁用

示例

<!-- 时间选择器 -->
<picker value="selectTime" mode="time" start="{{startTime}}" end="{{endTime}}" bindchange="change">
    <view class="picker">
        当前选中:{{selectTime}}
    </view>
</picker>
Page({ 
    data:{ 
        startTime:"00:00",
        endTime:"24:00",
        selecTime:"11:30"
    } ,
    // 修改选中项文案
    change:function(e){ 
        this.setData({ 
            selectTime:e.detail.value
        } )
    } 
} )

效果

image-20200630112922680

3、日期选择器

对应的mode属性为data

  • value:表示选中的日期,字符串格式为“yyyy-MM-dd”
  • start:表示有效日期范围的开始
  • end:表示有效日期范围的结束
  • fields:表示选择器的粒度,有效值为year、month、day,默认为day
  • bindchange:value改变时触发change事件
  • disabled:是否禁用,默认值为false

示例

<!-- 日期选择器 -->
<picker value="selectDate" mode="date" start="{{startDate}}" end="{{endDate}}" filed="day" bindchange="change">
    <view class="picker">
        当前选中:{{selectDate}}
    </view>
</picker>
// 日期选择器
Page({ 
    data:{ 
        startDate:"2020-6-30",
        endDate:"2020-12-30",
        selectDate:"2020-10-01"
    } ,
    change:function(e){ 
        this.setData({ 
            selectDate:e.detail.value
        } )
    } 
} )

效果

image-20200630114413691

4.4.7、picker-view自定义选择器

自定义滚动选择器,使用<picker-view/>和<picker-view-column/>实现,其中<picker-view-column/>用于创建列

<picker-view/>属性如下

  • value:数组类型,数组中的数字依次表示选择的第几项,从0开始
  • indicator-style:设置选择器中间选中框的样式
  • bingchange:当滚动选择时,触发事件
属性 类型 默认值 必填 说明 最低版本
value Array.<number> 数组中的数字依次表示 picker-view 内的 picker-view-column 选择的第几项(下标从 0 开始),数字大于 picker-view-column 可选项长度时,选择最后一项。 1.0.0
indicator-style string 设置选择器中间选中框的样式 1.0.0
indicator-class string 设置选择器中间选中框的类名 1.1.0
mask-style string 设置蒙层的样式 1.5.0
mask-class string 设置蒙层的类名 1.5.0
bindchange eventhandle 滚动选择时触发change事件,event.detail = {value};value为数组,表示 picker-view 内的 picker-view-column 当前选择的是第几项(下标从 0 开始) 1.0.0
bindpickstart eventhandle 当滚动选择开始时候触发事件 2.3.1
bindpickend eventhandle 当滚动选择结束时候触发事件 2.3.1

示例

  • wxml代码
<!-- 自定义选择器 -->
<view class="custom-picker">
    <view class="title">
        自定义滑动选择器
    </view>
    <!-- 设置内部选中选项高度 -->
    <picker-view  indicator-style="height: 50px;" bindchange="change">
        <!-- 日期列 -->
        <picker-view-column>
            <view class="cell" wx:for="{{list}}" wx:key="list">
                {{item.date}}
            </view>
        </picker-view-column>
        <!-- 时段列 -->
        <picker-view-column>
            <view class="cell" wx:for="{{times}}" wx:key="times1">
                {{item.time}}
            </view>
        </picker-view-column>
    </picker-view>
</view>

其中wx:key的作用

官方解释:当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

我的理解:不使用 wx:key的情况下, 如果 array 内的数据发生改变,则会重新创建每个Item对象然后渲染列表(费时费力)在使用 wx:key的情况下,如果array中的数据发生改变,只是将对应的对象重新排序。未发生变化的对象,不会重新创建。

  • js代码
// 自定义选择器
Page({ 
    data:{ 
        list:[
            { date:'6月30日'} ,
            { date:'7月01日'} ,
            { date:'7月02日'} 
        ],
        times:[],
        times1:[
            { time:'19:00'} ,
            { time:'19:30'} ,
            { time:'20:00'} ,
            { time:'20:30'} ,
            { time:'21:00'} ,
            { time:'21:30'} 
        ],
        times2:[
            { time:'22:00'} ,
            { time:'22:30'} ,
            { time:'23:00'} ,
            { time:'23:30'} ,
            { time:'00:00'} ,
            { time:'00:30'} 
        ],
        times3:[
            { time:'01:00'} ,
            { time:'01:30'} ,
            { time:'02:00'} ,
            { time:'02:30'} ,
            { time:'03:00'} ,
            { time:'03:30'} 
        ]
    } ,
    // 日期改变时渲染对应时间
    change:function(e){ 
        console.log(e);
        switch(e.detail.value[0]){ 
            case 0:
                this.setData({ 
                    times:this.data.times1
                } );
                break;
            case 1:
                this.setData({ 
                    times:this.data.times2
                } );
                break;
            case 2:
                this.setData({ 
                    times:this.data.times3
                } );
                break;
        } 
    } ,
    // 初始化运行
    onLoad: function (options) { 
        this.setData({ 
            times:this.data.times1
        } )
      } ,
} )
  • wxss代码
/* 自定义选择器 */
.custeom-picker{ 
  top:100px;
  width: 80%;
  margin: 0 auto;
  margin-top: 200rpx;
  border: solid 1px #ccc;
} 
.custom-picker .title{ 
  text-align: center;
  color: #444;
  padding: 20rpx;
  font-size: 24rpx;
  background-color: #eee;
  border-bottom: solid 1px #ccc;
} 
.custom-picker picker-view{ 
  height: 200px;
} 
.custom-picker picker-view .cell{ 
  line-height: 50px;
  text-align: center;
} 
.custom-picker picker-view-column{ 
  border-right: solid 1px #ccc;
  position: relative;
  left: 1px;
} 
  • 运行效果:选择不同的日期会对应不同的时间选项

image-20200630152714151

4.4.8、input输入框

单行输入框,根据不同的type属性值,输入字段拥有很多形式,与HTML不同的是<input/>类型没有按钮类型

  • value:输入框的初始内容
  • type:input的类型;有效值为:text、number、idcard、digit、time、date
  • password:是否显示密码类型,默认为false
  • placeholder:输入框为空时的占位符
  • placeholder-style:指定placeholder的样式
  • placeholder-class:指定placeholder的样式类,默认值为imput-placeholder
  • disable:是否禁用
  • maxlength:最大输入长度,设置为0时不限制最大长度,默认为140
  • cursor-spacing:指定光标与键盘的距离,单位px
  • auto-focus:自动聚焦,拉起键盘。页面中只能由一个设置该属性
  • focus:获取焦点,默认false
  • bindinput:当键盘输入时触发事件
  • bindfocus:输入框聚焦时触发
  • bindblur:输入框失去焦点时触发
  • bindconfirm:点击完成按钮时触发

示例演示

  • wxml代码
<view class="section">
    <input placeholder="默认样式,自动聚焦" auto-foucus/>
</view>
<view class="section">
    <input placeholder="内容中123会被替换为0" bindinput="changeValue" type="number" maxlength="20"/>
</view>
<view class="section">
    <input placeholder="输入3个以上字符会收起键盘" bindinput="hideKeyboard" type="number"/>
</view>
  • js代码
// input输入框
Page({ 
    changeValue:function(e){ 
        console.log(e.detail);
        var value = e.detail.value,
            // 光标位置cursor
            pos = e.detail.cursor,
            left;
        if(pos > 0){ 
            // 获取光标前面的内容
            left = value.slice(0, pos);
            // 修改后光标的位置也要变化
            pos = left.replace('123', '0').length;
        } 
        return{ 
            value:e.detail.value.replace('123', '0'),
            cursor:pos
        } 
    } ,
    hideKeyboard:function(e){ 
        console.log(e.detail.value.length);
        if(e.detail.value.length >= 3){ 
            // 调用关闭键盘的API
            wx.hideKeyboard();
        } 
    } 
} )
  • wxss代码
.section { 
  font-size: 12px;
  padding: 10px;
} 
.section input{ 
  border: solid 1px #ccc;
  padding: 0 5px;
  background-color: #fff;
  border-radius: 4px;
  height: 30px;
} 

效果展示:进入时自动选中第一个输入框

image-20200630191150993

4.4.9、textarea文本域

多行输入框,但与HTML中的不同,小程序中的是一个自闭合标签,它的值需要赋值为value属性,而不是被标签包裹

  • value:初始内容

  • placeholder:输入框为空时的占位符

  • placeholder-style:指定placeholder的样式

  • placeholder-class:指定placeholder的样式类,默认值为imput-placeholder

  • disable:是否禁用

  • maxlength:最大输入长度,设置为0时不限制最大长度,默认为140

  • auto-focus:自动聚焦,拉起键盘。页面中只能由一个设置该属性

  • cursor-spacing:指定光标与键盘的距离,单位px

  • focus:获取焦点,默认false

  • fixed:如果textarea是一个position:fixed的区域,需要显示指定属性fixed为true,默认false

  • bindinput:当键盘输入时触发事件

  • bindfocus:输入框聚焦时触发

  • bindblur:输入框失去焦点时触发(可以实现Ajax功能)

  • bindconfirm:点击完成按钮时触发

  • bindlinechange:输入框行数变化时调用,首次渲染时也会触发

示例演示

<view class="section">
    <textarea bindblur="getValue" placeholder="请输入文案" placeholder-class="textarea-holder"/>
</view>
Page({ 
    getValue:function(e){ 
        // 失去焦点触发
        console.log(e.detail.value);
    } 
} )
.section { 
  font-size: 12px;
  padding: 10px;
} 
.section textarea{ 
  border:solid 1px #ccc;
  padding: 5px;
  background-color: #fff;
  border-radius: 10px;
  height: 60px;
} 
.section .textarea-holder{ 
  color: rgb(65, 72, 158);
} 

效果

image-20200630200605125

4.4.10、button按钮

按钮至少有3种状态:默认点击(default)、建议点击(primary)、谨慎点击(warn)

  • size:表示按钮的大小;有效值为:default、mini,默认值为default
  • type:按钮的样式类型,有效值为primary、default、warn,默认为default
  • plain:按钮是否镂空,背景色透明,默认值为false
  • diable:是否禁用,默认false
  • loading:名称前是否带loading图标,默认为false。通常在表单提交过程中或者按钮点击后等待反馈时,就需要打开loading让用户感知
  • form-type:用于<form/>组件,有效值为submit、reset,可以触发表单的事件
  • hover-class:指定按钮按下去的样式类。当hover-class=“none”时,没有点击态效果,默认为button-hover
  • hover-start-time:按住后多久出现点击态,单位毫秒,默认50
  • hover-stay-time:手指松开后点击态保留时间,单位毫秒,默认400

示例演示

<!-- 按钮 -->
<button>默认按钮样式</button>
<button size="mini">小类型</button>
<button type="primary">type="primary"</button>
<button type="warn">type="warn"</button>
<button plain>plain镂空</button>
<button disable>disable禁用</button>
<button loading>loading加载</button>
<!-- 按钮按住会变成红色 -->
<button hover-class="my-button-hover">
    按住变红
</button>
<!-- 嵌套多媒体的自定义按钮 -->
<button>
    <image src="../image/灯泡.png"/>
</button>
/* 按钮 */
button{ 
  margin: 8px;
} 
.my-button-hover{ 
  background-color: red;
  color: #fff;
} 

效果展示

image-20200630202720873

去除button的样式
  1. 去掉边框

    .user-phone-btn::after { 
      border: none;
    } 
  2. 去掉圆角(注意border-radius: 0以下两处都要写)

    .user-phone-btn { 
      border-radius: 0;
    } 
    .user-phone-btn::after { 
      border-radius: 0;
    } 
  3. 去除背景

    .user-phone-btn { 
      background-color:transparent;
    } 

4.4.11、form表单

可以将上面学习的组件合并起来使用

  • report-submit:是否返回formId,formId用于发送模板消息,默认false
  • bindsubmit:携带form中的数据触发的submit事件,与<button/>按钮的form-type属性配合使用
  • bindreset:触发重置事件,也是与按钮配合使用

示例演示

<!-- 表单 -->
<form bindsubmit="submit" bindreset="reset">
    <!-- 开关 -->
    <view class="section">
        <view class="title">swicth</view>
        <switch name="开关" />
    </view>
    <!-- 输入框 -->
    <view class="section">
        <view class="title">input</view>
        <input name="输入框" placeholder="请输入内容" value="{{textvalue}}" />
    </view>
    <!-- 复选框 -->
    <view class="section">
        <view class="title">checkbox</view>
        <checkbox-group name="复选框">
            <lable>
                <checkbox value="中国">中国</checkbox>
            </lable>
            <lable>
                <checkbox value="美国">美国</checkbox>
            </lable>
            <lable>
                <checkbox value="日本">日本</checkbox>
            </lable>
        </checkbox-group>
    </view>
    <!-- 单选框 -->
    <view class="section">
        <view class="title">radio</view>
        <radio-group name="单选框">
            <lable>
                <radio value=""></radio>
            </lable>
            <lable>
                <radio value=""></radio>
            </lable>
        </radio-group>
    </view>
    <!-- 选择器 -->
    <view class="section">
        <view class="title">picker</view>
        <picker value="{{selectTime}}" mode="time" bindchange="changeTime" name="时间">
            <view class="picker">
                时间:{{selectTime}}
            </view>
        </picker>
    </view>
    <!-- 提交 -->
    <view class="section">
        <button type="primary" form-type="submit">提交</button>
        <button form-type="reset">重置</button>
    </view>
</form>
.section { 
  font-size: 12px;
  padding: 10px;
} 
.section label{ 
  margin-right: 20px;
} 
.section .title{ 
  margin: 5px 0;
  color: #43CD80;
} 
.section textarea{ 
  border:solid 1px #ccc;
  padding: 5px;
  background-color: #fff;
  border-radius: 10px;
  height: 60px;
} 
Page({ 
    data:{ 
        selectTime:'00:00'
    } ,
    // 时间切换
    changeTime:function(e){ 
        console.log(e);
        this.setData({ 
            selectTime:e.detail.value
        } );
    } ,
    // 点击提交表单
    submit:function(e){ 
        console.log(e.detail.value);
    } ,
    // 重置表单
    reset:function(e){ 
        console.log('已经重置表单');
        this.setData({ 
            selectTime:'00:00'
        } );
    } 
} )

效果展示

image-20200630211225909

4.5、导航组件

<nacigator/>时小程序中的页面链接,作用和HTML的超链接标签一样,控制页面的跳转

  • url:应用内跳转链接,地址为相对地址
  • redirect:跳转行为是否为重定向,如果为true,则跳转时会关闭当前页面,默认为false
  • open-type:可选值为navigate、redirect、switchTab默认为navigate
  • hover-class:点击时的样式类,为none时没有点击效果

示例演示

  • index.wxml
<!-- 导航组件 -->
<navigator url="test?name=lxj&age=20">
    跳转到其他页面
</navigator>
<!-- redirect重定向会销毁原页面 -->
<navigator url="test?name=lxj&age=21" hover-class="myhover" redirect>
    重定向到其他页面
</navigator>
<navigator url="test?name=lxj&age=22" hover-class="myhover" redirect>
    刷新当前页面
</navigator>
  • index.wxss
/* 导航 */
.myhover{ 
  background-color: rgb(175, 230, 161);
  color: rgb(17, 22, 26);
} 
  • test.wxml
<view>
    name:{{query.name}}, age:{{query.time}}
</view>
  • test.js
Page({ 
    data:{ 
        query:{ } 
    } ,
    onLoad:function(query){ 
        // 框架已将参数转化为onLoad参数
        this.data.query = query;
        this.setData(this.data);
    } 
} )

效果展示

  • 默认页面

image-20200701173223715

  • 使用了重定向,只能返回首页并重新加载

image-20200701173237679

  • 返回原页面,无需重新加载

image-20200701173256035

4.6、媒体组件

图片、视频、音频等组件

4.6.1、image图片

属性如下:

  • src:图片资源地址,可以是网络地址
  • mode:图片的裁剪、缩放模式,默认为“scaleToFill”
  • binderror:当错误发生时,发布到App Service的事件名
  • bindload:当图片载入完毕时发布的事件名
  • bindtap:当点击图片时触发

mode属性的13中裁剪模式,4种为缩放模式,9种时裁剪模式

  1. 缩放模式:
    • scaleToFill:不保持纵横比缩放图片,使图片的宽高完全拉伸至填满image元素
    • aspectFit:保持纵横比缩放图片,使图片的长边能够完全显示出来
    • **aspectFill(常用)**:保持纵横比缩放图片,只保证图片的短边能完全显示出来,长边发生截取
    • widthFix:宽度不变,高度自动变化
  2. 裁剪模式(均不缩放图片):
    • top:只显示图片的顶部区域
    • bottom:只显示图片的底部区域
    • center:只显示图片的中间区域
    • left:只显示图片的左边区域
    • right:只显示图片的右边区域
    • top left:只显示图片的左上边区域
    • top right:只显示图片的右上边区域
    • bottom left:只显示图片的左下边区域
    • bottom right:只显示图片的右下边区域

效果对比

  • 缩放模式

image-20200701174820905

  • 裁剪模式

image-20200701174902436

image-20200701174911622

4.6.2、audio音频

基本属性:

  • src:音频资源地址,可以是网络资源
  • loop:是否循环播放,默认为false
  • controls:是否显示默认控件,默认为true
  • poster:默认控件上的音频封面的图片资源地址,如果controls属性值为false则poster无效
  • name:默认控件上的音频名字,如果controls属性值为false则name无效,默认值为“未知音频”
  • author:默认控件上的作者名字,如果controls属性值为false则author无效,默认值为“未知作者”
  • bindended:当播放到末尾时触发ended事件
  • binderror:当发生错误时触发error事件
  • bindplay:当开始/继续播放时触发play事件
  • bindpause:当暂停播放时触发pause事件
  • bindtimeupdate:当播放进度改变时触发timeupdate事件

binderror错误类型:

  • MEDIA_ERR_ABORTED:获取资源被用户禁止
  • MEDIA_ERR_NETWORD:网络错误
  • MEDIA_ERR_DECODE:解码错误
  • MEDIA_ERR_SRC_NOT_SUPPOERTED:不合适资源

示例演示

<!-- 音频组件 -->
<audio poster="{{myaudio.poster}}" src="{{myaudio.src}}" name="{{myaudio.name}}" author="{{myaudio.author}}" controls loop></audio>
// 音频组件
Page({ 
    data:{ 
        myaudio:{ 
            src:'../audio/七里香_周杰伦_128K.mp3',
            poster:'http://cdnmusic.migu.cn/picture/2019/1108/2207/AS2fc0b9eec0a24d3c9c77ed9ee133ffc4.jpg',
            name:'七里香',
            author:'周杰伦'
        } 
    } 
} )

效果展示

image-20200701183543541

4.6.3、video视频

video默认宽高为300px、225px,该组件不能在<scroll-view>中使用

更多属性参考官网:https://developers.weixin.qq.com/miniprogram/dev/component/video.html

  • src:资源地址
  • controls:是否显示控件
  • muted:是否静音
  • initial-time:初始播放位置(number类型)
  • direction:设置全屏时视频的方向,不指定则根据宽高比自动判断,有效值:0、90、-90,正常竖向、屏幕逆时针90度、屏幕顺时针90度
  • show-play-btn:是否显示视频底部控制栏的播放按钮
  • show-center-play-btn:是否显示视频中间的播放按钮
  • enable-progress-gesture:是否开启控制进度的手势
  • poster:封面
  • show-mute-btn:是否显示静音按钮
  • enable-play-gesture:是否开启播放手势,即双击切换播放/暂停
  • enable-auto-rotation:是否开启手机横屏时自动全屏,当系统设置开启自动旋转时生效
  • show-screen-lock-button:是否显示锁屏按钮,仅在全屏时显示,锁屏后控制栏的操作
  • danmu-list:弹幕列表
  • danmu-btn:是否显示弹幕按钮,只能初始化时有效,不能动态变化,默认为false
  • enable-danmu:是否展示弹幕,只能初始化时有效,不能动态变化,默认为false
  • autoplay:是否自动播放,默认false
  • bindplay:当开始/继续播放时触发play事件
  • bindpause:当暂停播放时触发pause事件
  • bindended:当播放到末尾时触发ended事件
  • bindtimeupdate:当播放进度改变时触发timeupdate事件
  • objectFit:当视频大小与video容器大小不一致时,视频的表现形式。contain:包含,fill:填充,cover:覆盖;默认为contain

示例演示

  • wxml
<!-- 视频组件 -->
<view class="video">
    <video 
        enable-auto-rotation
        enable-play-gesture 
        danmu-btn 
        show-center-play-btn 
        show-play-btn 
        id="myVideo" 
        src="{{src}}" 
        danmu-list="{{danmu}}" 
        enable-danmu controls>
    </video>
    <view class="action">
        <button bindtap="getVideo">本地视频</button>
        <view class="danmu">
            <input type="text" value="{{danmuText}}" bindblur="setInputValue" />
            <button bindtap="sendDanmu">发送弹幕</button>
        </view>
    </view>
</view>
  • wxss
/* 视频 */
.video video{ 
  width: 100%;
  height: 380px;
} 
.video .action{ 
  padding: 20rpx;
} 
.video .action .danmu{ 
  margin-top: 10px;
  position: relative;
  padding-right: 210rpx;
  height: 80rpx;
} 
.video .action .danmu input{ 
  border: solid 1px #ccc;
  height: 80rpx;
  padding: 0 10rpx;
  border-radius: 6px;
} 
.video .action .danmu button{ 
  width: 200rpx;
  position: absolute;
  right: 0;
  bottom: 0;
  height: 80rpx;
} 
  • js
Page({ 
    data:{ 
        src:'http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400',
        // 设置弹幕
        danmu:[{ 
            text:'第1s出现的弹幕',
            color:'#f00',
            time:1
        } ,{ 
            text:'第3s出现的弹幕',
            color:'#0f0',
            time:3
        } ],
        danmuText:''
    } ,
    onReady:function(){ 
        // 获取video上下文videoContext对象
        this.videoContext = wx.createVideoContext('myVideo');
    } ,
    getVideo:function(){ 
        var self = this;
        // 从本地或相机中选择视频
        wx.chooseVideo({ 
          success: function(res){ 
              self.setData({ 
                  maxDuration:60,
                  src:res.tempFilePath
              } )
          } ,
        } );
    } ,
    setInputValue:function(e){ 
        // 同步数据
        this.setData({ 
            danmuText:e.detail.value
        } );
    } ,
    sendDanmu:function(){ 
        // 发送弹幕
        var danmuText = this.data.danmuText;
        console.log(this.videoContext);
        this.videoContext.sendDanmu({ 
            text:danmuText,
            color:'#f00'
        } );
        // 发送弹幕后清空输入框
        this.setData({ 
            danmuText:''
        } );
    } 
} );

效果展示

image-20200701201031192

注意支持的格式:

image-20200701201941757

4.7、map地图组件

小程序提供了<map/>组件和定位相关的API,地理位置的获取在后续的API中讲解。同样该组件不能在<scroll-view>中使用

  • latitude:中心纬度

  • longitude:中心经度

  • scale:缩放级别,默认为16

  • markers:标记点,用于在地图上显示标记的位置,不能自定义图标和样式,每个标记点属性如下:

  • polyline:路线

markers属性

标记点用于在地图上显示标记的位置

属性 说明 类型 必填 备注 最低版本
id 标记点 id number marker 点击事件回调会返回此 id。建议为每个 marker 设置上 number 类型 id,保证更新 marker 时有更好的性能。
latitude 纬度 number 浮点数,范围 -90 ~ 90
longitude 经度 number 浮点数,范围 -180 ~ 180
title 标注点名 string 点击时显示,callout存在时将被忽略
zIndex 显示层级 number 2.3.0
iconPath 显示的图标 string 项目目录下的图片路径,支持网络路径、本地路径、代码包路径(2.3.0
rotate 旋转角度 number 顺时针旋转的角度,范围 0 ~ 360,默认为 0
alpha 标注的透明度 number 默认 1,无透明,范围 0 ~ 1
width 标注图标宽度 number/string 默认为图片实际宽度
height 标注图标高度 number/string 默认为图片实际高度
callout 自定义标记点上方的气泡窗口 Object 支持的属性见下表,可识别换行符。 1.2.0
label 为标记点旁边增加标签 Object 支持的属性见下表,可识别换行符。 1.2.0
anchor 经纬度在标注图标的锚点,默认底边中点 Object {x, y},x 表示横向(0-1),y 表示竖向(0-1)。{x: .5, y: 1} 表示底边中点 1.2.0
aria-label 无障碍访问,(属性)元素的额外描述 string 2.5.0

marker 上的气泡 callout

属性 说明 类型 最低版本
content 文本 string 1.2.0
color 文本颜色 string 1.2.0
fontSize 文字大小 number 1.2.0
borderRadius 边框圆角 number 1.2.0
borderWidth 边框宽度 number 2.3.0
borderColor 边框颜色 string 2.3.0
bgColor 背景色 string 1.2.0
padding 文本边缘留白 number 1.2.0
display ‘BYCLICK’:点击显示; ‘ALWAYS’:常显 string 1.2.0
textAlign 文本对齐方式。有效值: left, right, center string 1.6.0
anchorX 横向偏移量,向右为正数 number 2.11.0
anchorY 纵向偏移量,向下为正数 number 2.11.0

marker 上的气泡 label

属性 说明 类型 最低版本
content 文本 string 1.2.0
color 文本颜色 string 1.2.0
fontSize 文字大小 number 1.2.0
x label的坐标(废弃) number 1.2.0
y label的坐标(废弃) number 1.2.0
anchorX label的坐标,原点是 marker 对应的经纬度 number 2.1.0
anchorY label的坐标,原点是 marker 对应的经纬度 number 2.1.0
borderWidth 边框宽度 number 1.6.0
borderColor 边框颜色 string 1.6.0
borderRadius 边框圆角 number 1.6.0
bgColor 背景色 string 1.6.0
padding 文本边缘留白 number 1.6.0
textAlign 文本对齐方式。有效值: left, right, center string 1.6.0

polyline

指定一系列坐标点,从数组第一项连线至最后一项

属性 说明 类型 必填 备注 最低版本
points 经纬度数组 array [{latitude: 0, longitude: 0}]
color 线的颜色 string 十六进制
width 线的宽度 number
dottedLine 是否虚线 boolean 默认 false
arrowLine 带箭头的线 boolean 默认 false,开发者工具暂不支持该属性 1.2.0
arrowIconPath 更换箭头图标 string 在 arrowLine 为 true 时生效 1.6.0
borderColor 线的边框颜色 string 1.2.0
borderWidth 线的厚度 number 1.2.0

position

属性 说明 类型 必填 备注
left 距离地图的左边界多远 number 默认为0
top 距离地图的上边界多远 number 默认为0
width 控件宽度 number 默认为图片宽度
height 控件高度 number 默认为图片高度

示例演示

<!-- 地图组件 -->
<map 
     id="map" 
     longitude="{{longitude}}" 
     latitude="{{latitude}}" 
     circles="{{circles}}" 
     scale="14" 
     controls="{{controls}}" 
     bindcontroltap="controltap" 
     markers="{{markers}}" 
     bindmarkertap="markertap" 
     polyline="{{polyline}}" 
     bindregionchange="regionchange" 
     show-location 
     style="width:100%;height:300px">
</map>
// 地图组件
Page({ 
    data:{ 
        longitude:104,
        latitude:30,
        scale:5,
        // 设置标记点
        markers:[
            { 
                iconPath:"../image/灯泡.png",
                id:0,
                // 纬度
                latitude:30,
                // 经度
                longitude:104,
                // 图片宽高
                width:30,
                height:30
            } ,{ 
                iconPath:"../image/banner3.png",
                id:1,
                latitude:30,
                longitude:104.1,
                width:30,
                height:30
            } 
        ],
        // 设置路线
        polyline:[{ 
            // 按顺序设置5个点
            points:[
                { 
                    longitude:104,
                    latitude:30
                } ,{ 
                    longitude:104.1,
                    latitude:30
                } ,{ 
                    longitude:104.2,
                    latitude:30
                } ,{ 
                    longitude:104.3,
                    latitude:30
                } ,{ 
                    longitude:104.4,
                    latitude:30
                } 
            ],
            color:"#0ff",
            width:2,
            arrowLine:true
        } ],
        // 设置2个图标
        controls:[{ 
            id:1,
            iconPath:'../image/banner1.png',
            position:{ 
                left:0,
                top:250,
                width:30,
                height:30
            } ,
            clickable:true
        } ,{ 
            id:2,
            iconPath:'../image/banner2.png',
            position:{ 
                left:30,
                top:250,
                width:30,
                height:30
            } ,
            clickable:true
        } ]
    } ,
    // 地图发生变化时触发
    regionchange(e){ 
        // type可以区分是开始拖动还是结束拖动
        console.log(e.type)
    } ,
    // 标记点点击触发
    markertap(e){ 
        // 根据标记点markerId区分
        console.log(e.markerId)
    } ,
    // 点击controls设置的图标
    controltap(e){ 
        // 通过markerId区分按钮
        console.log(e.controlId)
    } 
} )

效果展示

image-20200703141702437

4.8、canvas画布组件

<canvas/>用于绘制图形,相当于在页面中放置了一块“画布”,可以在其中进行图形绘制,它仅仅是容器,需要调用相关API来完成实际的绘图任务

  • canvas-id:canvas组件的唯一标识符
  • disable-scroll:当在canvas中移动时,禁止屏幕滚动以及下拉刷新,默认false
  • bindtouchstart:手指触摸动作开始
  • bindtouchmove:手指触摸后移动
  • bindtouchend:手指触摸动作结束
  • bindtouchcancel:手指触摸动作被打断,如来点提示、弹窗
  • bindlongtaop:手指长按500ms之后触发,触发了长按事件后进行移动不会触发屏幕的滚动
  • binderror:当发生错误时触发error事件

实例演示

<canvas canvas-id="myCanvas" style="width:100%; height:300px;">
</canvas> 
// 画布
Page({ 
    onReady:function(){ 
        // 获取绘图上下文
        var context = wx.createContext();
          // 设置线条样式      
        context.setStrokeStyle("#00f");
        context.setLineWidth(5);
        context.rect(3, 2, 150, 200);
        context.stroke();
        // 绘制图像
        wx.drawCanvas({ 
            canvasId:'myCanvas',
            actions:context.getActions()
        } );
        console.log('asdf');
    } 
} );

效果展示

image-20200703143302195

4.9、contact客服会话

<contact-button/>用于在页面显示一个客服会话按钮,点击之后进入客服会话界面,需要后台系统配合

  • size:会话按钮大小,有效值18~27px,默认18
  • type:会话按钮的样式类型,有效值为default-dark、default-light,默认为default-dark
  • session-form:用户从按钮进入会话时,触发带有参数的事件推送

示例演示

<!-- 客服会话按钮 -->
<contact-button session-form="yoursession" style="margin:120rpx">
</contact-button>

效果展示

image-20200703143940590

==关于组件的介绍就到这里了,这些组件能满足大部分开发需求,建立多参考官方文档的组件详细介绍,了解各个组件的功能和特点==

5、小程序API

本部分讲解小程序提供的API,包括 网络、媒体、文件、数据缓存、位置、设备、界面、开放接口8大类,通过逻辑层 JS 代码进行调用

image-20200703144510489

两种调用API的方式

// 以wx.on开头
wx.onSocketOpen(function(res){ 
    console.log('WebSocket连接已打开');
} );
// 不以wx.on开头
wx.request({ 
    // 接口调用成功
    success:function(){ } ,
    // 接口调用失败
    fail:function(){ } ,
    // 接口调用结束(成功失败都会执行)
    complete:function(){ } 
} )

5.1、网络

每个微信小程序需要事先设置一个通信域名,小程序可以跟指定域名进行网络通。包括不同HTTPS请求(wx.erquest)、WebSocket通信(wx.connectSocket)、上传文件(wx.uploadFile)、和下载文件(wx.downloadFile)。设置通信域名需要登录小程序“后台 ==》 设置 ==》 开发设置”,在服务器配置中添加受信任的域。

5.1.1、发起HTTPS请求

使用wx.request(Object)发起HTTPS请求,默认超时时间和最大超时时间为60秒,小程序只能使用HTTPS请求,同时只能有5个网络请求。

Object参数属性如下:

  • url:后台服务器接口地址

  • data:请求的参数

  • header:设置请求头

    header中content-type默认为 ‘application/json’;

    而referer固定为:‘https://servicewechat.com/{appid}/{version}/page-frame.html’,{version}为小程序的版本号,0表示开发版

  • method:HTTPS请求方法类型,默认为GET,有效值为:OPTIONS、GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT,均必须大写

  • dataType:数据类型,默认为json

  • success:收到服务器成功返回的回调函数

  • fail:接口调用失败的回调函数

  • complete:接口调用结束的回调函数

示例代码

wx.request({ 
    url:'https://www.myserver.com',
    header:{ 
        'Content-Type':'application/json'
    } ,
    // 接口调用成功
    success:function(){ } ,
    // 接口调用失败
    fail:function(){ } ,
    // 接口调用结束(成功失败都会执行)
    complete:function(){ } 
} )

5.1.2、上传和下载

1、wx.uploadFile

上传文件最大并发限制为10个,超时为60秒

Object参数属性如下:

  • url:开发者服务器url
  • filePath:要上传文件资源的路径
  • name:文件对应的key,可以在服务端通过这个key获取到文件的二进制内容
  • header:设置请求头,同上
  • formData:HTTP请求中其他额外的请求数据
  • success:收到服务器成功返回的回调函数,参数如下
    • data:开发者服务器的返回数据
    • statusCode:HTTP状态码
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例代码

wx.chooseImage({ 
    // 调用选中图片的接口
    success:function(res){ 
        // 获取临时图片地址
        var tempFilePaths = res.tempFilePaths;
        wx.uploadFile({ 
            // 需要有自己的服务器
            url:'http://www.myserver.com',
            filtPath:tempFilePaths[0],
            name:'myFile',
            formData:{ 
                // 其他数据
                'otherData':'value'
            } ,
            success:function(response){ 
                // 服务器返回数据
                var data = response.data;
            } 
        } )
    } 
} )
2、wx.downloadFile

从服务端下载资源到本地,作为临时文件,如需持久保存需要主动调用wx.saveFile进行保存

  • url:下载资源的url
  • header:设置请求头,同上
  • success:收到服务器成功返回的回调函数
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例代码

wx.downloadFile({ 
    url:'http://myserver.com',
    success:function(res){ 
        // 下载图片资源后读取其信息
        wx.getImageInfo({ 
            src:res.tempFilePaths[0],
            success:function(info){ 
                console.log(info.width + ',' + info.height);
            } 
        } )
    } 
} );

5.1.3、WebSocket

这为短连接方式实现,客户端和服务器端之间的即时通信技术只能使用轮询,需要客户端不断的发出请求,这种方式既浪费性能又占带宽。

1、wx.connectSocket

一个小程序同时只能有一个WebSocket连接

  • url:服务器接口地址。必须是WSS协议,且域名必须是后台配置的合法域名
  • data:请求的数据
  • header:设置请求头,同上
  • method:HTTPS请求方法类型,默认为GET,有效值为:OPTIONS、GET、POST、HEAD、PUT、DELETE、TRACE、CONNECT
  • success:收到服务器成功返回的回调函数
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例代码

wx.connectSocket({ 
    // 服务端需要实现socket监听
    url:'wss://www.myserver.com',
    data:{ 
        myData:'data'
    } ,
    header:{ 
        'Content-Type':'application/json'
    } ,
    method:'get'
} );
2、wx.onSocketOpen

监听WebSocket连接打开事件

实例代码

wx.connectSocket({ 
    // 创建连接
    url:'wss://www.myserver.com'
} );
wx.onSocketOpen(function(res){ 
    console.log('socket连接已打开');
} );
3、wx.onSocketError

监听WebSocket错误

wx.onSocketError(function(res){ 
    console.log('连接打开失败');
} );
4、wx.sendSocketMessage

通过WebSocket连接发送数据

wx.sendSocketMessage({ 
    data:msg
} );
5、wx.onSocketMessage

监听接收到服务器的消息事件,callback返回参数为data

wx.onSocketMessage(function(res){ 
    console.log('收到服务器内容:' + res.data);
} );
6、wx.closeSocket

关闭WebSocket连接

wx.closeSocket();
7、wx.conSocketClose

监听WebSocket是否关闭,成功关闭时触发

wx.conSocketClose(function({ 
    console.log('连接已关闭');
} ));

5.2、媒体

5.2.1、图片

1、wx.chooseImage

从本地相册选择图片或者使用相机拍照,拍照时产生的临时路径,在小程序本次启动期间可以正常使用,如需持久保存,需要调用wx.saveFile,这样下次启动时才能访问到。

  • count:最多可以选择的图片张数,默认为9
  • sizeType:图片尺寸类型,有效值为original(原图)、compressed(压缩图),默认二者都有
  • sourceType:获取图片的方式,有效值为album(从相册选图)、camera(使用相机),默认二者都有
  • success:成功则返回图片的本地文件路径列表tempFilePaths
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例演示

<view>
    <image src="{{src}}"></image>
    <button bindtap="chooseImage">选择图片</button>
</view>
// 选择图片
Page({ 
  src:'',
  chooseImage:function(){ 
      var self = this;
      wx.chooseImage({ 
          count:1,
          sizeType:['original', 'compressed'],
          sourceType:['album', 'camera'],
          success:function(res){ 
              console.log(res.tempFilePaths);
              self.setData({ 
                src:res.tempFilePaths
              } )
          } 
      } );
  } 
} );

效果展示

image-20200703184626631

2、wx.previewImage

预览图片,调用后小程序会开启图片浏览界面

  • current:当前显示图片的链接,必须是urls中存在的链接,不填则默认第一张
  • urls:需要预览的图片的链接列表
  • success:接口调用成功
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例代码

wx.previewImage({ 
    // 默认先显示第二张
    current:'png2',
    urls:[
        'png1',
        'png2'
    ]
} );
3、wx.getImageInfo

获取图片信息

  • src:图片的路径
  • success:接口调用成功的函数
  • fail:接口调用失败的回调函数
  • complete:接口调用结束的回调函数

示例代码

chooseImage:function(){ 
    wx.chooseImage({ 
        success:function(res){ 
            wx.getImageInfo({ 
                src:res.tempFilePaths[0],
                success:function(info){ 
                    console.log(info);
                } 
            } )
        } 
    } )
} 

5.2.2、录音

1、wx.startRecord

开始录音,主动调用wx.stopRecord,或者录音超过1分钟时自动结束录音。

  • success:录音成功后调用,返回临时文件路径,res={tempFilePath:’录音文件的临时文件路径’}
  • fail:失败的回调函数
  • complete:结束的回调函数
wx.startRecord({ 
    success:function(res){ 
        var tempFilePath = res.tempFilePath;
        wx.playVoice({ 
            // 录音完成后立即播放
            filePath:tempFilePath
        } )
    } 
} )
2、wx.stopRecord

主动调用停止录音

// 十秒自动停止
setTimeout(function(){ 
    wx.stopRecord();
} , 10000)

5.2.3、音频播放控制

1、wx.playVoice

开始播放语音,同时只允许一个文件播放

  • filePath:文件路径
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.playVoice({ 
    filePath:tempFilePath
} )
2、wx.pauseVoice

暂停正在播放的语音,再次调用则继续播放。使用wx.stopVoice才可以重头播放

示例代码

// 播放五秒后暂停
setTimeout(function(){ 
    wx.pauseVoice();
} , 5000);
3、wx.stopVoice

结束播放语音

// 播放五秒后结束
setTimeout(function(){ 
    wx.stopVoice();
} , 5000);

5.2.4、音乐播放控制

1、wx.getBackgroundAudioPlayerState

获取后台音乐播放状态,调用本方法可以获取<audio/>组件等的音乐。

  • success:成功,参数如下:
    • duration:选定音频的长度
    • currentPosition:选定音频播放位置
    • status:播放状态
    • downloadPercent:音频的下载进度
    • dataUrl:歌曲数据链接
  • fail:失败
  • complete:结束

示例代码

wx.getBackgroundAudioPlayerState({ 
    success:function(res){ 
        var statusText = { 
            2 : '没有音乐在播放',
            1 : '播放中',
            0 : '暂停中'
        } 
        console.log(statusText[res.status]);
    } 
} )
2、wx.playBackgroundAudio

播放音乐

  • dataUrl:音乐链接
  • title:音乐标题
  • coverImgUrl:封面URL
  • success:成功
  • fail:失败
  • complete:失败

示例代码

wx.playBackgroundAudio({ 
    dataUrl:'mp3',
    title:'我的音乐',
    coverImgUrl:'jpg',
    success:function(){ 
        console.log("开始播放音乐了");
    } 
} );
3、wx.pauseBackgroundAudio

暂停播放音乐

// 暂停播放
wx.pauseBackgroundAudio();
4、wx.seekBackgroundAudio

控制音乐播放进度,实现快进、快退和播放位置拖动功能

  • position:音乐位置
  • success:成功
  • fail:失败
  • complete:结束

示例代码

// 获取播放状态
wx.wx.getBackgroundAudioPlayerState({ 
    success:function(res){ 
        var currentPosition = res.currentPosition;
        wx.seekBackgroundAudio({ 
            position: currentPosition + 30
        } );
    } 
} );
5、wx.stopBackgroundAudio

停止播放音乐

wx.stopBackgroundAudio();
6、wx.onBackgroundAudioPlay

监听音乐播放

wx.onBackgroundAudioPlay(function(){ 
    console.log('音乐播放');
} )
7、wx.onBackgroundAudioPause

监听音乐暂停

wx.onBackgroundAudioPause(function(){ 
    console.log('音乐暂停');
} )
8、wx.onBackgroundAudioStop

监听音乐停止

wx.onBackgroundAudioStop(function(){ 
    console.log('音乐停止');
} )

5.2.5、音频组件的控制

wx.creatAudioContext(audioId) 创建并返回audio上下文audioContext对象,通过audioId和组件绑定

  • setSrc:设置音频地址
  • play:播放
  • pause:暂停
  • seek:跳转到指定位置,单位为s

示例演示

<!-- 音频控制 -->
<view class="custom-audio">
    <audio id="myAudio" style="display:none;" controls></audio>
    <image class="poster" mode="widthFix" src="http://cdnmusic.migu.cn/picture/2019/1108/2207/AS2fc0b9eec0a24d3c9c77ed9ee133ffc4.jpg"></image>
    <view class="actions" bindtap="action">
        <view data-type="play">播放</view>
        <view data-type="pause">暂停</view>
        <view data-type="seek">跳到30秒</view>
        <view data-type="reset">重放</view>
    </view> 
</view>
// 音频控制
Page({ 
  onReady:function(e){ 
      this.audioContext = wx.createAudioContext('myAudio');
      this.audioContext.setSrc('../music/七里香_周杰伦_128K.mp3');
  } ,
  action:function(e){ 
    var type = e.target.dataset.type,
        audioContext = this.audioContext;
    console.log(type);
    switch(type){ 
        // 播放
        case 'play':
          audioContext.play();
          break;
        // 暂停
        case 'pause':
          audioContext.pause();
          break;
        // 跳转
        case 'seek':
          audioContext.seek(200);
          console.log('跳到30秒');
          break;
        // 重放
        case 'reset':
          audioContext.seek(0);
          break;
    } 
  } 
} )
.custom-audio{ 
  width: 500rpx;
  border: solid 1px #ccc;
  border-bottom: 0;
  margin: 60rpx auto;
} 

.custom-audio .poster{ 
  width: 80%;
  border-radius: 50%;
  margin: 10%;
} 

.custom-audio .actions view{ 
  height: 80rpx;
  line-height: 80rpx;
  text-align: center;
  border: solid 1px #ccc;
  border-width: 1px 0px;
  background: -webkit-gradient(linear, 0% 0% 0% 100%, from(#fff), to(#eee));
  margin-top: 10rpx;
} 

效果展示

image-20200704144025535

5.2.6、视频

wx.chooseVideo拍摄视频或从手机相册选取视频,返回视频的临时文件路径。

  • sourceType:获取视频方式,album从相册中选视频,camera使用相机拍摄,默认两者都有

  • maxDuration:拍摄视频最长拍摄时间,单位秒,最长支持60秒

  • camera:拍摄适配的方式用前置或后置视像头,默认为前后都有;有效值为back后、front前

  • success:成功,参数如下:

    • tempFilePath:选定临时文件路径
    • duration:选定视频的时间长度
    • size:选定视频的数据量大小
    • height:选定视频的高
    • width:宽
  • fail:失败

  • complete:结束

示例代码

wx.chooseVideo({ 
    sourceType:['album', 'camera'],
    camera:['front', 'back'],
    success:function(res){ 
        console.log(res.tempFilePath);
    } 
} );

5.2.7、视频组件控制

wx.createVideoContext(videoId)获取上下文

  • play:播放
  • pause:暂停
  • seek:跳转,单位为s
  • sendDanmu:发送弹幕,danmu有两个属性text,color

示例演示

<!-- 视频控制 -->
<video src="http://wxsnsdy.tc.qq.com/105/20210/snsdyvideodownload?filekey=30280201010421301f0201690402534804102ca905ce620b1241b726bc41dcff44e00204012882540400&bizid=1023&hy=SH&fileparam=302c020101042530230204136ffd93020457e3c4ff02024ef202031e8d7f02030f42400204045a320a0201000400" id="myVideo"></video>
<button bindtap="play">播放</button>
<button bindtap="pause">暂停</button>
<button bindtap="restart">回到开头</button>
<button bindtap="sendDanmu">发送弹幕</button>
// 视频控制
Page({ 
  onReady:function(){ 
      this.videoContext = wx.createVideoContext('myVideo');
  } ,
  play:function(){ 
      this.videoContext.play();
  } ,
  pause:function(){ 
      this.videoContext.pause();
  } ,
  restart:function(){ 
      this.videoContext.seek(0);
  } ,
  sendDanmu:function(){ 
      this.videoContext.sendDanmu({ 
          text:'弹幕',
          color:'#faf'
      } );
  } 
} );

效果展示:可以通过按钮实现相应控制

image-20200704145556940

5.3、文件

从网络下载、拍照、录音、录视频时,都是存在临时文件中,需要持久化保存需要调用文件处理API5.

5.3.1、wx.saveFile

保存文件到本地,本地文件存储大小限制为10MB

  • tempFilePath:需要保存文件的临时路径
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.saveFile({ 
    // 保存已获取的临时文件
    tempFilePath:tempFilePath,
    success:function(res){ 
        // 持久地址路径
        var saveFilePath = res.savedFilePath;
        console.log('文件已保存');
    } 
} );

5.3.2、wx.getSavedFileList

获取本地已保存文件列表

  • success:成功,参数如下:
    • errMsg:接口调用结果
    • fileList:文件列表,属性包括:
      • createTime:文件保存的时间戳,从1970/01/01 08:00:00到当前的秒数
      • size:文件的大小,单位为B
  • fail:失败
  • complete:结束

示例代码

wx.getSavedFileList({ 
    success:function(res){ 
        for(var i = 0; i < res.fileList.length; i++){ 
            console.log('第' + (i+1) + '个文件,路径为:' + res.fileList[i].filePath);
        } 
    } 
} )

5.3.3、wx.getSaveFileInfo

获取本地文件的文件信息

  • filePath:文件路径
  • success:成功,参数如下:
    • errMsg:接口调用结果
    • size:文件大小,单位B
    • createTime:文件保存时的时间戳
  • fail:失败
  • complete:结束

示例代码

wx.getSaveFileInfo({ 
    filePath:file.filePath,
    success:function(res){ 
        console.log('文件大小为' + res.size)
    } 
} )

5.3.4、wx.removeSavedFile

删除本地存储文件

  • filePath:文件路径
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.removeSavedFile({ 
    filePath:file.filePath
} );

5.3.5、wx.openDocument

在新页面打开文档,支持的格式有:doc、docx、xls、xlsx、ppt、pptx、pdf

  • filePath:文件路径
  • success:成功
  • fail:失败
  • complete:结束

示例代码

// 调用下载文件接口
wx.downloadFile({ 
    url:'http://www.myserver.com/my.docx',
    success:function(res){ 
        var filePath = res.filePath;
        // 下载文档后在新页面中预览
        wx.openDocument({ 
            filePath:filePath
        } );
    } 
} );

5.4、数据缓存

每个小程序都可以有自己的本地缓存,local Storage是永久存储的,本地缓存最大为10MB,数据操作分为同步和异步两种

5.4.1、保存数据

1、wx.setStorage

将数据存在本地缓存指定的key中,会覆盖掉原来该key对应的内容,这是一个异步接口

  • key:本地缓存中的指定的key
  • data:需要存储的内容
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.setStorage({ 
    key:'myKey',
    data:'myValue'
} );
2、wx.setStorageSync

将数据缓存到本地中,这是同步接口

  • key:本地缓存中指定的key
  • data:需要存储的内容

实例代码

wx.setStorageSync('myKey', 'myValue');

5.4.2、获取数据

1、wx.getStorage

从本地缓存中异步获取指定key对应的内容

  • key:本地缓存中指定的key
  • success:接口调用的回调函数
  • fail:失败
  • complete:结束

示例代码

wx.getStorage({ 
    key:'myKey',
    success:function(res){ 
        // 打印出myKey对应的内容
        console.log(res.data);
    } 
} )
2、wx.getStorageSync

从本地缓存中同步获取指定key的对应内容

var value = wx.getStorageSync('myKey');
console.log(value);

5.4.3、获取本地数据信息

1、wx.getStorageInfo

异步获取当前storage的相关信息

  • success:成功,参数如下:
    • keys:当前storage中所有的key
    • curretSize:当前占用的空间大小,单位kb
    • limitSize:限制的空间大小,单位kb
  • fail:失败
  • complete:结束

示例代码

wx.getStorageInfo({ 
    success:function(res){ 
        var p;
        for(p in res.keys){ 
            console.log(p + ':' + wx.getStorageSync(p));
        } 
    } 
} );
2、wx.getStorageInfoSync

同步获取当前storage的相关信息

var p,
    info = wx.getStorageInfoSync();
for(p in info.keys){ 
    console.log(p + ':' + wx.getStorageSync(p));
} 

5.4.4、删除数据

1、wx.removeStorage

根据key值异步删除本地数据

  • key:本地缓存中指定的key
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.removeStorage({ 
    key:'myKey',
    success:function(res){ 
        console.log(res.data);
    } 
} );
2、wx.removeStorageSync

根据key值同步删除本地数据

wx.removeStorageSync('myKey');

5.4.5、清空数据

1、wx.clearStorage

异步清理本地缓存

wx.clearStorage();
// 不会阻塞下面代码的运行
2、wx.clearStorageSync

同步清理本地数据缓存

wx.clearStorageSync();
// 会阻塞下面代码的运行

5.5、位置

5.5.1、获取位置

wx.getLocation用于获取当前的地理位置、速度,需要用户开启定位功能

  • type:默认为wgs84返回的GPS坐标,而gcj02返回的可用于wx.openLocation的坐标
  • success:成功,参数如下:
    • latitude:纬度,有效值-90~90
    • longitude:经度,有效值-180~180
    • speed:速度
    • accuracy:位置的精确度
  • fail:失败
  • complete:结束

示例代码

wx.getLocation({ 
    type:'wgs84',
    success:function(res){ 
        console.log(res);
    } 
} );

5.5.2、选择位置

wx.chooseLocation用于打开地图选择位置,用户选中后返回选中的信息

  • success:成功,参数如下:

    • name:位置名称
    • address:详细地址
    • latitude:纬度,有效值-90~90
    • longitude:经度,有效值-180~180
    • cancel:用户取消调用
  • fail:失败

  • complete:结束

示例代码

wx.chooseLocation({ 
    success:function(res){ 
        console.log(res.address);
    } 
} );

5.5.3、查看位置

wx.openLocation用于在微信内置地图查看位置

  • latitude:纬度,有效值-90~90
  • longitude:经度,有效值-180~180
  • scale:缩放比例,有效值为1~28,默认28
  • name:位置名称
  • address:详细地址
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.getLocation({ 
    // 返回可用于wx.openLocation的经纬度
    type:'gcj02';
    success:function(res){ 
           wx.openLocation({ 
            latitude:res.latitude,
            longitude:res.longitude
        } );
    } 
} );

5.5.4、地图组件控制

wx.createMapContext用于创建并返回map上下文mapContext对象

  • getCenterLocation:获取当前地图中心的经纬度,返回的是gcj02坐标系,属性如下:
    • moveToLocation:将地图中心移动到当前定位点,需要配置map组件的show-location使用
    • success:成功
    • fail:失败
    • complete:结束

示例演示

<!-- 地图控制 -->
<map id="myMap" show-location class="mymap"/>
<button data-type="getCenterLocation" bindtap="action">获取位置</button>
<button data-type="location" bindtap="action">移动位置</button>
Page({ 
    onReady:function(e){ 
        this.mapContext = wx.createMapContext('myMap');
    } ,
    action:function(e){ 
        var type = e.target.dataset.type,
            mapContext = this.mapContext;
        switch(type){ 
            // 获取当前地图中心纬度
            case 'getCenterLocation':
                mapContext.getCenterLocation({ 
                    success:function(res){ 
                        console.log(res.longitude + ',' + res.latitude);
                    } 
                } );
                break;
            // 定位到当前位置
            case 'location':
                mapContext.moveToLocation();
                break;
        } 
    } 
} )
.mymap{ 
  height: 400px;
  width: 400px;
} 

效果展示

image-20200704213141439

5.6、设备

5.6.1、系统信息

1、wx.getSystemInfo

异步获取系统信息

  • success:成功,参数如下:

    • model:手机型号
    • pixelRatio:设备像素比
    • windowWidth:窗口宽度
    • windowHeight:窗口高度
    • language:微信设置的语言
    • version:微信版本号
    • system:操作系统版本
    • platform:客户端平台
  • fail:失败

  • complete:结束

示例演示

<!-- 手机信息 -->
<view>手机型号:{{model}}</view>
<view>像素比:{{pixelRatio}}</view>
<view>微信版本号:{{version}}</view>
<view>操作系统:{{system}}</view>
<view>客户端平台:{{platform}}</view>
// 手机信息
Page({ 
    data:{ 
        model:'',
        pixelRatio:'',
        version:'',
        system:'',
        platform:''
    } ,
    onReady:function(){ 
        var self = this;
        wx.getSystemInfo({ 
            success:function(info){ 
                self.setData({ 
                    model:info.model,
                    pixelRatio:info.pixelRatio,
                    version:info.version,
                    system:info.system,
                    platform:info.platform
                } )
            } 
        } );
    } 
} )

效果展示

image-20200704222358697

2、wx.getSystemInfoSync

同步获取系统信息

vat info = wx.getSystemInfoSync();
console.log(info);

5.6.2、网络状态

wx.getNetworkType用于获取网络类型

  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.getNetworkType({ 
    success:function(res){ 
        console.log(res.networkType)
    } 
} )

5.6.3、重力感应

wx.onAccelerometerChange监听重力感应数据,频率:5次/秒

  • x:x轴
  • y:y轴
  • z:z轴

横竖屏的判断方法:https://www.cnblogs.com/dianzan/p/9668488.html

image-20200704214600627

示例代码

<view>{{x}},{{y}},{{z}}</view>
Page({ 
    data:{ 
        x:0,
        y:0,
        z:0
    } ,
    onReady:function(){ 
        var self = this;
        wx.onAccelerometerChange(function(res){ 
            self.setData({ 
                x:res.x,
                y:res.y,
                z:res.z
            } );
        } )
    } 
} )

效果展示

image-20200704215021695

5.6.4、罗盘

wx.onCompassChange用于监听罗盘数据,频率:5次/秒,调用罗盘需要开启定位功能

callback参数的属性有direction:前面向的方向度数,正北方为0,范围为0~360,-1代表没有开启定位功能

实例代码

wx.onCompressChange(function(res){ 
    console.log(res.direction);
} );

5.6.5、拨打电话

wx.makePhoneCall用于调用手机拨打电话功能

  • phoneNumber:需要拨打的电话号码
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.makePhoneCall({ 
    phoneNumber:'1111111'
} );

效果展示:在真手机中使用的时候则直接跳转到拨号界面

image-20200704215911845

5.6.6、扫码

wx.scanCode(Object)调起客户端扫码界面,扫码成功后返回对应结果

  • success:成功,参数如下:

    • result:扫码的内容
    • scanType:所扫码的类型
    • charSet:所扫码的字符集
    • path:当所扫的码为当前小程序的合法二维码时,会返回此字段,内容为二维码携带的path
  • fail:失败

  • complete:结束

示例代码

// 自动调用起微信扫码功能
wx.scanCode({ 
    success:function(res){ 
        // 打印扫码内容
        console.log(res.result);
    } 
} )

5.7、界面

5.7.1、交互反馈

1、wx.showToast

显示消息提示框

  • title:提示内容
  • icon:图片,只支持“ success ”、“ loading ”
  • duration:提示的延迟时间,到了指定时间自动关闭,单位为毫秒,默认1500,最大为10000
  • mask:是否显示透明蒙层,防止误触穿透,默认为false
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.showToat({ 
    title:'操作成功',
    icon:'success'
} );
2、wx.hideToast

隐藏消息提示框

wx.showToast({ 
    title:'请稍等...',
    icon:'loading',
    duration:10000
} );
setTimeout(function(){ 
    // 关闭toast
    wx.hideToast();
} , 2000);
3、wx.showModal

显示模态弹窗

  • title:提示的标题
  • content:提示的内容
  • showCancel:是否显示取消按钮,默认为true
  • cancelText:取消按钮的文字,默认为“取消”,最多为4个字符
  • cancelColor:取消按钮的文字颜色,默认为“#000000”
  • confirmText:确定按钮的文字,默认为“确定”,最多为4个字符
  • confirmColor:确定按钮的文字颜色,默认为“#3CC51F”
  • success:成功,表示用户点击确定按钮
  • fail:失败
  • complete:结束

示例代码

wx.showModal({ 
    title:'标题',
    content:'内容',
    success:function(res){ 
        if(!res.confirm){ 
            // 用户点击取消按钮,不做处理
            return;
        } 
        // 可以继续流程
        console.log('用户点击确定');
    } 
} )
4、wx.showActionSheet

显示操作菜单

  • itemList:按钮的文字数组,数组长度最大为6个
  • itemColor:按钮的文字颜色,默认为“ #000000 ”
  • success:成功,表示用户点击确定按钮
    • cancel:用户是否取消选择
    • tapIndex:用户点击的按钮,从上到下的顺序,从0开始
  • fail:失败
  • complete:结束

示例代码

wx.showActionSheet({ 
    itemList:[
        '缺货',
        '配送时间选错',
        '不想买了',
        '其他'
    ]
    success:function(res){ 
        if(!res.cancle){ 
            console.log(res.tapIndex);
        } 
    } 
} )

5.7.2、设置导航条

1、wx.setNavigationBarTitle

动态设置当前页面的标题

  • title:页面的标题
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.setNavigationBarTitle({ 
    title:'新页面'
} );
2、wx.showNavigationBarLoading

在当前页面显示导航条加载动画

Page({ 
    onShow:function(){ 
        wx.showNavigationBarLoading();
    } 
} );
3、wx.hideNavigationBarLoading

隐藏导航条加载动画

示例代码

Page({ 
    onLaunch:function(){ 
        wx.hideNavigationBarLoading();
    } 
} )

5.7.3、导航

1、wx.navigateTo

保留当前页面,跳转到应用内的某个页面,使用wx.navigateBack可以返回到原页面,最多页面路径为5层

  • url:需要跳转的应用内页面的路径,可带参数
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.navigateTo({ 
    url:''
} );
Page({ 
    onLoad:function(option){ 
        console.log(option.query);
    } 
} );
2、wx.redirectTo

关闭当前页面,跳转到应用内的某个页面,可带参数

  • url:页面路径
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.redirectTo({ 
    url:''
} );
3、wx.switchTab

跳转到tabBar页面,并关闭其他所有非tabBar页面

  • url:需要跳转的tabBar页面的路径,不能带参数
  • success:成功
  • fail:失败
  • complete:结束

示例代码

// app.json配置tabBar
{ 
    "tabBar":{ 
        "list":[{ 
            "pagePath":"home",
            "text":"首页"
        } ,{ 
            "pathPath":"other",
            "text":"其他页面"
        } ]
    } 
} 
wx.switchTab({ 
    // 必须是已注册的tab
    url:'/home'
} );
4、wx.navigateBack

关闭当前页面,返回上一页面或多级页面。可通过getCurrenPages()获取当前的页面栈,以决定返回几层。

  • delta:表示返回的页面数,如果大于现有页面则返回到首页,默认为1
// 向前返回3级
wx.navigateBack({ 
    delta:3
} )

5.7.4、动画

wx.createAnimation用于创建一个动画示例animation

  • duration:动画持续时间,单位为ms,默认为400
  • timeingFunction:定义动画的效果,默认值” linear“,有效值为”linear“、”ease“、”ease-in“、”ease-in-out“、”ease-out“、”step-start“、”step-end“
  • delay:动画延迟时间
  • transformOrigin:设置transform-origin,默认为”50%50%0“

示例代码

var animation = wx.createAnimation({ 
    // 以左上角为中心点
    transformOrgin:'0 0',
    duration:20000,
    timingFunction:'ease-in'
} );
1、动画描述

创建实例后我们需要调用实例动画方法来描述动画,这些方法调用后会返回自身,支持链式调用的写法,动画的描述方法按类型可分为样式、旋转、缩放、偏移、倾斜、矩阵变形

(1)样式
  • opacity:设置透明度,参数如下:
    • value:透明度,范围0~1
  • backgroundColor:设置背景颜色,参数如下
    • color:颜色值
  • width:设置宽度,参数如下:
    • length:长度值
  • hright:设置高度
    • top:设置top属性
    • length:长度值
  • left:设置left属性
    • length:长度值
  • bottom:设置底部属性
    • length:长度值
  • right:设置右边属性
    • length:长度值
(2)旋转
  • rotate(deg):从原定顺时针旋转一个deg角度
    • deg:旋转角度,范围-180~180
  • rotatex(deg):在X轴旋转一个deg角度
  • rotatey(deg):在y轴旋转一个deg角度
  • rotatez(deg):在z轴旋转一个deg角度
  • rotate3d(x, y, z, deg):旋转的简写方法
    • x:在x轴的旋转角度,范围-180~180
    • y:在y轴的旋转角度,范围-180~180
    • z:在z轴的旋转角度,范围-180~180
    • deg:从原定顺时针旋转一个deg角度,范围-180~180
(3)缩放
  • scale(sx, sy):同时设置在X轴、Y轴的缩放
    • sx:只有这一个参数时,表示在X轴、Y轴同时缩放sx倍数;当有个参数时,只表示在X轴的缩放
    • sy:Y轴的缩放,可不写
  • scaleX(sx):设置X轴的缩放
  • scaleX(sy):设置y轴的缩放
  • scaleX(sz):设置z轴的缩放
  • scaleX(sx, sy, sz):同时控制X、Y、Z轴的缩放
(4)偏移
  • translate(tx, ty):表示在X、Y轴偏移量
    • tx:只有这一个参数时,表示在X轴、Y轴同时偏移tx,单位px;当有个参数时,只表示在X轴的偏移
    • ty:在Y轴的偏移,单位px
  • translateX(tx):表示在X轴的偏移量
    • tx:在X轴的偏移,单位px
  • translateY(ty):表示在y轴的偏移量
  • translateZ(tz):表示在z轴的偏移量
  • translate3d(tx, ty, tz):表示在X,Y,Z轴的偏移量
(5)倾斜
  • skew(ax,ay):表示在X、y轴倾斜
  • skewX(ax):表示X轴的倾斜
  • skewY(ay):表示Y轴的倾斜
(6)矩阵变形
  • matrix(a, b, c, d, tx, ty):定义矩阵变形,基于X轴和Y轴坐标重新定位元素位置
  • matrix3d():定义矩阵变形,基于X轴、Y轴、Z轴重新定位元素位置
2、动画队列

调用动画操作方法后要调用step()来表示一组动画完成,可以在一组动画调用任意多个动画方法,一组动画中的所有动画会同时开始,一组动画完成后才会进行下一组动画。

示例演示

<!-- 动画 -->
<view style="width:100%; height:200px">
    <icon animation="{{animaData}}" 
        style="position:absolute; left:100px;" 
        type="success" 
        size="40"/>
</view>
<button bindtap="rotateAndMove">旋转并移动</button>
<button bindtap="rotateThenMove">旋转后移动</button>
// 动画
Page({ 
    data:{ 
        animaData:{ } 
    } ,
    // 旋转并移动
    rotateAndMove:function(){ 
        var anim = wx.createAnimation({ 
            // 持续时间
            duration:1000,
            // 动画效果
            timingFunction:'ease'
        } );
           // 偏移、旋转,调用step()来表示一组动画完成
        anim.translateY('100px').rotate('720').step();
        this.setData({ 
            animaData:anim.export()
        } );
    } ,
    // 旋转后移动
    rotateThenMove:function(){ 
        var anim = wx.createAnimation({ 
            timingFunction:'ease'
        } );
        // 分步执行3个动画,通过step切割,duration为持续时间
        anim.rotate('720').step({ duration:500} );
        anim.translateY('100px').step({ duration:500} );
        anim.translateX('100px').step({ duration:500} );
        this.setData({ 
            animaData:anim.export()
        } );
    } 
} );

效果展示

image-20200705110700322

5.7.5、绘图

在组件中提到过的<canvas/>组件,画图必须通过本部分的API实现,绘图可分为3部分:

  1. 创建执行上下文
  2. 通过执行上下文进制绘制描述
  3. 调用绘图API,将绘制描述道<canvas/>

示例演示

<canvas canvas-id="myCanvas" style="width:200px;height:200px;border:solid 1px"/>
// 绘图
Page({ 
    onReady:function(){ 
        // 创建上下文
        var canvasContext = wx.createCanvasContext('myCanvas');
        // 设置绘制描述
        canvasContext.setFillStyle('blue');
        canvasContext.fillRect(15, 15, 100, 100);
        // 绘图
        canvasContext.draw();
    } 
} )

效果展示

image-20200705111513242

1、基础API
(1)wx.createCanvasContext(canvasId)

绘图上下文对象,与组件的id进行绑定

var context = wx.createCanvasContext('myCanvas');
(2)wx.canvasToTempFilePath

将当前画布内容导出生成图片,并返回文件路径

  • canvasId:画布标识,指定导出哪个画布
  • success:接口调用成功,返回参数:
    • tempFilePath:导出图片的文件路径
  • fail:失败
  • complete:结束

实例代码

wx.canvasToTempFilePath({ 
    canvasId:'myCanvas',
    success:function(res){ 
        // 打印出图片路径
        console.log(res.tempFilePath);
    } 
} )
2、canvasContext对象方法

上下文对象包含的方法有10类:样式、渐变、线条样式、矩阵、路径、变形、文字、图片、混合、其他

(1)样式

样式设置会全局作用,如果没有覆盖,则会沿用之前的样式设置

  • setFillStyle(color):设置填充颜色,没有设置默认为black
  • setStrokeStyle(color):设置描边颜色
  • setShadow(offsetX, offsetY, blur, color):设置阴影:
    • offsetX:阴影相对于形状在水平方向的偏移
    • offsetY:阴影相对于形状在竖直方向的偏移
    • blur:阴影的模糊级别,数值越大越模糊
    • color:阴影的颜色

实例演示

<canvas canvas-id="myCanvas" style="width:100%;height:400px;"/>
// 绘图2
Page({ 
    onReady:function(){ 
        var canvasContext = wx.createCanvasContext('myCanvas');
        // 填充方形
        canvasContext.setFillStyle('blue');
        canvasContext.fillRect(10, 10, 50, 50);
        // 绘制方框
        // 设置描边颜色
        canvasContext.setStrokeStyle('#faf');
        // 画一个矩形,默认为黑色
        canvasContext.strokeRect(70, 10, 50, 50);
        // 绘制带阴影方形,前两个参数为偏移量,第三个表示模糊程度
        canvasContext.setShadow(10, 10, 0, '#0ff');
        // 这里填充的方形颜色受到第一句代码影响,也为蓝色
        canvasContext.fillRect(130, 10, 50, 50);
        canvasContext.draw();
    } 
} )

效果展示

image-20200705113906849

image-20200705114103557

(2)渐变

用于创建渐变对象

  • createLinearGradient(x0, y0, x1, y1):创建一个线性渐变,方形渐变图

    • x0:起点的x坐标
    • y0:起点的y坐标
    • x1:终点的x坐标
    • y1:终点的y坐标
    // addColorStop第一个参数范围0~1
    linearGradient.addColorStop(0, 'black');
    linearGradient.addColorStop(1, 'red');
  • createCircularGradient(x, y, r):创建一个圆形的渐变,起点在圆心,终点在圆环

    • x:圆心的x坐标
    • y:圆心的y坐标
    • r:圆的半径
  • addColorStop(stop, color):创建一个颜色渐变点

    • stop:表示渐变点在起点和终点中的位置,取值范围0~1
    • color:渐变点的颜色

使用完渐变之后,需要进行填充显示

// 填充方形
canvasContext.setFillStyle(linearGradient);
canvasContext.fillRect(10, 10, 100, 100);

示例演示

<canvas canvas-id="myCanvas" style="width:100%;height:400px;"/>
// 渐变
Page({ 
    onReady:function(){ 
        var canvasContext = wx.createCanvasContext('myCanvas'),
            linearGradient, 
            circularGradient;
        // 需要根据图形对渐变坐标进行换算
        linearGradient = canvasContext.createLinearGradient(0, 0, 100, 0);
        // 创建渐变时,至少创建2个渐变点,开始与结束
        linearGradient.addColorStop(0, 'red')
        linearGradient.addColorStop(0.33, 'yellow')
        linearGradient.addColorStop(0.66, 'cyan')
        linearGradient.addColorStop(1, 'white');
        // 填充方形
        canvasContext.setFillStyle(linearGradient);
        canvasContext.fillRect(10, 10, 100, 100);
        // 创建圆形渐变
        circularGradient = canvasContext.createCircularGradient(170, 60, 50);
        // 创建多个渐变点
        circularGradient.addColorStop(0, 'red')
        circularGradient.addColorStop(0.16, 'orange')
        circularGradient.addColorStop(0.33, 'yellow')
        circularGradient.addColorStop(0.5, 'green')
        circularGradient.addColorStop(0.66, 'cyan')
        circularGradient.addColorStop(0.83, 'blue')
        circularGradient.addColorStop(1, 'white');
        // 填充方形
        canvasContext.setFillStyle(circularGradient);
        canvasContext.fillRect(120, 10, 100, 100);
        // 绘制图形
        canvasContext.draw();
    } 
} )

效果展示

image-20200705120458646

(3)线条样式

和样式设置一样,线条样式设置会作用全局

  • setLineWidth(lineWidth):设置线条的宽度,默认为1px
  • setLineCap(lineCap):设置线条结束端点样式,默认结束端点样式为square,参数如下:
    • square:端点样式为正方形,不会截取线条宽度
    • butt:端点样式为正方形,会截取线条宽度
    • round:端点样式为圆形,不会截取线条宽度
  • setLineJoin(lineJoin):设置线条的交点样式,默认交点样式为miter。参数取值有:
    • bevel:斜角
    • round:圆角
    • miter:尖角
  • setMiterLimit:设置最大斜接长度,指在两条线交汇处内角和外角之间的距离,当setLineJoin为miter时才有效。

示例演示

<canvas canvas-id="myCanvas" style="width:100%;height:700px;"/>
// 线条样式
var _fn;
Page({ 
    onReady:function(){ 
        var canvasContext = wx.createCanvasContext('myCanvas');
        // 设置线宽度
        canvasContext.setLineWidth(10);
        // 端点样式为正方形,不会截取线条宽度
        canvasContext.setLineCap('square');
        _fn.drawLine(canvasContext, [10, 20], [150, 20]);
        // 端点样式为正方形,但会截取线条宽度
        canvasContext.setLineCap('butt');
        _fn.drawLine(canvasContext, [10, 40], [150, 40]);
        // 端点样式为圆形,不会截取线条宽度
        canvasContext.setLineCap('round');
        _fn.drawLine(canvasContext, [10,60], [150, 60]);
        // 恢复为默认线条边界
        canvasContext.setLineCap('square');
        // 交叉处为斜角
        canvasContext.setLineJoin('bevel');
        _fn.drawAngle(canvasContext, [10,80]);
        // 交叉处为圆角
        canvasContext.setLineJoin('round');
        _fn.drawAngle(canvasContext, [50,80]);
        // 交叉处为尖角
        canvasContext.setLineJoin('miter');
        _fn.drawAngle(canvasContext, [90,80]);
        // 设置交叉处为尖角
        canvasContext.setLineJoin('miter');
        canvasContext.setMiterLimit(1);
        _fn.drawAngle(canvasContext, [10,140]);
        canvasContext.setMiterLimit(2);
        _fn.drawAngle(canvasContext, [50,140]);
        canvasContext.setMiterLimit(3);
        _fn.drawAngle(canvasContext, [90,140]);
        canvasContext.draw();
    } 
} );
_fn = { 
    drawLine:function(canvasContext, start, end){ 
        // 开始画图
        canvasContext.beginPath();
        // 设置起点
        canvasContext.moveTo(start[0], start[1]);
        // 设置终点
        canvasContext.lineTo(end[0], end[1]);
        // 画出当前路径边框
        canvasContext.stroke();
    } ,
    drawAngle:function(canvasContext, beginPoint){ 
        canvasContext.beginPath();
        canvasContext.moveTo(beginPoint[0], beginPoint[1]);
        canvasContext.lineTo(beginPoint[0] + 40, beginPoint[1] + 20);
        canvasContext.lineTo(beginPoint[0], beginPoint[1] + 40);
        canvasContext.stroke();
    } 
} ;

效果展示

image-20200705212223839

(4)矩形
  • rect(x, y, width, height):创建一个矩形,创建后需要调用fill()或stroke()方法将矩形真正画到组件中,参数如下:
    • x:矩形路径左上角的x坐标
    • y:矩形路径左上角的y坐标
    • width:矩形路径的宽度
    • height:矩形路径的高度
  • fillRect(x, y, width, height):填充一个矩形,需要使用setFillStyle()设置颜色,默认黑色
    • x:矩形路径左上角的x坐标
    • y:矩形路径左上角的y坐标
    • width:矩形路径的宽度
    • height:矩形路径的高度
  • stokeRect(x, y, width, height):画一个非填充的矩形,绘制前需要调用setFillStroke()设置线条颜色,默认黑色
  • clearRect(x, y, width, height):清除画布上在该矩形区域的内容,清楚会直接显示出<canvas/>背景色

示例演示

<canvas canvas-id="myCanvas" style="width:100%;height:700px;"/>
// 矩形
Page({ 
    onReady:function(){ 
        var ctx = wx.createCanvasContext('myCanvas');
        // 设置填充颜色
        ctx.setFillStyle('blue');
        ctx.setStrokeStyle('red');
        // 绘制线框矩形
        ctx.rect(10, 10, 30, 30);
        ctx.stroke();
        ctx.draw();
        // 绘制填充矩形
        ctx.rect(50, 10, 30, 30);
        ctx.fill();
        ctx.draw(true); // 传入true,表示接着上次继续绘制
        // 绘制填充矩形
        ctx.fillRect(10, 50, 30, 30);
        ctx.draw(true);
        // 绘制线框矩形
        ctx.strokeRect(50, 50, 30, 30);
        ctx.draw(true);
        // 清除矩形区域
        ctx.clearRect(25, 25, 40, 40);
        ctx.draw(true);
    } 
} )

效果展示

image-20200705214103051

(5)路径

路径绘制并不会在画布上绘制形状,而是创建一个线条路径,可以被stroke()绘制线条,也可以被fill()填充区域,绘制路径需要调用beginPath()方法,结束需要调用closePath()方法。

  • beginPath:开始创建一个路径
  • closePath:关闭一个路径
  • fill:对当前路径中的内容进行填充
  • stroke:画出当前路径的边框,默认为黑色
  • moveTo(x, y):把路径移动到画布中的指定点
  • lineTo(x, y):添加一个新点,并画一条从画布中的点到当前点
  • arc(x, y, z, sAngle, eAngle, counterclockwise):添加一个弧形路径到当前路径,顺时针绘制
    • x:圆的x坐标
    • y:圆的y坐标
    • z:圆的z坐标
    • sAngle:起始弧度,以pai为单位,可以自己进行转换 startAngle*Math.PI/180
    • eAngle:终止弧度
    • counterclockwise:可选。指定弧度的方向时顺时针还是逆时针,默认为false顺时针
  • quadraticCurveTo(cpx, cpy, x, y):创建二次方贝塞尔曲线
    • cpx:贝塞尔控制点x坐标
    • cpy:贝塞尔控制点y坐标
    • x:结束点的x坐标
    • y:结束点的y坐标
  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y):创建三次反贝塞尔曲线
    • cp1x:第一个贝塞尔控制点的x坐标
    • cp1y:第一个贝塞尔控制点的y坐标
    • cp2x:第二个贝塞尔控制点的x坐标
    • cp2y:第二个贝塞尔控制点的y坐标
    • x:结束点的x坐标
    • y:结束点的y坐标

示例演示

<canvas canvas-id="myCanvas" style="width:100%;height:700px;"/>
// 路径
var _fn;
Page({ 
    onReady:function(){ 
        var ctx = wx.createCanvasContext('myCanvas');
        // 绘制三角形线条
        _fn.drawTrianglePath(ctx, [10, 60]);
        ctx.stroke();
        ctx.draw();
        // 绘制扇形
        _fn.drawSectorPath(ctx, [60, 10], 55, 0, 60);
        ctx.setFillStyle('#faa');
        ctx.stroke();
        ctx.fill();
        ctx.draw(true);
        // 绘制二次贝塞尔曲线
        ctx.setLineWidth(1);
        _fn.drawQuaDraticCurve(ctx, [10, 70], [10, 170], [100, 70]);
        ctx.setStrokeStyle("red");
        ctx.stroke();
        ctx.draw(true);
        // 绘制三次贝塞尔曲线
        _fn.drawBezierCurve(ctx, [110,70], [110, 150], [210, 150], [210, 70]);
        ctx.setStrokeStyle("blue");
        ctx.stroke();
        ctx.draw(true);
    } 
} );
_fn = { 
    // 绘制三角形
    drawTrianglePath:function(canvasContext, beginPos){ 
        canvasContext.moveTo(beginPos[0], beginPos[1]);
        // 开始路径
        canvasContext.beginPath();
        // 绘制3条边
        canvasContext.lineTo(beginPos[0] + 30, beginPos[1] - 50);
        canvasContext.lineTo(beginPos[0] + 60, beginPos[1]);
        canvasContext.lineTo(beginPos[0], beginPos[1]);
        // 关闭路径
        canvasContext.closePath();
    } ,
    // 绘制扇形
    drawSectorPath:function(canvasContext, beginPos, radius, startAngle, endAgel){ 
        canvasContext.moveTo(beginPos[0], beginPos[1]);
        // 开始路径
        canvasContext.beginPath();
        // 绘制边线
        canvasContext.lineTo(beginPos[0] + radius, beginPos[1]);
        // 绘制弧线
        canvasContext.arc(beginPos[0], beginPos[1], radius, startAngle*Math.PI/180, endAgel*Math.PI/180);
        // 绘制边线
        canvasContext.lineTo(beginPos[0], beginPos[1]);
        // 结束路径
    } ,
    // 绘制二次贝塞尔曲线路径
    drawQuaDraticCurve:function(canvasContext, startpoint, controlPoint, endPoint){ 
        canvasContext.beginPath();
        canvasContext.moveTo(startpoint[0], startpoint[1]);
        canvasContext.quadraticCurveTo(controlPoint[0], controlPoint[1], endPoint[0], endPoint[1]);
        // 这里不需要关闭路径,否则首尾相连
    } ,
    // 绘制三次贝塞尔曲线路径
    drawBezierCurve:function(canvasContext, startpoint, controlPoint1, controlPoint2, endPoint){ 
        canvasContext.beginPath();
        canvasContext.moveTo(startpoint[0], startpoint[1]);
        canvasContext.bezierCurveTo(controlPoint1[0], controlPoint1[1], controlPoint2[0], controlPoint2[1], endPoint[0], endPoint[1]);
        // 同样不需要关闭
    } 
}  

效果展示

image-20200705221724004

(6)变形

变形方法会整体影响之后绘图方法的坐标体系

  • scale(scaleWidth, scaleHeight):在调用scale方法后,之后创建的路径其横纵坐标都会被缩放,多此调用sacle,倍数会相乘,参数如下:

  • scaleWidth:横坐标缩放的倍数(1 = 100%,0.5 = 50%,2 = 200%)

  • scaleHeight:纵坐标缩放的倍数

  • rotate(rotate):以原点为中心顺时针旋转(degrees*Math.PI/180),原点可以使用translate方法修改。

  • translate(x, y):对当前坐标的原点(0,0)进行变换,默认的坐标系原点为页面左上角

    • x:水平坐标平移量
    • y:竖直坐标平移量

示例演示

<canvas style="width:100%; height:200px;" canvas-id="myCanvas"></canvas>
<button bindtap="scale">坐标放大2倍</button>
<button bindtap="rotate">旋转30度</button>
<button bindtap="translate">原点坐标x、y均加10px</button>
<button bindtap="drawReact">绘制正方形</button>
// 变形
Page({ 
    canvasContext:null,
    onReady:function(){ 
        this.canvasContext = wx.createCanvasContext('myCanvas');
    } ,
    translate:function(){ 
        this.canvasContext.translate(10, 10);
    } ,
    rotate:function(){ 
        this.canvasContext.rotate(30 * Math.PI/180);
    } ,
    scale:function(){ 
        this.canvasContext.scale(2,2);
    } ,
    drawReact:function(){ 
        var context = this.canvasContext;
        // 恢复绘制条件,并弹栈
        context.restore(); 
        context.rect(0, 0, 15, 15);
        context.stroke();
        // 基于上次图形继续绘制
        context.draw(true);
    } 
} )

效果展示

image-20200705230755077

(7)文字

将文字输出到画布中,字体颜色能通过setFillStyle()方法修改,其方法包括fillText(text, x, y):在画布上绘制被填充的文本

  • text:在画布上输出的文本
  • x:绘制文本的左上角x坐标位置
  • y:绘制文本的左上角y坐标位置
  • setFontSize(fontSize):设置字体的字号

示例演示

<canvas style="width:100%; height:200px;" canvas-id="myCanvas"></canvas>
// 文字
Page({ 
    onReady:function(){ 
        var context = wx.createCanvasContext('myCanvas');
        context.fillText('English', 10, 20);
        // 设置字体大小
        context.setFontSize(24);
        // 改变字体颜色
        context.setFillStyle('red');
        context.fillText('中文', 100, 20);
        context.draw();
    } 
} );

效果展示

image-20200706113238659

(8)图片

在画布上绘制图片

  • drawimage(imageResource, x, y, width, height):绘制图片
    • imageResource:图片资源路径
    • x:图像左上角的x坐标
    • y:图像左上角的y坐标
    • width:图像宽度
    • height:图像高度

示例演示

<canvas style="width:100%; height:200px;" canvas-id="myCanvas"></canvas>
// 图片
Page({ 
    onReady:function(){ 
        var context = wx.createCanvasContext('myCanvas');
        context.drawImage(
            '../image/灯泡.png',
            70,
            1,
            100,
            131
        );
        context.draw();
    } 
} )

效果展示

image-20200706114013094

(9)混合

设置全局画笔透明度

  • setGlobalAlpha(alpha):设置透明度
    • alpha:透明度,范围0~1;0表示全透明,1表示全不透明

示例演示

<canvas style="width:100%; height:200px;" canvas-id="myCanvas"></canvas>
// 混合
Page({ 
    onReady:function(){ 
        var context = wx.createCanvasContext('myCanvas');
        context.setFillStyle('blue');
        context.fillRect(10, 10, 100, 100);
        // 设置透明度
        context.setGlobalAlpha(0.5);
        context.fillRect(50, 50, 100, 100);
        context.draw();
    } 
} )

效果展示

image-20200706114819034

(10)其他

其他的一些绘图方法

  • save():保存当前的绘图上下文,每次保存类似将当前设置进行压栈,仅用于保存当前绘图上下文状态,而不是用于保存当前的操作步骤
  • restore():恢复之前保存的绘图上下文
  • **draw(reserve)**:将之前在绘图上下文中的描述滑倒canvas组件中
    • reserve:为flase时,则在本次绘制之前清空画布再继续绘制;为true时,则保留当前内容继续绘制

示例演示

<canvas style="width:100%; height:200px;" canvas-id="myCanvas"></canvas>
// 其他
Page({ 
    onReady:function(){ 
        var context = wx.createCanvasContext('myCanvas');
        context.setFillStyle('red');
        // 保存上下文
        context.save();
        context.setFillStyle('blue');
        context.fillRect(10, 10, 100, 100);
        // 恢复到之前红色设置
        context.restore();
        context.fillRect(120, 10, 100, 100);
        context.draw();
    } 
} )

效果展示:依然保留了red的设置

image-20200706115941449

5.6.7、下拉刷新

下拉刷新包括以下API

  • onPullDownRefresh(callback)
    • 监听下拉刷新事件需要在Page中定义onPull-DownRefresh处理函数。
    • 需要在app.json配置中开启window配置enablePullDownRefresh选项。
  • wx.stopPullDownRefresh():停止当前页面下拉刷新

示例代码

Page({ 
    // 监听当前页面下拉刷新
    onPullDownRefresh:function(){ 
        // 停止当前页面下拉刷新
        wx.stopPullDownRefresh();
    } 
} )

5.8、开放接口

5.8.1、登录

登录分2步骤:

  1. 获取登录凭证
  2. 用登陆凭证获取用户登录态信息
1、wx.login(Object)

调用接口获取登录凭证(code)进而换取用户登录态信息,包括用户唯一表示(openid)及本次登录的会话密钥(session_key),用户数据的加解密通信需要依赖会话密钥完成。

  • success:成功的回调函数,参数如下:
    • errMsg:调用结果
    • code:用户允许登陆后,回调内容回带上code(有效期五分钟),需要将code发送到开发者服务器后台,使用code换取session_key API,将code换成openid和session_key。
  • fail:失败
  • complete:结束

示例代码

wx.login({ 
    success:function(res){ 
        if(!res.code){ 
            return;
        } 
        // 这里建议调用后台接口进行登录转换、保存工作
        wx.request({ 
            url:'https://myserver.com/login',
            data{ 
                   code:res.code
            } ,
               success:function(loginInfo){ 
                console.log('登陆成功');
            } 
        } );
    } 
} );
2、获取用户信息

code换取session_key,调用wx.login()获取code后我们需要在5分钟内用code换取session_key、openid等用户信息,为此官方暴露了一个HTTP接口,可通过wx.request()调用接口,获取信息,但session_key是对用户数据进行加密签名的密钥。

为了自身应用安全,尽量使用后台服务器调用这个接口,保存登录信息,返回给小程序前台,接口地址如下:

https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

请求参数

属性 类型 默认值 必填 说明
appid string 小程序 appId
secret string 小程序 appSecret
js_code string 登录时获取的 code
grant_type string 授权类型,此处只需填写 authorization_code

接口返回参数

属性 类型 说明
openid string 用户唯一标识
session_key string 会话密钥
unionid string 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见 UnionID 机制说明
errcode number 错误码
errmsg string 错误信息
js_code string 调用wx.login()登录时获取的code
grant_type string 填写为“authorization_code”

errcode 的合法值

说明
-1 系统繁忙,此时请开发者稍候再试
0 请求成功
40029 code 无效
45011 频率限制,每个用户每分钟100次

返回值示例代码

// 正常返回的JSON数据包
{ 
    "openid":"OPENID",
    "session_key":"SESSIONKEY",
    "expires_in":2592000
} 
// 错误时返回JSON数据包(示例为Code无效)
{ 
    "errcode":40029,
    "errmsg":"invalid code"
} 
3、登录态维护

开发中,每个项目应该利用后台自己维护登录态,不能直接把session_key、openid等字段作为用户的标识或者session的表示,具体使用可参考后面案例。

4、wx.checkSession

检查登录态是否过期

  • success:接口调用成功的回调函数,登录态未过期
  • fail:失败,登录态过期
  • complete:结束

示例代码

wx.checkSession({ 
    success:function(){ 
        // 登录态未过期
    } ,
    fail:function(){ 
        // 登录态过期
    } 
} )

5.8.2、用户信息

获取用户信息

  • wx.getUserInfo(Object)
    • success:接口成功,参数属性如下:
      • userInfo:用户信息对象,不包含openid等敏感信息
      • rawData:用于计算签名
      • signature:使用sha1(rawData+sessionkey)得到的字符串,用于校验用户信息
      • encryptedData:包括敏感数据在内的完整用户信息的加密数据
      • iv:加密算法的初始向量
    • fail:失败
    • complete:结束

示例代码

wx.getUserInfo({ 
    success:function(res){ 
        // 打印出用户信息
        console.log(res);
    } 
} )

对encryptedData解密后可得到完整的用户信息,如接口 wx.getUserInfo 敏感数据当中的 watermark:image-20200706132510031

加密数据解密算法

接口如果涉及敏感数据(如wx.getUserInfo当中的 openId 和 unionId),接口的明文内容将不包含这些敏感数据。开发者如需要获取敏感数据,需要对接口返回的加密数据(encryptedData) 进行对称解密。 解密算法如下:

  1. 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充。
  2. 对称解密的目标密文为 Base64_Decode(encryptedData)。
  3. 对称解密秘钥 aeskey = Base64_Decode(session_key), aeskey 是16字节。
  4. 对称解密算法初始向量 为Base64_Decode(iv),其中iv由数据接口返回。

微信官方提供了多种编程语言的示例代码((点击下载)。每种语言类型的接口名字均一致。调用方式可以参照示例。

另外,为了应用能校验数据的有效性,会在敏感数据加上数据水印( watermark )

watermark参数说明:

参数 类型 说明
appid String 敏感数据归属 appId,开发者可校验此参数与自身 appId 是否一致
timestamp Int 敏感数据获取的时间戳, 开发者可以用于数据时效性校验
{ 
    "openId": "OPENID",
    "nickName": "NICKNAME",
    "gender": GENDER,
    "city": "CITY",
    "province": "PROVINCE",
    "country": "COUNTRY",
    "avatarUrl": "AVATARURL",
    "unionId": "UNIONID",
    "watermark":
    { 
        "appid":"APPID",
        "timestamp":TIMESTAMP
    } 
} 

5.8.3、微信支付

用于发起微信支付

wx.requesetPayment(Object):

  • timestamp:时间戳,从1970年1月1日00:00:00到现在的秒数
  • nonceStr:随机字符串,长度为32个字符以下
  • package:统一下单接口返回的prepay_id参数值,提交格式如:prepay_id = *
  • signType:签名算法
  • paySign:签名
  • success:成功
  • fail:失败
  • complete:结束

示例代码

wx.requestPayment({ 
    'timeStamp':'',
    'nonceStr':''
} )

5.8.4、模板信息(已废弃)

类似微信支付后推送的支付信息,在小程序中我们也能使用模板给用户推送信息

1、调用模板消息接口

发送模板信息需要通过POST方式调用微信后台接口,可以时前台调用也可以后台,接口地址:

https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN

请求参数

属性 类型 默认值 必填 说明
access_token string 接口调用凭证
touser string 接收者(用户)的 openid
template_id string 所需下发的模板消息的id
page string 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
form_id string 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id
data Object 模板内容,不填则下发空模板。具体格式请参考示例。
emphasis_keyword string 模板需要放大的关键词,不填则默认无放大

请求示例

{ 
  "touser": "OPENID",
  "template_id": "TEMPLATE_ID",
  "page": "index",
  "form_id": "FORMID",
  "data": { 
      "keyword1": { 
          "value": "339208499"
      } ,
      "keyword2": { 
          "value": "2020年07月06日 12:30",
          "color":"#faf"
      } 
  } ,
  "emphasis_keyword": "keyword1.DATA"
} 

返回示例

{ 
 "errcode": 0,
 "errmsg": "ok"
} 

errcode 的合法值

说明
40037 template_id不正确
41028 form_id不正确,或者过期
41029 form_id已被使用
41030 page不正确
45009 接口调用超过限额(目前默认每个帐号日调用限额为100万)

5.8.5、订阅信息

用于代替模板信息

消息能力是小程序能力中的重要组成,为开发者提供了订阅消息能力,以便实现服务的闭环和更优的体验。

  • 订阅消息推送位置:服务通知
  • 订阅消息下发条件:用户自主订阅
  • 订阅消息卡片跳转能力:点击查看详情可跳转至该小程序的页面

img

使用说明

1、获取模板ID

在微信公众平台手动配置获取模板 ID:登录 https://mp.weixin.qq.com 获取模板,如果没有合适的模板,可以申请添加新模板,审核通过后可使用。

image-20200706135458629

image-20200706135735495

复制ID

image-20200706135841297

2、获取下发权限

详见小程序端消息订阅接口 wx.requestSubscribeMessage

属性 类型 默认值 必填 说明
tmplIds Array 需要订阅的消息模板的id的集合,一次调用最多可订阅3条消息(注意:iOS客户端7.0.6版本、Android客户端7.0.7版本之后的一次性订阅/长期订阅才支持多个模板消息,iOS客户端7.0.5版本、Android客户端7.0.6版本之前的一次订阅只支持一个模板消息)消息模板id在[微信公众平台(mp.weixin.qq.com)-功能-订阅消息]中配置
success function 接口调用成功的回调函数
fail function 接口调用失败的回调函数
complete function 接口调用结束的回调函数(调用成功、失败都会执行)

示例代码

wx.requestSubscribeMessage({ 
    tmplIds: [''],
    success (res) {  } 
} )
3、调用接口下发订阅消息

详见服务端消息发送接口 subscribeMessage.send

使用HTTPS 调用,请求地址:

https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN

请求参数

属性 类型 默认值 必填 说明
access_token string 接口调用凭证
touser string 接收者(用户)的 openid
template_id string 所需下发的订阅模板id
page string 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
data Object 模板内容,格式形如 { “key1”: { “value”: any }, “key2”: { “value”: any } }
miniprogram_state string 跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
lang string 进入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN

返回值

属性 类型 说明
errcode number 错误码
errmsg string 错误信息

接口限制

次数限制:开通支付能力的是3kw/日,没开通的是1kw/日。

示例代码

{ 
    "touser": "OPENID",
    "template_id": "TEMPLATE_ID",
    "page": "index",
    "miniprogram_state":"developer",
    "lang":"zh_CN",
    "data": { 
        "number01": { 
            "value": "339208499"
        } ,
        "date01": { 
            "value": "2015年01月05日"
        } ,
        "site01": { 
            "value": "TIT创意园"
        }  ,
        "site02": { 
            "value": "广州市新港中路397号"
        } 
    } 
} 

5.8.6、客服消息

通过点击<cantact-button/>组件进入客服会话系统,用户发送的消息回以POST方式传递给开发者填写的URL

1、接入指引

接入微信小程序消息服务需要2步:

  1. 填写服务器配置
  2. 开发者服务器接受请求并返回指定信息,验证服务器地址有效性

参考官网:https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html

(1)填写服务器配置

登录小程序后台后,在「开发」-「开发设置」-「消息推送」中,管理员扫码启用消息服务,填写服务器地址(URL)、令牌(Token) 和 消息加密密钥(EncodingAESKey)等信息。

  • URL: 开发者用来接收微信消息和事件的接口 URL。开发者所填写的URL 必须以 http:// 或 https:// 开头,分别支持 80 端口和 443 端口。
  • Token: 可由开发者可以任意填写,用作生成签名(该 Token 会和接口 URL 中包含的 Token 进行比对,从而验证安全性)。
  • EncodingAESKey: 由开发者手动填写或随机生成,将用作消息体加解密密钥。

同时,开发者可选择消息加解密方式:明文模式(默认)、兼容模式和安全模式。可以选择消息数据格式:XML 格式(默认)或 JSON 格式。

image-20200706141338222

模式的选择与服务器配置在提交后都会立即生效,请开发者谨慎填写及选择。切换加密方式和数据格式需要提前配置好相关代码,详情请参考 消息加解密说明

(2)验证服务器地址有效性

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

参数 描述
signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串

开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次 GET 请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

验证URL有效性成功后即接入生效,成为开发者。

检验signature的PHP示例代码:

private function checkSignature()
{ 
    $signature = $_GET["signature"];
    $timestamp = $_GET["timestamp"];
    $nonce = $_GET["nonce"];

    $token = TOKEN;
    $tmpArr = array($token, $timestamp, $nonce);
    sort($tmpArr, SORT_STRING);
    $tmpStr = implode( $tmpArr );
    $tmpStr = sha1( $tmpStr );

    if ($tmpStr == $signature ) { 
        return true;
    }  else { 
        return false;
    } 
} 
2、接收消息和时间

微信服务器在将用户的消息发给开发者服务器地址后,微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。如果在调试中,发现用户无法收到响应的消息,可以检查是否消息处理超时。关于重试的消息排重,有 msgid 的消息推荐使用 msgid 排重。事件类型消息推荐使用 FromUserName + CreateTime 排重。

服务器收到请求必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试,否则,将出现严重的错误提示。详见下面说明:

  1. 直接回复success(推荐方式)
  2. 直接回复空串(指字节长度为0的空字符串,而不是结构体中content字段的内容为空)
  3. 若接口文档有指定返回内容,应按文档说明返回

对于客服消息,一旦遇到以下情况,微信会在小程序会话中向用户下发系统提示“该小程序客服暂时无法提供服务,请稍后再试”:

  1. 开发者在5秒内未回复任何内容
  2. 开发者回复了异常数据

接收的消息按类型可分为3类:进入会话事件、文本消息、图片消息。

5.8.7、分享

小程序分享页面需要在Page中定义onShareAppMessage函数,设置该页面分享信息。只有定义了此事件函数,右上角才会显示”分享“按钮。

  • title:分享标题,默认为小程序名称
  • desc:分享描述,默认为当前小程序名称
  • path:分享路径,必须是以 ” / “开头且在app.json中已注册的路径,默认为当前页面path
Path({ 
    onShareAppMessage:function(){ 
        return{ 
            title:'自定义分享标题',
            desc:'自定义分享描述',
            path:'/path/home?tab=cart'
        } 
    } 
} )

5.8.8、获取二维码

wxacode.createQRCode获取小程序二维码,适用于需要的码数量较少的业务场景。通过该接口生成的小程序码,永久有效,有数量限制,详见获取二维码

请求地址

https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=ACCESS_TOKEN

请求参数

属性 类型 默认值 必填 说明
access_token string 接口调用凭证
path string 扫码进入的小程序页面路径,最大长度 128 字节,不能为空;对于小游戏,可以只传入 query 部分,来实现传参效果,如:传入 “?foo=bar”,即可在 wx.getLaunchOptionsSync 接口中的 query 参数获取到 { foo:"bar"}
width number 430 二维码的宽度,单位 px。最小 280px,最大 1280px

示例代码

{ 
 "path":"page/index/index",
 "width":430
} 

5.9、动态修改标题

quwei: function () { 
    wx.setNavigationBarTitle({ 
        title: '趣味表情' 
    } )
}