微信小程序

简介

  • 小程序的大小限制在 2MB 以内

开发前的准备

首先要注册个微信开发者工具,来这个网站
https://mp.weixin.qq.com/wxopen/waregister?action=step1
我用邮箱注册的(我新建的网易 163 邮箱)

小程序 ID

注册完之后请把你的 ID 记住了

在这里插入图片描述

在这里插入图片描述


下载开发者工具

开发者平台地址。
根据你自己的操作平台来下载,我的是 Win10


新建工程

安装完开发者工具之后,打开它
在这里插入图片描述


编译界面简介

在这里插入图片描述


WXML 的基本开发

创建新的页面

  • 我们点开 app.json 文件,在 "pages" 这个数组中添加新的语句,我填的是 "pages/demo1/demo1",,这句话就是声明一个名为 demo1 的新页面,然后按下Ctrl + S,保存好之后在左侧的 pages 文件夹中自动生成 demo1 文件夹
  • 注意 pages 这里谁写在第一位,那么在开启小程序的时候就会展示这一页,你可以想象成主页。
    在这里插入图片描述
    在这个文件夹中自动生成四个文件,其中的 .wxml 就类似 .html.wxss 就类似 .css,我说的类似是他们功能是相似的,但是里面的语法,及标签的使用还是有些许区别的
    在这里插入图片描述

创建 tabBar

简单操作

首先 tabBar 是个啥呢?就是你打开微信,下面的四个切换栏

app.json 文件中

1
2
3
4
5
6
7
8
9
10
11
12
"tabBar":{
"list":[
{
"pagePath":"pages/demo1/demo1",
"text":"demo1"
},
{
"pagePath": "pages/index/index",
"text": "index"
}
]
},

注意

  • 对象中最后一项语句的末尾,是不可以有逗号的,比方说这个 "text":"demo1",他是对象中最后一个键值对,它的最后面不可以加逗号的,也就是写成 "text":"demo1",
1
2
3
4
{
"pagePath":"pages/demo1/demo1",
"text":"demo1"
}
  • 颜色的表示方法,很多都是 十六

具体添加方法如下
在这里插入图片描述

添加 tabBar 的图标

微信官方给的要求:
icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。

首先来这个网站 https://www.iconfont.cn/ 搜索你想要的图标,比方我要微信上的 Chats 图标
在这里插入图片描述

  • iconPath 这个属性是选项卡没有选中时的图片,通常为灰色
  • selectedIconPath 选项卡选中时的图片,微信是绿色的,这两个图片我们都要设置

在这里插入图片描述


页面的编写

  • 新的标签名字 view 类似原先的 div

以下是水平的滑动,演示如下
在这里插入图片描述
代码如下

1
2
3
4
5
6
7
8
9
10
11
<!--pages/demo2/demo2.wxml-->
<scroll-view id="scroll" scroll-x="true">
<view class="flex">
<view class="item item1">1</view>
<view class="item item2">2</view>
<view class="item item3">3</view>
<view class="item item4">4</view>
<view class="item item5">5</view>
<view class="item item6">6</view>
</view>
</scroll-view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/* pages/demo1/demo1.wxss */
#scroll {
width: 750rpx;
height: 100px;
box-sizing: border-box;
border: 1px salmon solid;
}
.flex {
display: flex;
width: 1300px;
justify-content: space-between;
}
.item {
height: 100px;
width: 200px;
}
.item1 {
background-color: gold;
}
.item2 {
background-color: rgb(34, 148, 11);
}
.item3 {
background-color: rgb(223, 123, 84);
}
.item4 {
background-color: rgb(165, 45, 95);
}
.item5 {
background-color: rgb(87, 37, 204);
}
.item6 {
background-color: rgb(151, 102, 123);
}

轮播图

轮播图 <swiper> 需要配合 <swiper-item> 来一起使用

1
2
3
4
<swiper>
<swiper-item>1</swiper-item>
<swiper-item>2</swiper-item>
</swiper>

https://developers.weixin.qq.com/miniprogram/dev/component/swiper.html
这是官方给的轮播图的属性

其他

常用的标签在官网上都有说明,需要的话自行查找


生命周期

页面生命周期

组建的生命周期

组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发。

