微信小程序开发

微信小程序官方文档:微信开放文档

目录

一、开发环境配置

申请开发Appid

安装开发工具 

二、微信小程序开发相关配置及说明

 允许上传的文件

全局配置

页面配置

sitemap 配置

三、小程序基本开发

小程序页面的创建及单个页面入口

小程序页面的创建 

方法一:右键文件夹点击“新建Page”,快速生成单个页面的基本文件

方法二:在app.json的pages字段中直接添加页面路径,保存后,开发工具会根据路径自动生成相关文件

小程序页面的生命周期 

在小程序中使用flex布局实现一个小demo(引入微信小程序)

步骤一:在页面的wxml中使用列表渲染展示数据

步骤二:在页面的wxss中使用flex布局给wxml添加样式 

四、WSXL语法

数据绑定

列表渲染

小Demo引入列表渲染 (看不懂可跳过)

步骤一:在wxs中定义数据

步骤二:使用wx:for将数据列表渲染

条件渲染(wx:if、wx:else、wx:elif)

模版 

定义模板

使用模板

 渲染结果展示​编辑

模版使用案例一:

模版使用案例二:

引用 

 定义模版​编辑

使import导入模版并使用

使用include导入模板并使用 

五、WXSS语法 

wxss与css相比扩展的特性

尺寸单位

样式导入

选择器

 全局样式与局部样式

六、WXS语法

模块

module 对象

require函数

标签

变量 

运算符 

 基本运算符

一元运算符 

位运算符 

比较运算符 

 等值运算符

 赋值运算符

 二元逻辑运算符

其他运算符 

语句

 if 语句

 switch 语句

for 语句

while 语句 

数据类型 

number

 string

 boolean

object 

function

array 

date 

regexp

数据类型判断 

constructor:判断数据类型

 typeof:可以区分部分数据类型

WXS响应事件 (以官方提供例子为例)

案例:movable-view(可移动的视图容器,在页面中可以拖拽滑动)

使用WXS函数用来响应小程序事件 

在WXML中定义事件 

定义并导出WXS中的时间处理函数和属性改变触发的函数

Tips:

七、事件

绑定事件与事件交互 

绑定事件

事件交互 

事件冒泡和捕获 

事件分类

绑定并阻止事件冒泡

互斥事件绑定 

 事件的捕获阶段

 八、微信小程序组件

基本组件

 icon(图标组件) 

progress (进度条组件)

rich-text(渲染html内容组件)

 text(文本组件)

表单常用组件

组件说明

表单组件提交获取信息案例

视图容器

组件说明

轮播图案例(通过案例学习swiper相关属性)

可滚动视图案例

媒体组件

组件说明

媒体组件案例---音频组件

媒体组件案例---视频组件 

画图组件

组件说明

画图组件案例

其他组件

九、微信小程序API 


一、开发环境配置

申请开发Appid

  • 进入小程序注册网址小程序
  • 根据提示信息完成注册 

  •  查询注册后的appid

登录https://mp.weixin.qq.com查看自己的appid

后面会跟着自己的appid,这里看不见是进行了处理

安装开发工具 

微信开发者工具下载地址与更新日志 | 微信开放文档

 第一次打开开发工具需要微信登录

 登录后进入项目管理页面

创建项目 

项目开发界面以及项目结构说明

二、微信小程序开发相关配置及说明

 允许上传的文件

wxs、png、jpg、jpeg、gif、svg、json、cer、mp3、aac、m4a、mp4、wav、ogg、silk、wasm、br、cert

  • 注意:除以上文件能上传外,其他文件能在开发工具访问到,但是无法上传

全局配置

  • 小程序根目录下的 app.json 文件用来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等(详细请查阅官方文档)

代码示例

{
  "pages": [
    "pages/index/index",
    "pages/logs/index"
  ],
  "window": {
    "navigationBarTitleText": "Demo"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/logs/index",
      "text": "日志"
    }]
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true
}

 配置相关名称说明

页面配置

  • 每一个小程序页面也可以使用同名 .json 文件来对本页面的窗口表现进行配置,页面中配置项会覆盖 app.json 的 window 中相同的配置项。

代码示例

{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "微信接口功能演示",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light"
}

sitemap 配置

  • 小程序根目录下的 sitemap.json 文件用来配置小程序及其页面是否允许被微信索引。

    完整配置项说明请参考小程序 sitemap 配置

三、小程序基本开发

小程序页面的创建及单个页面入口

在项目中的pages/index/index.js是单个页面的js脚本文件,在这个js文件中的Page字段为这个页面的入口程序

Page({
  data:{
    name:'123'
  }
})
Page字段参数说明
参数说明
data页面的初始数据
options页面的组件选项
behaviors类似于mixins和traits的组件间代码复用机制
onLoad生命周期回调—监听页面加载
onShow生命周期回调—监听页面显示
onReady生命周期回调—监听页面初次渲染完成
onHide生命周期回调—监听页面隐藏
onUnload生命周期回调—监听页面卸载
onRouteDone生命周期回调—监听路由动画完成
onPullDownRefresh监听用户下拉动作
onReachBottom页面上拉触底事件的处理函数
onShareAppMessage用户点击右上角转发
onShareTimeline用户点击右上角转发到朋友圈
onAddToFavorites用户点击右上角收藏
onPageScroll页面滚动触发事件的处理函数
onResize页面尺寸改变时触发
onTabItemTap当前是 tab 页时,点击 tab 时触发
onSaveExitState页面销毁前保留状态回调

小程序页面的创建 

方法一:右键文件夹点击“新建Page”,快速生成单个页面的基本文件

优点:便捷快速,小程序会自动在app.json中的Pages字段中添加这个页面的路径,但是不默认是这个新建的页面为默认展示页面

缺点:该方法只生成单页面的基本文件,为方便文件架构,我们一般在Pages中手动创建一个文件夹,然后在这个文件夹里生成新的页面文件

补充:要展示的这个页面,要把页面的路径移动到第一个这个操作是在app.json中

方法二:在app.json的pages字段中直接添加页面路径,保存后,开发工具会根据路径自动生成相关文件

小程序页面的生命周期 

Page生命周期说明
生命周期名称说明

onLoad

页面加载时触发。一个页面只会调用一次,可以在 onLoad 的参数中获取打开当前页面路径中的参数

onReady

页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互

onShow

页面显示/切入前台时触发

onHide

页面隐藏/切入后台时触发

onUnload

页面卸载时触发
onRouteDone路由动画完成时触发

onPullDownRefresh

监听用户下拉动作

Page事件处理函数
事件名称说明
onPullDownRefresh监听用户下拉刷新事件
onReachBottom        监听用户上拉触底事件
onPageScroll监听用户滑动页面事件
onAddToFavorites监听用户点击右上角菜单“收藏”按钮的行为,并自定义收藏内容
onShareAppMessage监听用户点击页面内转发按钮(button 组件open-type="")或右上角菜单“转发”按钮的行为,并自定义转发内容
onShareTimeline监听右上角菜单“分享到朋友圈”按钮的行为,并自定义分享内容
onResize页面尺寸改变时触发。详见响应显示区域变化
onTabItemTap点击 tab 时触发
onSaveExitState每当小程序可能被销毁之前,页面回调函数会被调用,可以进行退出状态的保存

在小程序中使用flex布局实现一个小demo(引入微信小程序)

目标效果

步骤一:在页面的wxml中使用列表渲染展示数据

