文章目录
微信小程序
简介
- 小程序的大小限制在 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
文件中
"tabBar":{
"list":[
{
"pagePath":"pages/demo1/demo1",
"text":"demo1"
},
{
"pagePath": "pages/index/index",
"text": "index"
}
]
},
注意
- 对象中最后一项语句的末尾,是不可以有逗号的,比方说这个
"text":"demo1"
,他是对象中最后一个键值对,它的最后面不可以加逗号的,也就是写成"text":"demo1",
{
"pagePath":"pages/demo1/demo1",
"text":"demo1"
}
- 颜色的表示方法,很多都是 十六
具体添加方法如下
添加 tabBar 的图标
微信官方给的要求:
icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。
首先来这个网站 https://www.iconfont.cn/ 搜索你想要的图标,比方我要微信上的 Chats 图标
iconPath
这个属性是选项卡没有选中时的图片,通常为灰色selectedIconPath
选项卡选中时的图片,微信是绿色的,这两个图片我们都要设置
页面的编写
- 新的标签名字
view
类似原先的div
,
以下是水平的滑动,演示如下
代码如下
<!--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>
/* 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>
来一起使用
<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"
,我在里面放了个
data: {
flag:"true"
},
如何在 wxml 页面引用变量?
用{{变量名}}
两个花括号
<text>{{flag}}</text>
这样引用变量既可以当属性名,也可以用来做属性值
条件
微信小程序中的条件是 wx:if
<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
,取名任意,你想改就改
<view wx:for="{{arr}}" wx:item="item">
{{item}}
</view>
更新数据
更新数据需要用到 setData
,这里更新完的数据会传递到页面中供其使用
刚开始我们需要 let that = this;
使指针指向对象,这个对象是 page
里的那个对象,就是下面动画里选中的这一大坨
let that = this;
that.setData({
//这里填你想要修改的值
"key":"value"
})
这个key值如果有变量的话就要在外部拼接好,然后在这里用解构,比方说下面的例子
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 的数据值,是不会传递到页面中去的
完整代码
//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
})
},
/*wxml*/
<text>点击那个那个变色,只有一个变色</text>
<view wx:for="{{arr}}" data-index="{{index}}" bindtap="changeCol" class="color{{tapIndex == index ? 'Select':'Normal'}}">{{item}}</view>
.colorNormal{
color: black
}
.colorSelect{
color:red
}
点击变色(2)
问题描述
击那个就切换颜色,再次点击取消颜色
演示如下
解决思路
- 给每一个 li 添加一个状态,这种状态记录着它是否被点击过,因为我们循环的数据,那么我们暂且把这种状态加到数据里
//我的这组数据中 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: key值为变量,arr[index].num 是不会被解析的
that.setData({
arr[index].num : 1
})
//错误2: key值为变量,result 里是有 index 的,
//index 也是变量不是字符串,照样是不会被解析的
var result = "arr[" + index + "].num";
that.setData({
result : 1
//等价于 "arr[" + index + "].num" : 1
})
//正确示范:加上中括号,里面的变量就可以解析了(es6)
var result = "arr[" + index + "].num";
that.setData({
[result] : 1
})
我们可以这样测试一下
var index = 1;
var result = "arr[" + index + "].num";
var obj = {
[result] : 1
}
console.log(obj); // {arr[1].num: 1}
// 如果不加括号的话 直接是{result: 1}了,就不会解析里面的变量
// 因为对象的key 值是自动toString的
// 需要通过中括号结构解析
完整代码
<!--页面.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>
/* 样式.wxss */
.colorNormal{
color: black
}
.colorSelect{
color:red
}
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
})
}
},
双击/单击
//简写输出语句
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,这个事件每次输入值的话就会触发,这样事件就会触发很多次,然而 触发事件是消耗内存的)
// 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
})
},
网页如下
<input bindblur="inputBox" placeholder="输入密码" id="inputId" value="{{valueInput}}"></input>
图片选择、预览
//选择图片
//你可以把这段程序放在按钮的点击事件上
wx.chooseImage({ //选择照片
count: 9, //能选照片的最多数量,最大是9
sourceType: ['album', 'camera'], //选择照片的方式
success(res) {
// tempFilePath可以作为img标签的src属性显示图片
const tempFilePaths = res.tempFilePaths;
that.setData({
imgSrc: tempFilePaths
})
}
});
//预览图片
previewImage(e){
var that = this;
// 全屏显示图片
wx:wx.previewImage({
urls: that.data.imgSrc, //当前显示图片的http链接数组,
current: that.data.imgSrc[e.currentTarget.dataset.id] //需要预览的图片地址
})
},
wxml 模板
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
<!-- 以name名字定义 -->
<template name="msgItem">
<view>
这是一个模板
</view>
</template>
<!-- 用is来调用html 的模板
is里可以使用{{三目运算符}} -->
<template is="msgItem" data=""/>
对外暴露并引用
如果你想在 js 中调用别的 js 文件中的函数或者属性,那么你就需要把要调用的属性 对外暴露
- 关键语句
module.exports.testA = testA;
这里前面的testA
你可以起任何名字,后面的testA
是你要暴露的函数/属性名字
//比方说我要暴露这个 testA 的函数,让他在别的 js 中也能调用
let {log:l} = console;
function testA(){
l("testA()",1);
}
//对外暴露方法 module.exports.给对外暴露的方法起名字 = 想要调用的方法
module.exports.testA = testA;
引用的方法如下
//这个写在Page外面
let container = require("a.js"); //先写引用的路径,把模块保存到container里
//这个可以写在 onLoad 里测试一下
container.testA(); //调用这样调用,模块.函数名
- 模块化思想: 依赖关系,如果你想封装百度地图的天气信息,你先把百度功能的天气提取然后封装到一个对象中,然后暴露这个对象
小程序中的防抖节流
使用场景:模糊搜索
演示如下
代码截图
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()
downloadAndSeeBtn() {
const that = this;
// 显示加载图标
wx.showLoading({
title: "加载中",
});
wx.downloadFile({
url: ``, // 下载资源的 url
success: (res) => {
// 成功下载文件,之后隐藏 loading
wx.hideLoading();
},
fail: () => {},
complete: () => {},
});
},