其中,最重要的生命周期是 created attached detached ,包含一个组件实例生命流程的最主要时间点。

  • 组件实例刚刚被创建好时, created 生命周期被触发。此时,组件数据 this.data 就是在 Component 构造器中定义的数据 data 。 此时还不能调用 setData 。 通常情况下,这个生命周期只应该用于给组件 this 添加一些自定义属性字段。
  • 在组件完全初始化完毕、进入页面节点树后, attached 生命周期被触发。此时, this.data 已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。
  • 在组件离开页面节点树后, detached 生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则 detached 会被触发。

JS

简介

小程序中是没有 dom 的,依赖于 数据的绑定

定义、引用变量(数据绑定)

目前我们需要把变量声明到 xx.js 文件中的 data 里,放在这里的变量可以用在 wxml
在这里插入图片描述
data 里是对象,里面放 "key":"value",我在里面放了个

1
2
3
data: {
flag:"true"
},

如何在 wxml 页面引用变量?
{{变量名}} 两个花括号

1
<text>{{flag}}</text>

这样引用变量既可以当属性名,也可以用来做属性值
在这里插入图片描述

条件

微信小程序中的条件是 wx:if

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

循环

通过 wx:for="{{arr}}" 来声明循环那个对象,{{要循环的对象}},通过 wx:item="item" 来声明对象中每个元素叫啥,这里取名叫 item ,取名任意,你想改就改

1
<view wx:for="{{arr}}" wx:item="item"> {{item}} </view>

更新数据

更新数据需要用到 setData,这里更新完的数据会传递到页面中供其使用
刚开始我们需要 let that = this; 使指针指向对象,这个对象是 page 里的那个对象,就是下面动画里选中的这一大坨
在这里插入图片描述

1
2
3
4
5
let that = this;
that.setData({
//这里填你想要修改的值
key: "value",
});

这个 key 值如果有变量的话就要在外部拼接好,然后在这里用解构,比方说下面的例子

1
2
3
4
var key = `arr[${choiseIndex}].boolean`; //这里的key有变量choiseIndex,在外部拼接好了
that.setData({
[key]: false, //这里不能直接写key,要用中括号解构好变量,像这样:[key]
});

点击变色(1)

问题描述:我点击 li,这个 li 就变色,在点击另一个 li,另一个 li 变色,上一个 li 就恢复原来的颜色,只能存在一个 li 是变色的
演示如下
在这里插入图片描述

解决思路:

  • 首先小程序里没有 Dom 节点,只能通过数据绑定了
  • 那么我们可以通过切换每个标签的类名,实现样式的改变
  • 我给每一个标签加上索引,判断 点击的索引 == 标签的索引,如果是,就给他加样式,如果不是就不用管它

抛出问题:

  • 如何给标签加属性索引?
  • 如何在 js 中找到点击的是哪一个?

解决问题:

  • 我用 data-xxx ,把他写在标签里,相当于给标签加上了新的属性,写它的好处在于你能在 js 文件中通过事件因子 e 找到你点击的是哪一个在这里插入图片描述
  • 我们可以通过事件因子中的 e.currentTarget.dataset 这里找到我们在标签里写的属性。
    在这里插入图片描述

注意:

  • that.setData({})只有在这里修改 data 里的数据,才会把更改后的新数据传到页面中,你在他外面修改 data 的数据值,是不会传递到页面中去的

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//js
//上面的Page没有写,函数是写在page里的
data: {
arr:["a","b","c","d"],
tapIndex:-1
},

changeCol(e){
var that = this;
var tapIndex = e.currentTarget.dataset.index;
that.setData({
tapIndex: tapIndex
})
},
1
2
3
4
5
6
7
8
9
/*wxml*/
<text>点击那个那个变色,只有一个变色</text>
<view
wx:for="{{arr}}"
data-index="{{index}}"
bindtap="changeCol"
class="color{{tapIndex == index ? 'Select':'Normal'}}"
>{{item}}</view
>
1
2
3
4
5
6
.colorNormal {
color: black;
}
.colorSelect {
color: red;
}

点击变色(2)

问题描述
击那个就切换颜色,再次点击取消颜色
演示如下
在这里插入图片描述

解决思路

  • 给每一个 li 添加一个状态,这种状态记录着它是否被点击过,因为我们循环的数据,那么我们暂且把这种状态加到数据里