<view class="box">
    <view class="box_farg">
        <view class="box_icon">icon</view>
        <text>前端</text>
    </view>
    <view class="box_farg">
        <view class="box_icon">icon</view>
        <text>后端</text>
    </view>
    <view class="box_farg">
        <view class="box_icon">icon</view>
        <text>产品</text>
    </view>
    <view class="box_farg">
        <view class="box_icon">icon</view>
        <text>运维</text>
    </view>
</view>

步骤二:在页面的wxss中使用flex布局给wxml添加样式 

page {
  height: 100vh;
  display: flex;
  flex-direction: column;
}

.box{
    margin-top: 20rpx;
    display: flex;
    justify-self: baseline;
    justify-content: space-around;
}
.box_farg{
    display: flex;
    flex-direction: column;
    text-align: center;
}
.box_icon{
    width: 100rpx;
    height: 100rpx;
    text-align: center;
    line-height: 100rpx;
    border-radius: 50%;
    background-color: lightskyblue;
}

四、WSXL语法

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

数据绑定

  • 数据绑定使用 Mustache 语法(双大括号)将变量包起来
  • 支持组件属性(需要在双引号之内):<view id="item-{{id}}"> </view>
  • 支持控制属性(需要在双引号之内):<view wx:if="{{condition}}"> </view>
  • 支持关键字:<checkbox checked="{{false}}"></checkbox>
  • 支持运算、三元运算、算数运算、逻辑判断、字符串运算、数据路径运算
  • 支持组合,在双大括号内直接进行组合,构成新的对象或者数组:
    <view wx:for="[zero,1,2,3,4]}">{item}</view>
  • setData方法修改数据触发页面更新
    注意:如有存在变量名相同的情况,后边的会覆盖前面

基本用法示例

<!--wxml-->
<view> {{message}} </view>
<view id="item-{{id}}"> </view>
//控制属性
<view wx:if="{{condition}}"> </view>
//关键字
<checkbox checked="{{false}}"> </checkbox>
//三元运算
<view hidden="{{flag ? true : false}}"> Hidden </view>
//算数运算
<view> {{a + b}} + {{c}} + d </view>
//逻辑判断
<view wx:if="{{length > 5}}"> </view>
//字符串运算
<view>{{"hello" + name}}</view>
//数据路径运算
<view>{{object.key}} {{array[0]}}</view>
//组合---数组
<view wx:for="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>
//组合---对象
<template is="objectCombine" data="{{for: a, bar: b}}"></template>

// page.js
Page({
  data: {
    message: 'Hello MINA!',
    id: 0,
    condition: true,
    a: 1,
    b: 2,
    c: 3,
    name: 'MINA',
    object: {
      key: 'Hello '
    },
    array: ['MINA'],
    zero: 0,
    

  },
onLoad:function(){
    // 数据改变 但不触发页面更新
    this.data.name='lisi'
    // setData 数据改变 触发页面更新
    this.setData({
        name:"lisi",
        age:18
    })
}
})

列表渲染

  • 在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件
  • 可以将wx:for用在<block>标签上,以渲染一个包含多节点的结构块

  • 如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如input中的输入内容,switch的选中状态),需要使用wx:key来指定列表中项目的唯一的标识符

  • 当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率
    注意:如不提供wx:key,会报一个warning, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略

注意

  1. 当wx:for的值为字符串时,会将字符串解析成字符串数组
  2. 花括号和引号之间如果有空格,将最终被解析成为字符串

基本示例 

<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>


// page.js
Page({
  data: {
    array: [1, 2, 3, 4, 5]
  }
})

小Demo引入列表渲染 (看不懂可跳过)

目标结果

步骤一:在wxs中定义数据

//wxs(js文件)
Page({
data:{},

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    //   模拟网络数据
    var courseList=[
        {
            img:'../../images/123.png',
            name:"测试"
        },
        {
            img:'../../images/123.png',
            name:"测试"
        },
        {
            img:'../../images/123.png',
            name:"测试"
        },
        {
            img:'../../images/123.png',
            name:"测试"
        },
    ]
    // 将数据获取到data字段中中
    this.setData({
        list:courseList
    })

  },
})

步骤二:使用wx:for将数据列表渲染

//wxml
<view class="box">
    <block wx:for="{{list}}" wx:for-item="course" wx:for-index="idx" >
        <view class="box_item_img">
            <image src="{{course.img}}" />
            <text>{{course.name}}</text>
            <text> {{idx}}</text>
        </view>
    </block>
</view>

步骤三:在wxss中使用flex布局修改样式

//wxss
.box{
    width: 100%;
    height: 400rpx;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    justify-items: normal;
}
.box_item_img{
    display: flex;
    flex-direction: column;
}


.box_item_img image{
    width: 300rpx;
    height: 300rpx;
}

条件渲染(wx:if、wx:else、wx:elif)

  • 在框架中,使用wx:if=" "来判断是否需要渲染该代码块
  • 也可以用wx:elif和wx:else来添加一个 else 块
  • 如果要一次性判断多个组件标签,可以使用一个<block>标签将多个组件包装起来,并在block上使用wx:if控制属性
<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>


// page.js
Page({
  data: {
    view: 'MINA'
  }
})

模版 

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

定义模板

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

</template>

使用模板

//wxml中,is:模版匹配; data: 模版传递数据
<template is="msgItem" data="{{...item}}"/>
//js文件的Page字段中 
 data: {
      item:{
          index:0,
          msg:'this is msg',
          time:'2024-3-11'
      }
  },

 渲染结果展示

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

模版使用案例一:

目标结果展示:

方法一(在内部使用wxs):

<!-- 在wxml中定义wxs -->
<wxs module="info">
    var msg = "hello world";
    var num = function (num1, num2) {
        return num1 + num2;
    }
    module.exports = {
        message: msg,
        add: num
    } 
</wxs>
<!-- 在wxml中使用wxs -->
<view>{{info.message}}</view>
<view>{{info.add(20,10)}}</view>

方法二(在wxml外部定义wxs):

// 在common.wxs中定义
var msg = "hello world";

var num = function (numl, num2) {
    return numl +num2;
}
//commonjs模块化导出
module.exports = {
    message: msg,
    add: num
}
//引入,在其他文件调用,src是定义的wxs的文件路径
<!-- 导入外部的wxs文件并使用 -->
<wxs src="./common.wxs" module="info2"></wxs>
<view>{{info2.message}}</view>
<view>{{info2.add(20,10)}}</view>

模版使用案例二:

目标渲染结果(通过使用外部定义wxs实现一些方法的调用): 

步骤一:创建wxs文件,并定义相关方法 

var message = "hello 你好"

var add  = function(num1,num2){
    return num1+num2
}

// 格式化价格数字
var toFixed = function (value, count) {
    return value.toFixed(count);
}
// 时间戳格式化
var formatNumber = function (n) {
    n = n.toString()
    return n[1] ? n : '0' + n
}
var regYear = getRegExp("(y+)", "i");
var dateFormat = function (timestamp, format) {
    if (!format) {
        format = "yyyy-MM--dd hh:mm:ss";
    }
    timestamp = parseInt(timestamp);
    var realDate = getDate(timestamp);

    function timeFormat(num) {
        return num < 10 ? '0' + num : num;
    }
    var date = [
        ["M+", timeFormat(realDate.getMonth() + 1)],
        ["d+", timeFormat(realDate.getDate())],
        ["h+", timeFormat(realDate.getHours())],
        ["m+", timeFormat(realDate.getMinutes())],
        ["s+", timeFormat(realDate.getSeconds())],
        ["q+", Math.floor((realDate.getMonth() + 3) / 3)],
        ["S+", realDate.getMilliseconds()],
    ];
    var reg1 = regYear.exec(format);
    if (reg1) {
        format = format.replace(reg1[1], (realDate.getFullYear() +
            '').substring(4 - reg1[1].length));
    }
    for (var i = 0; i < date.length; i++) {
        var k = date[i][0];
        var k = date[i][1];
        var reg2 = getRegExp("(" + k + ")").exec(format);
        if (reg2) {
            format = format.replace(reg2[1], reg2[1].length = 1 ? v :
                ("00" + v).substring(("" + v).length));
        }
    }
    return format;
}
module.exports = {
    message:message,
    add:add,
    formatNumber:formatNumber,
    toFixed:toFixed,
    dateFormat:dateFormat
}

步骤二:导入wxs并使用

<!-- 导入wxs -->
<wxs src="./demo3.wxs" module="info" />
<view>{{info.message}}</view>
<view>加法运算</view>
<view>{{info.add(20,10)}}</view>
<view>格式化小数</view>
<view>{{info.toFixed(20.133,3)}}</view>
<view>格式化时间戳</view>
<view>{{info.formatNumber(1566285608000)}} </view>

引用 

WXML 提供两种文件引用方式import和include

  • import可以在该文件中使用目标文件定义的template
  • include可以将目标文件除了<template><wxs>外的整个代码引入,相当于拷贝到include位置

 定义模版

使import导入模版并使用

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

渲染结果展示

注意:import的作用域:只会import目标文件中定义的template,而不会import目标文件import的template,如C import B,B import A,在C中不能使用A定义的template 

使用include导入模板并使用 

结果显示 

五、WXSS语法 

  • WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
  • 为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。

wxss与css相比扩展的特性

尺寸单位

  • rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
@import "common.wxss";

样式导入

  •  使用@import语句可以导入外联样式表,@import后跟需要导入的外联样式表的相对路径,用“;”表示语句结束

@import "common.wxss";

选择器

 全局样式与局部样式

 定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。

六、WXS语法

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

模块

  • 每一个.wxs文件和<wxs>标签都是一个单独的模块。
  • 每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
  • 一个模块要想对外暴露其内部的私有变量与函数,只能通过module实现

示例

var foo = "'hello world' from comm.wxs";
var bar = function(d) {
  return d;
}
//不能简写
module.exports = {
  foo: foo,
  bar: bar
};

注意:该.wxs文件可以被其他的.wxs文件 或 WXML 中的<wxs>标签引用 

module 对象

每个wxs模块均有一个内置的module对象,通过module.exports可以对外共享本模块的私有变量与函数。

module.exports.msg = "some msg";

require函数

在.wxs模块中引用其他wxs文件模块,可以使用require数。

var tools = require("./tools.wxs");

注意

  • 只能引用.wxs文件模块,且必须使用相对路径。
  • wxs模块均为单例,wxs模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个wxs模块对象。
  • 如果一个xs模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

<wxs>标签

示例

//类似与script标签
<wxs module="foo">
var some_msg = "hello world";
module.exports = {
  msg : some_msg,
}

//外部导入
<wxs src="../../wxs/common.wxs" module="info"></wxs>


</wxs>
//支持响应式数据
<view> {{foo.msg}} </view>

注意: 

  • <wxs>模块只能在定义模块的WXML文件中被访问到。使用<include>或<import>时,<wxs>模块不会被引入到对应的WXML文件中。
  • <template>:标签中,只能使用定义该<template>的WXML文件中定义的<wxs>模块。

变量 

  • WXS中的变量均为值的引用。
  • 没有声明的变量直接赋值使用,会被定义为全局变量。
  • 如果只声明变量而不赋值,则默以值为undefined。
  • var表现与javascript-一致,会有变量提升。
var foo = 1;
var bar = "hello world";
var i; // i === undefined

运算符 

 基本运算符

var a = 10, b = 20;
// 加法运算
console.log(30 === a + b);
// 减法运算
console.log(-10 === a - b);
// 乘法运算
console.log(200 === a * b);
// 除法运算
console.log(0.5 === a / b);
// 取余运算
console.log(10 === a % b);
//加法运算(+)也可以用作字符串的拼接
var a = '.w' , b = 'xs';
// 字符串拼接
console.log('.wxs' === a + b);

一元运算符 

var a = 10, b = 20;
// 自增运算
console.log(10 === a++);
console.log(12 === ++a);
// 自减运算
console.log(12 === a--);
console.log(10 === --a);
// 正值运算
console.log(10 === +a);
// 负值运算
console.log(0-10 === -a);
// 否运算
console.log(-11 === ~a);
// 取反运算
console.log(false === !a);
// delete 运算
console.log(true === delete a.fake);
// void 运算
console.log(undefined === void a);
// typeof 运算
console.log("number" === typeof a);

位运算符 

var a = 10, b = 20;

// 左移运算
console.log(80 === (a << 3));
// 带符号右移运算
console.log(2 === (a >> 2));
// 无符号右移运算
console.log(2 === (a >>> 2));
// 与运算
console.log(2 === (a & 3));
// 异或运算
console.log(9 === (a ^ 3));
// 或运算
console.log(11 === (a | 3));

比较运算符 

var a = 10, b = 20;

// 小于
console.log(true === (a < b));
// 大于
console.log(false === (a > b));
// 小于等于
console.log(true === (a <= b));
// 大于等于
console.log(false === (a >= b));

 等值运算符

var a = 10, b = 20;

// 等号
console.log(false === (a == b));
// 非等号
console.log(true === (a != b));
// 全等号
console.log(false === (a === b));
// 非全等号
console.log(true === (a !== b));

 赋值运算符

var a = 10;
a = 10; a *= 10;
console.log(100 === a);
a = 10; a /= 5;
console.log(2 === a);
a = 10; a %= 7;
console.log(3 === a);
a = 10; a += 5;
console.log(15 === a);
a = 10; a -= 11;
console.log(-1 === a);
a = 10; a <<= 10;
console.log(10240 === a);
a = 10; a >>= 2;
console.log(2 === a);
a = 10; a >>>= 2;
console.log(2 === a);
a = 10; a &= 3;
console.log(2 === a);
a = 10; a ^= 3;
console.log(9 === a);
a = 10; a |= 3;
console.log(11 === a);

 二元逻辑运算符

var a = 10, b = 20;
// 逻辑与
console.log(20 === (a && b));
// 逻辑或
console.log(10 === (a || b));

其他运算符 

var a = 10, b = 20;
//条件运算符
console.log(20 === (a >= 10 ? a + 10 : b + 10));
//逗号运算符
console.log(20 === (a, b));

语句

 if 语句

// if ...

if (表达式) 语句;

if (表达式)
  语句;

if (表达式) {
  代码块;
}


// if ... else

if (表达式) 语句;
else 语句;

if (表达式)
  语句;
else
  语句;

if (表达式) {
  代码块;
} else {
  代码块;
}

// if ... else if ... else ...

if (表达式) {
  代码块;
} else if (表达式) {
  代码块;
} else if (表达式) {
  代码块;
} else {
  代码块;
}

 switch 语句

switch (表达式) {
  case 变量:
    语句;
  case 数字:
    语句;
    break;
  case 字符串:
    语句;
  default:
    语句;
}

注意:

  • default 分支可以省略不写
  • case关键词后面只能使用变量,数字,字符串

for 语句

  • 支持break和continue
for (语句; 语句; 语句)
  语句;

for (语句; 语句; 语句) {
  代码块;
}

while 语句 

  • 当代码块为true时,循环执行语句或代码块
  • 支持使用break和continue
while (表达式)
  语句;

while (表达式){
  代码块;
}

do {
  代码块;
} while (表达式)