1
2
3
4
5
6
7
8
9
//我的这组数据中 num 就是记录这种状态,默认 -1 为未点击状态
data: {
arr: [
{ data: "第1", num: -1 },
{ data: "第2", num: -1 },
{ data: "第3", num: -1 },
{ data: "第4", num: -1 },
],
},
  • 我还是通过 data-num="{{index}}" 来寻找点的是哪一个标签
  • 重点!!!: 我们在用 setData 来更新 data 里的数据的时候,对象里的 key 值一定是个字符串
1
2
3
4
//错误1: key值为变量,arr[index].num 是不会被解析的
that.setData({
arr[index].num : 1
})
1
2
3
4
5
6
7
//错误2: key值为变量,result 里是有 index 的,
//index 也是变量不是字符串,照样是不会被解析的
var result = "arr[" + index + "].num";
that.setData({
result: 1,
//等价于 "arr[" + index + "].num" : 1
});
1
2
3
4
5
//正确示范:加上中括号,里面的变量就可以解析了(es6)
var result = "arr[" + index + "].num";
that.setData({
[result]: 1,
});

我们可以这样测试一下

1
2
3
4
5
6
7
8
9
var index = 1;
var result = "arr[" + index + "].num";
var obj = {
[result]: 1,
};
console.log(obj); // {arr[1].num: 1}
// 如果不加括号的话 直接是{result: 1}了,就不会解析里面的变量
// 因为对象的key 值是自动toString的
// 需要通过中括号结构解析

完整代码