数据类型 

  • number:数值
  • string:字符串
  • boolean:布尔值
  • object:对象
  • function:函数
  • array: 数组
  • date:日期
  • regexp:正则

number

var a = 10;
var PI = 3.141592653589793;

属性: constructor:返回字符串“Number”

Number方法

方法名

toString
toLocaleString
valueOf
toFixed
toExponential/

 string

var a = 10;
var PI = 3.141592653589793;

属性: constructor:返回字符串“String”

String方法

方法名

toString
valueof
charAt
charCodeAt
concat
indexOf
lastIndexOf
localeCompare

match

replace
search
slice
split
substring
toLowerCase
toLocaleLowerCase
toUpperCase
toLocaleUpperCase
trim

 boolean

  •  布尔值只有两个特定的值:true和false

属性:constructor:返回字符串“Boolean”

Boolean方法
方法名说明
toString转化为字符串
valueOf判断值的类型

object 

  •  object 是一种无序的键值对
var o = {} //生成一个新的空对象

//生成一个新的非空对象
o = {
  'string'  : 1,  //object 的 key 可以是字符串
  const_var : 2,  //object 的 key 也可以是符合变量定义规则的标识符
  func      : {}, //object 的 value 可以是任何类型
};

//对象属性的读操作
console.log(1 === o['string']);
console.log(2 === o.const_var);

//对象属性的写操作
o['string']++;
o['string'] += 10;
o.const_var++;
o.const_var += 10;

//对象属性的读操作
console.log(12 === o['string']);
console.log(13 === o.const_var);

属性:constructor:返回字符串“object”

方法 : 返回字符串“[object object]”

function

//方法 1
function a (x) {
  return x;
}

//方法 2
var b = function (x) {
  return x;
}

//或
var a = function (x) {
  return function () { return x;}
}

var b = a(100);
console.log( 100 === b() );

//function 里面可以使用 arguments 关键词。该关键词目前只支持以下的属性:
//length: 传递给函数的参数个数。
//[index]: 通过 index 下标可以遍历传递给函数的每个参数。
var a = function(){
  console.log(3 === arguments.length);
  console.log(100 === arguments[0]);
  console.log(200 === arguments[1]);
  console.log(300 === arguments[2]);
};
a(100,200,300);

属性

  • constructor:返回字符串“Function”
  • length:返回函数形参的个数

方法

  • toString:返回字符串“[function Function]”

array 

var a = [];      //生成一个新的空数组

a = [1,"2",{},function(){}];  //生成一个新的非空数组,数组元素可以是任何类型

属性:

  •  constructor:返回字符串“Array”
  • length:返回数组元素个数
array方法
方法名
toString
concat
join
pop
push
reverse
shift
slice
sort
splice
unshift
indexOf
lastIndexOf
every
some
forEach
map
filter
reduce
reduceRight

date 

  •    生成date对象需要使用getDate函数            
//参数
//milliseconds: 从1970年1月1日00:00:00 UTC开始计算的毫秒数
//datestring: 日期字符串,其格式为:"month day, year hours:minutes:seconds"
getDate()
getDate(milliseconds)
getDate(datestring)
getDate(year, month[, date[, hours[, minutes[, seconds[, milliseconds]]]]])


//示例代码:
var date = getDate(); //返回当前时间对象
date = getDate(1500000000000);
// Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)
date = getDate('2017-7-14');
// Fri Jul 14 2017 00:00:00 GMT+0800 (中国标准时间)
date = getDate(2017, 6, 14, 10, 40, 0, 0);
// Fri Jul 14 2017 10:40:00 GMT+0800 (中国标准时间)

 属性:constructor:返回字符串“Date” 

date方法
方法名
toString

toDateString

toTimeString
toLocaleString
toLocaleTimeString
valueOf
getTime
getFullYear
getUTCFullYear
getMonth
getDate
getUTCDate
getDay
getUTCDay
getHours
getUTCHours
getMinutes
getUTCMinutes
getSeconds
getUTCSeconds
getMilliseconds
getUTCMilliseconds
getTimezoneOffset
setTime
setMilliseconds
setUTCMilliseconds
setSeconds
setUTCSeconds
setMinutes
setUTCMinutes
setHours
setUTCHours
setDate
setUTCDate
setMonth
setUTCMonth
setFullYear
setUTCFullYear
toUTCString
toISOString
toJSON

regexp

  • 生成regexp对象需要使用getRegExp函数
  • 参数:
    pattern:正则表达式的内容
    flags:修饰符、该字段只能包含一些字符(g:global、i:ignoreCase、m:multiline)
getRegExp(pattern[, flags])

 基本示例

var a = getRegExp("x", "img");
console.log("x" === a.source);
console.log(true === a.global);
console.log(true === a.ignoreCase);
console.log(true === a.multiline);
regexp属性
属性名
constructor
source
global
ignoreCase
multiline
lastIndex
regexp方法
方法名
exec
test
toString

数据类型判断 

  • constructor:判断数据类型

var number = 10;
console.log( "Number" === number.constructor );

var string = "str";
console.log( "String" === string.constructor );

var boolean = true;
console.log( "Boolean" === boolean.constructor );

var object = {};
console.log( "Object" === object.constructor );

var func = function(){};
console.log( "Function" === func.constructor );

var array = [];
console.log( "Array" === array.constructor );

var date = getDate();
console.log( "Date" === date.constructor );

var regexp = getRegExp();
console.log( "RegExp" === regexp.constructor );
  •  typeof:可以区分部分数据类型

var number = 10;
var boolean = true;
var object = {};
var func = function(){};
var array = [];
var date = getDate();
var regexp = getRegExp();
console.log( 'number' === typeof number );
console.log( 'boolean' === typeof boolean );
console.log( 'object' === typeof object );
console.log( 'function' === typeof func );
console.log( 'object' === typeof array );
console.log( 'object' === typeof date );
console.log( 'object' === typeof regexp );
console.log( 'undefined' === typeof undefined );
console.log( 'object' === typeof null );

WXS响应事件 (以官方提供例子为例)

  • WXS 运行在视图层(Webview),里面的逻辑毕竟能做的事件比较少,需要有一个机制和逻辑层(App Service)开发者的代码通信,上面的callMethod是 WXS 里面调用逻辑层(App Service)开发者的代码的方法,而WxsPropObserver是逻辑层(App Service)开发者的代码调用 WXS 逻辑的机制

需求:有频繁用户交互的效果在小程序上表现是比较卡顿的,例如页面有 2 个元素 A 和 B,用户在 A 上做 touchmove 手势,要求 B 也跟随移动。

案例:movable-view(可移动的视图容器,在页面中可以拖拽滑动)

touchmove 事件的响应过程为:

  1. touchmove 事件从视图层(Webview)抛到逻辑层(App Service)
  2. 逻辑层(App Service)处理 touchmove 事件,再通过 setData 来改变 B 的位置

一次 touchmove 的响应需要经过 2 次的逻辑层和渲染层的通信以及一次渲染,通信的耗时比较大。此外 setData 渲染也会阻塞其它脚本执行,导致了整个用户交互的动画过程会有延迟

使用WXS函数用来响应小程序事件 

  •  目前只能响应内置组件的事件,不支持自定义组件事件。WXS 函数的除了纯逻辑的运算,还可以通过封装好的ComponentDescriptor实例来访问以及设置组件的 class 和样式
//在wxs中定义一个事件
var wxsFunction = function(event, ownerInstance) {
    var instance = ownerInstance.selectComponent('.classSelector') // 返回组件的实例
    //设置样式
    instance.setStyle({
        "font-size": "14px" // 支持rpx
    })
    instance.getDataset()
    instance.setClass(className)
    // ...
    return false // 不往上冒泡,相当于调用了同时调用了stopPropagation和preventDefault
}