1
2
3
4
5
6
<!--页面.wxml-->
<text>点击那个就切换颜色,再次点击取消,跟电影院选位置一样 </text>
<view wx:for="{{arr}}" data-num="{{index}}" bindtap="changeCol">
<view wx:if="{{item.num != -1}}" class="colorSelect"> {{item.data}} </view>
<view wx:else class="colorNormal"> {{item.data}} </view>
</view>
1
2
3
4
5
6
7
/* 样式.wxss */
.colorNormal {
color: black;
}
.colorSelect {
color: red;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
data: {
arr: [
{ data: "第1", num: -1 },
{ data: "第2", num: -1 },
{ data: "第3", num: -1 },
{ data: "第4", num: -1 },
],
},

changeCol(e) {
var that = this;
var index = e.currentTarget.dataset.num;
var result = "arr[" + index + "].num";
if(that.data.arr[index].num == -1){
that.setData({
[result] : 1
})
}else{
that.setData({
[result]: -1
})
}
},

双击/单击

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//简写输出语句
var { log: l } = console;
Page({
data: {
last: 0,
},

//设置空属性,等会延时定时器的名字
funC: null,

timeEnd: 0,
timeStart: 0,

touchStart(e) {
//记录触屏按下时的时间戳,赋值给对象中的timeStart属性
this.timeStart = e.timeStamp;
},
touchEnd(e) {
//记录触屏手抬起时的时间戳,赋值给对象中的touchEnd属性
this.timeEnd = e.timeStamp;
},

double(e) {
let that = this;
//如果(抬起 - 按下)的时间小于350毫秒,那么就可以判断他不是长按了
//然后我们区分单击还是双击
if (that.timeEnd - that.timeStart < 350) {
let now = e.timeStamp; //记录现在按下的时间戳
let last = that.data.last; //取出上一个记录的时间戳
that.data.last = now; //更新上一个的时间戳

if (now - last < 300) {
//如两次抬起的时间差小于300ms
clearTimeout(that.funC); //清除定时器
l("double"); //判断为双击,并输出提示
} else {
that.funC = setTimeout(function () {
l("single"); //否则设置延时定时器,并在300ms之后输出单击
}, 300);
}
}
},
});

存储

这个是官方的,我这里记一些我觉得有用的
https://developers.weixin.qq.com/miniprogram/dev/api/storage/wx.setStorageSync.html

  • 同步、异步,是要看项目的需求的,如果你的数据需要及时的读,那么就要同步
  • 需要存储的内容。只支持原生类型、Date、及能够通过 JSON.stringify 序列化的对象
  • 优化:存储数据的话以 id 为关键字来存储,例如 "用户名",[{属性1},{属性2},{属性3}],用数组对象来放置属性,这样你在移除 id 的时候只需要移除用户名的 value 就圆满了,尽量避免碎片化的存储记录

双向数据绑定

提出问题:我是否可以在页面 wxml 中更改 input 值,点击提交,同时 js 里也能获取到这个值

数据绑定,原先都是 js 里些数据,然后绑定渲染到页面中,那么可不可以反过来呢?

分析问题的需求 ,给 input 绑定这个事件最好不过了,bindblur,input 失焦就会触发这个事件(我原先是绑定的 bindinput,这个事件每次输入值的话就会触发,这样事件就会触发很多次,然而 触发事件是消耗内存的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// pages/12-10/demo6/input.js

// 触发事件会消耗内存的,所以尽量少一些触发事件

//一下这些写在page里錒!!
data: {
valueInput:null
},

inputBox(e){
let that = this;
console.log(e.detail.value);//好奇的话可以打印e事件因子看看里面都有啥
that.setData({
valueInput: e.detail.value
})
},

网页如下

1
<input bindblur="inputBox" placeholder="输入密码" id="inputId" value="{{valueInput}}"></input>

图片选择、预览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//选择图片
//你可以把这段程序放在按钮的点击事件上
wx.chooseImage({
//选择照片
count: 9, //能选照片的最多数量,最大是9
sourceType: ["album", "camera"], //选择照片的方式
success(res) {
// tempFilePath可以作为img标签的src属性显示图片
const tempFilePaths = res.tempFilePaths;
that.setData({
imgSrc: tempFilePaths,
});
},
});
1
2
3
4
5
6
7
8
9
//预览图片
previewImage(e){
var that = this;
// 全屏显示图片
wx:wx.previewImage({
urls: that.data.imgSrc, //当前显示图片的http链接数组,
current: that.data.imgSrc[e.currentTarget.dataset.id] //需要预览的图片地址
})
},

wxml 模板

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

1
2
3
4
5
6
7
8
<!-- 以name名字定义 -->
<template name="msgItem">
<view> 这是一个模板 </view>
</template>

<!-- 用is来调用html 的模板
is里可以使用{{三目运算符}} -->
<template is="msgItem" data="" />

对外暴露并引用

如果你想在 js 中调用别的 js 文件中的函数或者属性,那么你就需要把要调用的属性 对外暴露

  • 关键语句 module.exports.testA = testA; 这里前面的 testA 你可以起任何名字,后面的 testA 是你要暴露的函数/属性名字
1
2
3
4
5
6
7
//比方说我要暴露这个 testA 的函数,让他在别的 js 中也能调用
let { log: l } = console;
function testA() {
l("testA()", 1);
}
//对外暴露方法 module.exports.给对外暴露的方法起名字 = 想要调用的方法
module.exports.testA = testA;

引用的方法如下

1
2
3
4
5
//这个写在Page外面
let container = require("a.js"); //先写引用的路径,把模块保存到container里

//这个可以写在 onLoad 里测试一下
container.testA(); //调用这样调用,模块.函数名
  • 模块化思想: 依赖关系,如果你想封装百度地图的天气信息,你先把百度功能的天气提取然后封装到一个对象中,然后暴露这个对象

小程序中的防抖节流

使用场景:模糊搜索

演示如下
在这里插入图片描述
代码截图
在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
page{
timeID: -1,
// 模糊搜索
inputSearch(e) {
const that = this;
// 输入的时候等待 0.8 左右来处理模糊搜索的内容
clearTimeout(this.timeID)
this.timeID = setTimeout ( () => {
// 根据输入框中的值来过滤出 orgList 中的变量
const orgRes = this.data.orgList.filter(function(val){
// console.log(val.orgName)
return val.orgName.indexOf(e.detail.value) != -1;
})
that.setData({
selectList: orgRes
})
}, 800)
}
}

显示 / 隐藏加载

场景:下载文件的时候,希望有提示正在加载,然后下载完成之后,隐藏掉提示
主要的两个 API 是 wx.showLoading()wx.hideLoading()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
downloadAndSeeBtn() {
const that = this;
// 显示加载图标
wx.showLoading({
title: "加载中",
});
wx.downloadFile({
url: ``, // 下载资源的 url
success: (res) => {
// 成功下载文件,之后隐藏 loading
wx.hideLoading();
},
fail: () => {},
complete: () => {},
});
},