注意:
event是小程序事件对象基础上多了event.instance来表示触发事件的组件的ComponentDescriptor实例。ownerInstance表示的是触发事件的组件所在的组件的ComponentDescriptor实例,如果触发事件的组件是在页面内的,ownerInstance表示的是页面实例

ComponentDescriptor方法
方法名称参数说明
selectComponentselector对象返回组件的ComponentDescriptor实例
selectAllComponentsselector对象数组返回组件的ComponentDescriptor实例数组
setStyleObject/string设置组件样式,支持rpx。设置的样式优先级比组件wxml里面定义的样式高。不能设置最顶层页面的样式
addClass/removeClass/hasClassstring设置组件的 class。设置的 class 优先级比组件 wxml 里面定义的 class 高。不能设置最顶层页面的 class
getDataset返回当前组件/页面的dataset对象
callMethod(funcName:string, args:object)调用当前组件/页面在逻辑层(App Service)定义的函数。funcName表示函数名称,args表示函数的参数
requestAnimationFrameFunction和原生requestAnimationFrame一样。用于设置动画
getState返回一个object对象,当有局部变量需要存储起来后续使用的时候用这个方法
triggerEvent(eventName, detail)和组件的triggerEvent一致
getComputedStyleArray.<string>参数与SelectQuery的computedStyle一致
setTimeout(Function, Number)与原生setTime一致。用于创建定时器
clearTimeoutNumber与原生clearTimeout一致。用于清除定时器
getBoundingClientRect返回值与与SelectorQuery的boundingClientRect一致

在WXML中定义事件 

<wxs module="test" src="./test.wxs"></wxs>
//change:prop(属性前面带change:前缀)是在 prop 属性被设置的时候触发 WXS 函数,值必须用{{}}括起来。类似 Component 定义的 properties 里面的 observer 属性,在setData({propValue: newValue})调用之后会触发
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view>

注意:WXS函数必须用{{ }}括起来。当 prop 的值被设置 WXS 函数就会触发,而不只是值发生改变,所以在页面初始化的时候会调用一次WxsPropObserver的函数 

定义并导出WXS中的时间处理函数和属性改变触发的函数

module.exports = {
    touchmove: function(event, instance) {
        console.log('log event', JSON.stringify(event))
    },
    propObserver: function(newValue, oldValue, ownerInstance, instance) {
        console.log('prop observer', newValue, oldValue)
    }
}

Tips:

  1. 目前还不支持原生组件的事件、input和textarea组件的 bindinput 事件
  2. 目前在WXS函数里面仅支持console.log方式打日志定位问题,注意连续的重复日志会被过滤掉

七、事件

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

绑定事件与事件交互 

绑定事件

  • 法一:bind+事件名
  • 法二:bind:事件名
//wxml
//绑定了changeDate、tmove、lpress事件,
<button bind:touchstart="changeDate" bindtouchend="tmove" bind:longpress="lpress">改变数据</button>

事件交互 

//wxml
<button bind:touchstart="changeDate" bind:touchend="tmove" bind:longpress="lpress">改变数据</button>


//wxs
Page({
  data:{},
//点击事件
  changeDate:function(){
      this.setData({textStr:"Hello 你好"})
      
  },
//触摸移动
  tmove:function(){
      console.log("touchend");
      //弹窗用于调试
      wx.showToast({
          title: '成功',
          icon: 'success',
          duration: 2000
      })
        
},
//长按触发
lpress:function(){
    console.log("longpress");
    }
})

事件冒泡和捕获 

事件分类

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

  1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
  2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递
冒泡事件列表
事件名称说明
touchstart手指触摸动作开始
touchmove手指触摸后移动
touchcancel手指触摸动作被打断,如来电提醒,弹窗
touchend手指触摸动作结束
tap手指触摸后马上离开
longpress手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发
longtap手指触摸后,超过350ms再离开(推荐使用longpress事件代替)
transitionend会在 WXSS transition 或 wx.createAnimation 动画结束后触发
animationstart会在一个 WXSS animation 动画开始时触发
animationiteration会在一个 WXSS animation 一次迭代结束时触发
animationend会在一个 WXSS animation 动画完成时触发
touchforcechange在支持 3D Touch 的 iPhone 设备,重按时会触发

注意: 除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如from的submit事件,input的input事件,scroll-view的scroll事件这些都是非冒泡事件

绑定并阻止事件冒泡

  • 除bind外,也可以用catch来绑定事件。
  • 与bind不同,catch会阻止事件向上冒泡。
<view id="outer" bindtap="handleTap1">
  outer view
  <view id="middle" catchtap="handleTap2">
    middle view
    <view id="inner" bindtap="handleTap3">
      inner view
    </view>
  </view>
</view>

说明:点击 inner view 会先后调用handleTap3和handleTap2(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2,点击 outer view 会触发handleTap1。 

互斥事件绑定 

  • 除bind和catch外,还可以使用mut-bind来绑定事件
  • 一个mut-bind触发后,如果事件冒泡到其他节点上,其他节点上的mut-bind绑定函数不会被触发,但bind绑定函数和catch绑定函数依旧会被触发。即所有mut-bind是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响bind和catch的绑定效果
<view id="outer" mut-bind:tap="handleTap1">
  outer view
  <view id="middle" bindtap="handleTap2">
    middle view
    <view id="inner" mut-bind:tap="handleTap3">
      inner view
    </view>
  </view>
</view>

说明:点击 inner view 会先后调用handleTap3和handleTap2,点击 middle view 会调用handleTap2和 handleTap1。

 事件的捕获阶段

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

示例:

正常捕获冒泡:

<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
  outer view
  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
  </view>
</view>

说明:在下面的代码中,点击 inner view 会先后调用handleTap2、handleTap4、handleTap3、handleTap1

中断捕获阶段和取消冒泡阶段:

<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
  outer view
  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
  </view>
</view>

说明: 将正常捕获冒泡代码中的第一个capture-bind改为capture-catch,将只触发handleTap2。

事件对象 

 八、微信小程序组件

组件这块,只写一些基本组件,一些其他的组件可以直接查阅微信小程序组件文档(太多了参数属性了,手写个人感觉不全面,所以请大家自行查阅官方文档)

基本组件

 icon(图标组件) 

属性说明

属性说明
typeicon的类型,有效值:success, success_no_circle, info, warn, waiting, cancel, download, search, clea
sizeicon的大小,默认大小为23,单位默认为px
coloricon的颜色,同css的color
<icon type="warn" size="100rpx" color="red"/>

progress (进度条组件)

  • 进度条。组件属性的长度单位默认为px
<progress percent="30" show-info="true" border-radius="10" stroke-width="50rpx" activeColor="red" backgroundColor="#000" active="true"></progress>

 属性说明:

属性类型说明
percentnumber百分比0~100
show-infoboolean在进度条右侧显示百分比,默认false
border-radiusnumber/string圆角大小,默认0
font-sizenumber/string右侧百分比字体大小,默认16
stroke-widthnumber/string进度条线的宽度,默认6
colorstring进度条颜色(请使用activeColor),默认#09BB07
activeColorstring已选择的进度条的颜色,默认#09BB07,默认#EBEBEB
backgroundColorstring未选择的进度条的颜色,默认false
activeboolean进度条从左往右的动画,默认backwards
active-modestringbackwards: 动画从头播;forwards:动画从上次结束点接着播
durationnumber进度增加1%所需毫秒数,默认30
bindactiveendeventhandle动画完成事件

渲染展示 :

rich-text(渲染html内容组件)

  • 作用:富文本解析展示
属性说明
nodes节点列表/HTML String
space显示连续空格
user-select文本是否可选,该属性会使节点显示为block

nodes属性说明 

  • nodes支持两种节点,通过type区分
type=node
属性说明
name标签名
attrs属性
children子节点列表
type=text
属性说明
text文本

 text(文本组件)

  • 该属性会使文本节点显示为 inline-block
属性说明
user-select文本是否可选,该属性会使文本节点显示为inline-block

表单常用组件

组件说明

组件名称说明
button按钮
checkbox-group多项选择器,内部由多个checkbox组成
checkbox多选项目,放在checkbox-group内部
editor富文本编辑器
form表单
input输入框
label改进表单组件的可用性
radio单选框(由radio-group包裹)
radio-group单选框组(里面嵌套多个radio)
textarea多行文本输入框
keyboard-accessory设置 input / textarea 聚焦时键盘上方 cover-view / cover-image 工具栏视图
picker从底部弹起的滚动选择器
picker-view嵌入页面的滚动选择器。其中只可放置picker-view-column​​组件,其它节点不会显示
picker-view-column滚动选择器子项。仅可放置于picker-view中,其孩子节点的高度会自动设置成与picker-view的选中框的高度一致
slider滑动选择器
switch开关选择器

表单组件提交获取信息案例

  • 结果展示(当点击提交时可在控制台输出表单收集到的数据)

  • 实现代码
//wxml
<!-- 表单 -->
<!-- bindreset:重置触发的事件 -->
<form bindsubmit="handleSubmit" bindreset="handelReset">
    <view>
        <text>name:</text>
        <input type="text" name="" id="" placeholder="请输入姓名" bind:blur="handleBlur" />
    </view>
    <view>
        <text>age:</text>
        <input type="text" name="" id="" placeholder="请输入年龄" bind:blur="handleBlurAge" />
    </view>
    <!-- bindchange:用于收集radio-group数据 -->
    <radio-group bindchange="handlechange">
        <label for="boy">
            <radio value="boy" />男
        </label>
        <label for="girl">
            <radio value="girl" />女
        </label>
        <label for="unKown">
            <radio value="unKown" checked />保密
        </label>

    </radio-group>
    <checkbox-group bindchange="handlechangeMajor">
        <label for="">
            <checkbox value="vue" checked />Vue
            <checkbox value="react" checked />React
            <checkbox value="app" />App
        </label>
        <!-- 文本输入 -->
            <text>description:</text>
            <textarea value="" placeholder="请输入您的信息" bind:blur="handleBlurDesc" />
    </checkbox-group>

    <view style="margin: 20rpx;">
        <button form-type="submit">提交</button>
        <button form-type="reset">重置</button>
    </view>

</form>
//js,wxss
Page({

  /**
   * 页面的初始数据
   */
  data: {
      name:"",
      gerder:"",
      Major:[],
      desc:" "



  },
//   e为事件对象
  handleBlur:function(e){
      this.setData({
          name:e.detail.value
      })
  },
  handleBlurAge:function(e){
      this.setData({
          age:e.detail.value
      })
  },
  handleSubmit(){
      console.log(this.data);
  },
  handelReset(e){
    console.log(e);
  },
  handlechange(e){
      this.setData({gerder:e.detail.value})
  },
  handlechangeMajor(e){
      this.setData({Major:e.detail.value})
  },
  handleBlurDesc(e){
    console.log(e.detail.value);
    this.setData({
        desc:e.detail.value
    })
  },


})

视图容器

组件说明

组件名称说明

swiper

滑块视图容器。其中只可放置swiper-item组件,否则会导致未定义的行为。
swiper-item仅可放置在swiper组件中,宽高自动设置为100%

scroll-view

可滚动视图区域

cover-image

覆盖在原生组件之上的图片视图

cover-view

覆盖在原生组件之上的文本视图

match-media

media query 匹配检测节点。可以指定一组 media query 规则,满足时,这个节点才会被展示

movable-area

movable-view的可移动区域

movable-view

可移动的视图容器,在页面中可以拖拽滑动。movable-view必须在movable-area组件中,并且必须是直接子节点,否则不能移动

page-container

页面容器

root-portal

使整个子树从页面中脱离出来,类似于在 CSS 中使用 fixed position 的效果。主要用于制作弹窗、弹出层等

view

视图容器

轮播图案例(通过案例学习swiper相关属性)

  • 目标结果(图片实现自动轮播,且可以通过属性切换横向和纵向)

  • 代码实现及说明
//wxml
<!-- autoplay:是否自动播放,interval:滑动的间隔时间, duration:每次滑动的时间,indicator-dots:显示图片圆点预览,indicator-active-color:圆点的颜色,vertical:纵向滑动,circular:单向循环滑动,vertical circular display-multiple-items:一个界面显示图片的数量 -->
<swiper autoplay interval="500" duration="1000" indicator-dots indicator-active-color="#007aff" vertical circular display-multiple-items="2">
    <swiper-item wx:for="{{images}}" wx:for-index="dbs"> 
        <image src="{{item}}" mode=""/>
    </swiper-item>
</swiper>
//js,wxss
Page({
  data: {
    images:[ '../../images/123.png','../../images/21212121.png','../../images/123.png']

  },
})

注意:这里data里的images中是图片的地址,需要换成自己的图片地址

可滚动视图案例

  • 目标结果(在指定区域内可滚动图片,且点击按钮回到指定页面)

  • 代码实现
//wxml
<!-- scroll-view:可滚动视图 -->
<!-- 横向滑动 -->
<!-- <scroll-view scroll-x="{{true}}" 
style="display: flex;white-space: nowrap;"> 
    <block wx:for="{{imgs}}">
        <image src="{{item}}" alt=""/>
    </block>
</scroll-view> -->


//案例为模式二,横向滑动可作为学习参考
<!-- 模式二:在某个范围内滑动 -->
<!-- bindscrolltoupper:滑动到顶部触发的事件 -->
<!-- indscrolltolower:滑动到底部触发的事件 -->
<!-- scroll-into-view: 值应为某子元素id(id不能以数字开头)。设置哪个方向可滚动,则在哪个方向滚动到该元素 -->
<scroll-view scroll-y="{{true}}" 
scroll-top="200" style="height: 800rpx;"
bindscrolltoupper="upper"
bindscrolltolower="lower"
scroll-into-view="{{toView}}"> 
    <block wx:for="{{imgs}}">
        <image src="{{item}}" id="{{'img'+index}}"/>
    </block>
</scroll-view>

<button bind:tap="gotoview">回到顶部</button>
//js,wxss
Page({

    /**
     * 页面的初始数据
     */
    data: {
        imgs: [
            '/images/123.png',
            '/images/QQ图片20230223182711.jpg',
            '/images/QQ图片20230223182711.jpg',
            '/images/QQ图片20230223182711.jpg',
            '/images/QQ图片20230223182711.jpg',
        ],
        toView:'img1'

    },
    upper(){
        console.log("upper");
    },
    lower(){
        console.log("lower");
    },
    gotoview(){
        this.setData({
            toView:"img1"
        })

    },
})

注意:这里data里的imgs为图片地址,需要自行修改成自己图片的地址 

横向滚动视图案例

  • 目标结果(可实现标题栏的横向滑动,且自动将选中的标题居中显示)

  • 代码实现
//wxml
<!-- data-c:data-后面跟数据属性名,可通过事件对象获取 -->
<scroll-view scroll-x="{{true}}" class="nav" scroll-left="{{navScrollLeft}}">
    <block wx:for="{{navData}}" wx:key="index">
        <view class="nav_item {{currentNav==index?'active':''}}" bind:tap="switchNav" data-c="{{index}}">{{item.text}}</view>
    </block>

</scroll-view>
//wxss
Page({
  data: {
    navData:[
        {
            text:"首页"
        },
        {
            text:"商品"
        },
        {
            text:"地址"
        },
        {
            text:"配送"
        },
        {
            text:"GO"
        },
        {
            text:"我的"
        },
    ],
    currentNav:0,
    navScrollLeft:0
  },
  switchNav(e){
      let singleWitdh = this.data.windowWidth /5
    this.setData({
        currentNav:e.currentTarget.dataset.c,
        navScrollLeft:(e.currentTarget.dataset.c-2)*singleWitdh
    })
  },
  onLoad(options) {
    //   获取系统信息
      wx.getSystemInfo({
          success:(res)=>{
            //   获取设备宽度
            //   console.log(res.windowWidth);
              this.setData({
                  windowWidth:res.windowWidth
              })
          }
      })

  },

})

媒体组件

组件说明

组件名称说明
audio音频
camera系统相机
channel-live小程序内嵌视频号直播组件,展示视频号直播状态和封面,并无弹窗跳转至视频号
channel-video小程序内嵌视频号视频组件,支持在小程序中播放视频号视频,并无弹窗跳转至视频号
image图片。支持 JPG、PNG、SVG、WEBP、GIF 等格式
live-player实时音视频播放
live-pusher实时音视频录制

video

视频
voip-room多人音视频对话

媒体组件案例---音频组件

  • 目标结果(显示音频名称,作者,可以点击播放)

  • 实现代码
//wxml
<!-- controls:播放器的控制台,name:歌曲名称,author:歌曲作者,poster:音乐封面图片 -->
<audio src="{{audio.audiosrc}}" poster="{{audio.Imageposter}}" controls="{{true}}"
 name="{{audio.name}}" author="{{audio.author}}" ></audio>
//js,wxss
Page({

    /**
     * 页面的初始数据
     */
    data: {
        audio: {
            name: "飞-致我们的星辰大海",
            Imageposter: 'https://y.qq.com/music/photo_new/T002R300x300M000004fwlJg0Yug9n_2.jpg?max_age=2592000',
            author: "璨乐团",
            audiosrc: "/audio/璨乐团 - 飞-致我们的星辰大海.mp3"
        },
    }
})

媒体组件案例---视频组件 

画图组件

组件说明

组件名称说明
canvas画布

画图组件案例

  • 目标结果(在画布中显示两个方块)

  • 代码实现
//wxml
<view class="container">
<!-- 注意画布的长宽比尽量是1:1才能正常使用 -->
<!-- type的值可以是2d,也可以是3d,id用于给js文件获取画布 -->
    <canvas type="2d" id="mycanvas" class="canvas_container" />
</view>
//js,wxss
Page({
  data: {

  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {
    //创建画布
      wx.createSelectorQuery()
    //   获取画布的id
      .select('#mycanvas')
    //   设置节点,大小
      .fields({
          node:true,
          size:true
      })
    //   设置画布
      .exec((res)=>{
          console.log(res[0]);
          console.log(res[0].node);
        //   获取画布的节点
          const canvas = res[0].node
          const ctx = canvas.getContext('2d')
          const width = res[0].width
          const height = res[0].height
        //   清空画布
          ctx.clearRect(0,0,width,height)


        //   画个图
          ctx.fillStyle = 'rgb(200,0,0)'
          ctx.fillRect(10,10,50,50)


          ctx.fillStyle = 'rgb(0,0,200,0.5)'
          ctx.fillRect(30,30,50,50)
      })

  },

})

其他组件

导航组件
标签名称说明
functional-page-navigator仅在插件中有效,用于跳转到插件功能页
navigator页面链接
地图组件
标签名称说明
mapmap组件提供了地图展示、交互、叠加点线面及文字等功能,同时支持个性化地图样式,可结合地图服务 API 实现更丰富功能

九、自定义组件间及其配置

自定义组件

  • 在全局下创键compontents文件夹,在里面新建component作为组件,并在wxml里输入组件内容

  • 在要使用组件的页面的json中配置组件

  •  在page的wxml中按照注册的组件名导入组件

  • 效果 

  • 如果是全局组件就可以在app.json中定义组件

父组件向子组件传递数据 

插槽

  • 默认插槽
//默认插槽
<mycom>
    <!-- 插槽:默认插槽直接在组件标签内部写内容 -->
    1234344
</mycom>


//使用插槽
//mycom组件的wxml文件里使用
<view>
    <!-- 插槽:默认 -->
    <!-- <slot></slot> -->
</view>
  • 多个插槽
//使用多个插槽,
<mycom>
    <!-- 插槽 -->
    1234344
    <!-- 使用多个插槽 -->
    <view slot="slot1">slot1 123</view>
    <view slot="slot1">slot2 456</view>
</mycom>

//多个插槽需要在自定义组件中的js文件进行配置
Component({
  /**
   * 组件的属性列表
   */
  options:{
        multipleSlots:true
  }
})

//在mycom组件的wxml中使用多个插槽
<view>
    <!-- 插槽:默认 -->
    <!-- <slot></slot> -->
    <!-- 多个插槽 -->
    <slot name="slot1"></slot>
    <slot name="slot2"></slot>

</view>

注意:多个插槽是根据name标签来区分内容的 

组件样式隔离、共享

//组件的js文件
Component({

  /**
   * 组件的属性列表
   */
  options:{
        multipleSlots:true,
        // styleIsolation:"isolated"   //页面 和 组件的样式隔离
        // styleIsolation:"shared"     //页面 和 组件的样式共享
        // styleIsolation:"apply-shared"  //页面的样式传给组件,且组件可以保留自己的样式
  }
})

组件间传递值和样式

  •  传递值
//在父组件中向子组件传递title值
<mycom dataA="{{title}}"></mycom>
//父组件js文件
  data: {
      title:"页面的传递的title"

  },

//子组件接收父组件传过来的值并设置默认值
  properties: {
      dataA:{
          type:String,
            //当父组件没有传递值的时候子组件wxml获取到的就是这个默认值
          value:"默认标题"
      }

  },
//在子组件的wxml中使用title值
<text>{{dataA}}</text>
  • 传递样式
//在父组件中传递样式
<mycom my-class="red"></mycom>
//父组件wxss
.red{
    color:red;
}


//在子组件js文件获取从父组件传递过来的样式
externalClasses:['my-class'],
//在子组件wxml中使用传递过来的样式
<view class="my-class"></view> 

组件事件的传递

//父组件wxml使用子组件
<view><com_demo2 bind:search="search"></com_demo2></view>
//父组件js文件定义事件
  search(){
    console.log("search");
  },


//子组件wxml的事件
<input type="text" placeholder="search" bind:confirm="getSearchText"/>
//子组件js文件
  methods: {
    getSearchText(e){
        console.log(e.detail.value);
        //在子组件中调用了父组件的方法
        this.triggerEvent("search")
      },

  }

父组件获取子组件数据及方法

通过id获取子组件中的数据和方法(selectComponent)

//父组件的wxml
<view class="container">
    <button bind:tap="count">计数</button>
    <compontents12 id="mycount"></compontents12>
</view>

//子组件的wxml
<view>
    <text>{{count}}</text>
</view>


//子组件的js文件
  data: {
    count:1

  },
  methods: {
    innercount:function(){
        this.setData({
            count:this.data.count+1
        })
    },

  },


//父组件获取子组件的data数据和methods方法
  count:function(e){
      console.log(this.selectComponent("#mycount").data); //获取子组件中的data数据
      this.selectComponent("#mycount").innercount()   //调用子组件中的方法
    
  },

组件的生命周期 

定义组件生命周期

//组件的js文件
Component({
  lifetimes: {
    attached: function() {
      // 在组件实例进入页面节点树时执行
    },
    detached: function() {
      // 在组件实例被从页面节点树移除时执行
    },
  },
  // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  attached: function() {
    // 在组件实例进入页面节点树时执行
  },
  detached: function() {
    // 在组件实例被从页面节点树移除时执行
  },

})
组件生命周期
生命周期说明
created在组件实例刚刚被创建时执行
attached在组件实例进入页面节点树时执行
ready在组件在视图层布局完成后执行
moved在组件实例被移动到节点树另一个位置时执行
detached在组件实例被从页面节点树移除时执行
error每当组件方法抛出错误时执行

定义组件所在页面的生命周期

Component({
  pageLifetimes: {
    show: function() {
      // 页面被展示
    },
    hide: function() {
      // 页面被隐藏
    },
    resize: function(size) {
      // 页面尺寸变化
    }
  }
})
组件所在页面生命周期
生命周期说明
show组件所在的页面被展示时执行
hide组件所在的页面被隐藏时执行
resize组件所在的页面尺寸变化时执行
routeDone组件所在页面路由动画完成时执行

组件属性监听

单个监听(observer)

  • 在子组件接收父组件传递的数据的时候进行监听,可以监听到数据新值和旧值还有传数据的名称
    properties: {
        count1: {
            type: Number,
            value: 0,
            observer: function (newvalue, oldvalue, change) {
                console.log(newvalue, oldvalue, change);
            }
        },

    },

多个监听(observers)

//子组件js文件 
observers:{
        // 同时监听两个数据
        "count1,count2":function(n1,n2){
            // 监听数据的新值
            console.log(n1,n2);
            this.setData({
                sum:n1+n2
            })
        }
    },

组件案例

目标结果:page tag为父组件,抽离tab栏为子组件,使得点击tab栏标题传递到父组件使得page tag显示点击的那个标题

步骤一:创建page页面及子组件

 文件结构:

compontents
        |——demo1-com(子组件)
        |
   pages
        |
        |——demo1(父页面)

//demo1.json
{
  "usingComponents": {
       //引入子组件
      "compontents":"/compontents/demo1-com/demo1-com"
  }
}

步骤二:完成基本架构

//demo1.wxml
<view>
    //定义标题
    <view>page tag:{{tag}}</view>
    //使用子组件,并将父组件中的tabs传入子组件中遍历
    <compontents tabs="{{tabs}}"></compontents>
</view>

//demo1.js
//定义数据
  data: {
      tag:"",
      tabs:["推荐","体育","新闻","媒体"],

  },

//demo1-com.wxml
<view class="tab-box">
    <block wx:for="{{tabs}}" wx:key="index">
        <view class="tab-item"><text>{{item}}</text></view>
    </block>
</view>

//demo1-com.js
   //定义选中标题的索引
  data: {
    currindex:0,

  },

步骤三:在父页面完成相关css样式,并传入子组件 

//demo1.wxss
//在父页面定义css样式
//盒子样式
.tab-box{
    display: flex;
    height: 100rpx;
    line-height: 100rpx;
    background-color: lightgray;
}
//盒子样式
.tab-item{
    flex: 1;
    text-align: center;
}
//点击时的样式
.active{
    color: red;
}
//在demo1.wxml中向子组件传入样式
<view>
    <view>page tag:{{tag}}</view>
    <compontents tabs="{{tabs}}" tab-box="tab-box"  tab-item="tab-item" active="active"></compontents>
</view>


//在子组件中接收样式
//demo1-com.js
externalClasses:["tab-box","tab-item","active"],

步骤四:定义点击事件,实现点击标题css样式切换

//demo1-com.wxml
<view class="tab-box">
    <block wx:for="{{tabs}}" wx:key="index">
        //使用"data-"定义index数据,并定义一个名称叫clickchange的点击事件
        //在class中使用三元判断是否触发选中的Css样式
        <view class="tab-item {{currindex==index?'active':''}}" data-index="{{index}}" bind:tap="clickchange"><text>{{item}}</text></view>
    </block>
</view>

//dem1-com.js
//
methods: {
    clickchange:function(e){
        this.setData({
            //通过event事件参数获取定义的index值并赋给data中的currindex
            currindex:e.currentTarget.dataset.index
        })
    }

  }

步骤五:将触发点击事件的标题的索引传递给父页面获取显示,这是第一种方法

//demo1.js
//在父页面定义事件
tagClick:function(e){
  
  },


//demo1.wxml
<view>
    <view>page tag:{{tag}}</view>
    //将定义的事件传递给子组件
    <compontents bind:tagClick="tagClick" tab-box=" tab-box"  tab-item="tab-item" active="active" tabs="{{tabs}}"></compontents>
</view>


//demo1-com.js
methods: {
    clickchange:function(e){
        this.setData({
            currindex:e.currentTarget.dataset.index
        })
        //调用父页面传到子组件的事件,并将点击标题的索引以index为键传递给父页面
        this.triggerEvent('tagClick',{
            index:this.data.currindex
        })
    }

  }
//demo1.js
//使用在父页面中定义的事件获取子组件返回来的index下标并在tabs中选取值赋给tag从而显示到页面
tagClick:function(e){
      console.log(e);
    this.setData({
        tag:this.data.tabs[e.detail.index]
    })

第二种方法类似,只是在子组件中就通过索引获取到点击的标题再传给父页面显示

十、微信小程序API 

页面跳转

  • 法一:使用navigator

页面跳转
<navigator url="要跳转到的页面地址">页面跳转</navigator>
//返回上一个页面
<navigator open-type="navigateBack">返回上一个页面</navigator>
获取参数
//页面跳转时发送一个get请求的地址
<navigator url="../demo10/demo10?id=1&name=jack">页面跳转</navigator>


//获取get请求的参数(在跳转后的页面的js文件的监听页面加载的生命周期函数中获取参数)
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
//获取参数
      console.log(options);

  },
  • 法二: 使用wx内置API(wx.navigateTo)

页面跳转 

//在wxml中定义一个点击事件
<text bind:tap="gosort">sort page</text>
  gosort:function(){
      wx.navigateTo({
        //定义跳转的页面地址
        url: '/pages/demo1/demo1',
        //成功后执行的函数
        success:function(){
            console.log("sucess");
        }
      })
  },

页面返回

//wxml 定义一个点击事件 
<view class="box_bottom"><button bind:tap="goback">返回</button></view>

//定义一个返回的参数
goback(){
        // 增量2(一次返回2层)
        wx.navigateBack({
            delta:2
        })
    }

页面重定向

  • 跳转后销毁当前页面
//在wxml定义点击事件
<text bind:tap="redirect">页面重定向</text>
//js
  redirect:function(){
    //重定向
      wx.redirectTo({
        url: '../demo10/demo10',
      })

  },

底部标签

  • 底部标签显示及跳转
//在app.json中配置
"tabBar": {
      "list": [
        {
        "pagePath":"pages/index/index",
        "text":"首页"},
        {
        "pagePath":"pages/demo3/demo3",
        "text":"分类"},
        {
        "pagePath":"pages/demo9/demo9",
        "text":"个人"}
      ]
  },
  • 返回指定Tab页面
  wx.switchTab({
          url: '../demo2/demo2',
        })

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WDEP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值