微信小程序的组成
微信小程序总体上是由三个部分组成的:1、云函数库(cloudfunctions ) 2、小程序主体部分(miniprogram) 3、一些乱七八糟看不懂的环境配置(可以去查看微信小程序官方文档)

一、云函数库
云函数内的代码可以对数据库的所有数据进行操作,并且本地的函数只能对数据库的数据进行增删改查的基本操作,而云函数则可以实现更多的功能,包括支付之类的。
1、创建云函数
一般云函数要调用的参数都存放在event里,openid和appid放在context里,这是固定的格式,以下云函数用来计算两个参数的和。
const cloud = require('wx-server-sdk')
exports.main = async (event, context) => {
let { a, b} = event
let { OPENID, APPID } = cloud.getWXContext() // 这里获取到的 openId 和 appId 是可信的
let sum = a + b
return {
OPENID,
APPID,
sum
}
}
2、云函数的调用
也是有两种格式,与查询数据库的两种方法差不多。这里的res就不是返回数据了,而是返回云函数的返回值。
wx.cloud.callFunction({
name:'要调用的云函数的名字',
data: {
a: 12,
b: 19
}
})
.then (res =>{
//请求成功
console.log(res.data)
console.log(res)
})
.catch (error => {
//请求失败
console.error(error)
})
如果想获取云函数返回的调用该函数的用户的openid,则需要在setData({})里,使用res.result.openid。
二、云数据库
云数据库的组成
云数据库是一个database,里面有多个集合,每个集合里面又有很多个记录,每个记录里都有很多数据。就类似于记录是一个对象,记录里的数据则是对象里的变量。
1、查询数据库里的数据
以下代码写在page对象里的时候,记住都要放在一个函数里,page对象里除了data就是函数,不能有单独的代码。
先用db申请到数据库的使用,再用get方法去获取数据,以下是获取数据的两种格式:
const db = wx.cloud.database()
db.collection('集合名称').get()
.then (res =>{
//请求成功
console.log(res.data)
})
.catch (error => {
//请求失败
console.error(error)
})
在这种格式里使用this.setData({}) 函数,可以修改整个页面的变量值
const db = wx.cloud.database()
db.collection('集合名称').get
({
//请求成功
success(res) {
console.log(res.data)
},
fail(error) => {
//请求失败
console.error(error)
}
})
如果是第二种格式,要能够对data里的变量进行赋值,得先在最开始 that=this ,并且使用that.setData({})
2、只查询符合条件的数据
可以使用 .where({判断条件}) 来查询符合条件的数据项,
const db = wx.cloud.database()
db.collection('user')
.where({ username: 'xiaoming'})
.get()
.then (res =>{
//请求成功
console.log(res.data)
this.setData({
username:res.data[0].username
})
})
以上代码最后就会在user集合里查询到 username为xiaoming的那条记录,在对这条记录使用get(),所以最后在then的方法里的this指的就是当前这条记录。每一个点函数都是在当前函数的基础上进行下一步操作。如果要查询该记录的某个变量,一定要写作res.data[0].username
如果查询失败要进行操作,要将代码修改如下:
const db = wx.cloud.database();
db.collection('user').where({
userid: id
}).get().then(result => {
if (result.data.length === 0) {
db.collection('user').add({
data: {
userid: id,
username: '用户名',
userpicture: 'https://636c-cloud1-8g1mjjjn671cbda6-1325149093.tcb.qcloud.la/userpicture/no_login.png?sign=423807902f0d872433e1cc2fb6ff584c&t=1716002154'
}
}).then(() => {
wx.setStorageSync('userid', id);
this.globalData.userid = id;
})
3、增添数据
db.collection('todos').add({
// data 字段表示需新增的 JSON 数据
data: {
}
})
.then(res => {
console.log(res)
})
.catch(console.error)
4、为查询到的符合条件的信息添加信息
首先,使用
.where()方法查询符合条件的数据,然后再通过.update()方法对该数据进行修改和增添。.update()的用法如下:
const db = wx.cloud.database()
db.collection('user')
.where({ username: 'xiaoming'}).update({
data: {
// 这里添加你想要更新的字段和值
additionalInfo: 'new value'
},
success: res => {
console.log('更新成功:', res)
},
fail: err => {
console.error('更新失败:', err)
}
})
res和error
在微信小程序中调用数据库或云函数时,我们通常会遇到两个关键的参数:res 和 error。这两个参数在调用成功或失败时分别承载了不同的信息,让开发者能够理解操作的结果并据此作出响应。下面我用通俗易懂的方式解释一下这两个参数。
res(结果)
res 是当数据库操作或云函数调用成功完成时返回的对象。这个对象通常包含了我们需要的所有数据或操作结果。
res.data:这是最常见的属性,尤其是在数据库查询时。它包含了查询返回的数据数组。例如,如果你查询了一个集合中的所有文档,这些文档就会作为对象数组包含在res.data中。res.result:这通常在调用云函数时使用,包含了云函数执行后返回的结果,这个结果可以是任何 JavaScript 支持的数据类型,比如数值、字符串、对象或数组。
error(错误)
error 是当数据库操作或云函数调用失败时返回的对象。这个对象包含了错误的相关信息,帮助开发者了解为什么请求没有成功执行。在微信小程序的开发过程中,处理这个错误信息是非常重要的,它可以帮助你定位问题并进行修正。
error.code:一个数字代码,表示错误的类型。例如,网络问题、权限问题或是代码逻辑错误等。error.message:一个描述性的信息,说明了错误的具体原因。这是一个人类可读的字符串,例如 “request is forbidden” 表示请求被禁止。
三、云存储
云存储主要是用于存放图片、视频、文件之类的东西
上传图片或视频到云存储库
先对要上传的图片进行选择
wx.chooseMedia({
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
console.log(res.tempFiles[0].tempFilePath)
console.log(res.tempFiles[0].size)
}
})
不能在.js文件中直接设置,而是要先定义一个函数方法,把该内容放在你自己定义的函数当中。
再将通过以上方法获得的图片上传到云存储,可以用res.fileID获取文件的上传ID。
wx.cloud.uploadFile({
cloudPath: 'example.png',
filePath: '', // 文件路径
}).then(res => {
// success
console.log(res.fileID)
}).catch(error => {
// fail
})
警告:cloudpath一定要以.png或.jpg结尾,不然不会展示一张图片
this指针存在的问题
在.js文件中,this一般是指向page()函数定义的页面对象,通过这个页面对象this,我们可以在定义的函数中调用我们已经在这个page()内写好的其他函数,但是当存在success之类的回调函数时,this会指向当前的执行环境,所以当存在success的回调函数内想使用其他的函数,需要在调用wx.choosemedia()之前将页面对象this赋值给that,let that =this;
Page({
data: {
imagePath: ''
},
chooseImage: function() {
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: function(res) {
console.log(this); // this 指向回调函数的执行环境,而不是页面实例
const tempFilePath = res.tempFilePaths[0];
this.setData({
imagePath: tempFilePath
});
// 这样会报错,因为 this 并不是页面实例
this.upload(tempFilePath);
}
});
},
upload: function(filePath) {
console.log('正在上传文件:', filePath);
}
});
在上面的代码中,wx.chooseImage 的 success 回调函数内的 this 并不是指向页面实例,而是指向调用 wx.chooseImage 时的执行环境,这个环境通常是 wx.chooseImage 内部的环境。
解决方法有两个 :1、就是之前的 let that=this,在调用wx.chooseimage这样的函数之前。
2、就是不用success这样的形式,用箭头那样的格式。
从云存储中下载文件
wx.cloud.downloadFile({
fileID: 'a7xzcb'
}).then(res => {
// get temp file path
console.log(res.tempFilePath)
}).catch(error => {
// handle error
})
获取用户的微信头像和昵称
页面的wxml文件代码设置如下:
<button open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">
<image src="{
{avatarUrl}}"></image>
</button>
<input type="nickname" placeholder="请输入昵称"/>
页面的js文件代码设置如下
const defaultAvatarUrl = 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0'
Page({
data: {
avatarUrl: defaultAvatarUrl,
},
onChooseAvatar(e) {
const { avatarUrl } = e.detail
this.setData({
avatarUrl,
})
}
})
四、小程序主体

小程序主体部分基本上是由四个部分组成:1.小组件部分(components ) 2.图像部分(images )3.小程序的页面(pages )4.app.js 和app.json 和app.wxss 5.剩下的两个文件我也不太清楚(大家自行查看微信小程序官方文档)
1、小组件
小组件类似于一个缩小的页面,你在components中将它编写完成之后,就可以在微信小程序的所有页面中直接使用(全局有效)。
举个例子,你当前微信小程序的某个页面需要有很多个展示商品的窗口,用户可以通过这个窗口来观察到你的商品的图片,此时就可以将这个展示商品的窗口作为一个小组件编写完之后全局使用。
2、图像
这个好理解,就是你这个微信小程序当中所需要的所有图片都要存入到这个文件夹里,在wxml中需要调用这张图片的时候,输入这张图片的路径即可。
3、页面
这个pages可以说是微信小程序中最主要的组成部分,每个page对应的就是你在使用一个微信小程序时所见到的每个界面。每个界面又由四个部分组成分别是:.js文件 、.json文件 、.wxml文件、 .wxss文件。
.wxml文件决定了在这个页面中有几个方块,这些方块分别处于界面的什么位置(方块可能会用来展示图片,也有可能用来展示文字)
.wxss文件决定了不同的方块具有什么样的特点,这些特点包括了:方块背景颜色,方块尺寸大小等等
.js文件中包含了该页面中所需要的一些变量与函数,比如说在一个展示图片的方块下方,有一个很小的点赞方块,当你点击了这个点赞方块一下,关于这个页面的点赞数变量number就要通过调用点赞数加一函数dianzan()来实现对变量number的加一操作。
.json文件中包含了该页面的一些些配置,比如说导航栏的样式,关于该页面的.json文件叫局部配置,用到的地方不是很多,用到比较多的是后面的全局配置(app.json)
(1).wxml文件
a.基础知识
每个方块都被称作一个元素,一个方块里可以继续嵌套其他方块。
方块的表示格式为:<标签 属性 = “对应属性的属性值”>文本内容 这就表示了一个方块。
以下是不同种标签的作用以及不同标签对应的属性:
注意:以下三种属性是每个标签都具备的共有属性。
class:为元素添加类名,便于样式统一修改。style:内联样式,用于设置元素的样式。bindtap:事件绑定,当用户点击该元素时,会触发对应的事件处理函数。
view:视图标签,类似于 HTML 中的 div 标签,用于表示一个块级区域。
<view class="container" bindtap="onContainerTap">
<text>这是一个 view 标签</text>
</view>
scroll-view:滚动视图标签,用于创建一个可滚动的区域。
<scroll-view>
<view>滚动内容1</view>
<view>滚动内容2</view>
</scroll-view>
text:文本标签,用于显示文本内容。
<text>这是一个文本标签</text>
image:图片标签,用于显示图片。
src:图片资源地址。mode:图片裁剪模式,如aspectFill(按比例裁剪图片以填充整个元素)。
<image src="https://example.com/path/to/image.png" mode="aspectFill"></image>
button:按钮标签,用于创建按钮。
type:按钮类型,如primary(绿色)、warn(红色)等。size:按钮大小,如mini(小尺寸)。
<button type="primary" size="mini" bindtap="onButtonTap">点击我</button>
input:输入框标签,用于创建输入框。
type:输入框类型,如text(文本)、number(数字)、password(密码)等。placeholder:输入框的提示文本。value:输入框的值。- password :当为ture的时候,会认为是在输入密码,从而将密码用**隐藏。
<input type="text" placeholder="请输入内容" value="{
{inputValue}}"/>
form:表单 ,将组件内的用户输入的 input组件内的内容提交。
当点击 form 表单中 form-type 为 submit 的 button 组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
<form bindsubmit="create_login">
<view class="item">
<text>手机:</text><input name="phone" placeholder="请输入您的手机号"></input>
</view>
<view class="item">
<text>密码:</text><input name="password" placeholder="请输入您密码" password="true"></input>
</view>
<button class="submit" form-type="submit"><text>登录</text></button>
</form>
在这个填写的form表单中,当你点击了form-type属性值为"submit"的button组件时,就会将之前的每个input框的内容以数组的形式保存{phone:值 ,password:值 ……. }的形式保存。
如果想要将表单提交的内容获取,则要在bindsubmit属性对应的方法的函数中,以e为参数,通过 e.detai.value获取(e为这个表单点击对应的事件),代码如下:
create_login(e) {
let user = e.detail.value
console.log('user', user)
}
要注意以下两点:
1、无论是什么标签的方块都具有被点击并作出反应的功能,并不是只有button标签可以被点击,只需要为该标签设置bindtap属性,即可对用户对该方块的点击作出反应。button标签只会让该方块以按钮的形式出现在用户显示页面上。
2、image标签与input标签都在一个<>里,没有的形式,只有
的形式。
b.wxml特有的语法
数据绑定
在以上元素中对应属性的属性值处,可以通过{
{ a }}两个中括号来引用该页面的.js文件的data对象中的变量a的值,只要带上两个中括号,就可以将它们当作特定的变量来使用。例如:{
{a+b}} 、{
{a}}+{
{b}}。
列表渲染
当你某个元素的属性为wx::for时,在这个属性的属性值位置需要写一个页面的.js文件的data对象中的数组变量,这样就会为这个属性的方块生成多个与数组每个数对应的方块并有序显示在界面上,就是将这个数组的每个数所联系的方块渲染一遍。(渲染:就是将这个方块显示在界面上)。
假设在data对象里有个item数组,则以下代码会将这个item数组中的每个数都有序排列并显示在屏幕上:
<block wx:for="{
{arry}}" wx:key="item">
<text>{
{item}}</text>
</block>
这里的wx::key的作用在于提高系统的效率,它存在的意义是你改变这个数组中某个数的值的时候,当它运行时,对于没有被改变的数不做操作,只对被改变的数字操作。微信小程序在使用wx::for的时候数组自动会具有index和item这两个变量,代表了当前的索引与当前的项,索引从0开始,key后一般跟item,这个时候就不用{
{}}来表示这个变量,要用双引号。推荐用该数组每一项的某个唯一值来作为key,如id。
就以上代码举例,每显示一个arry数组的一项,就将该项的key设置为该项的item的值,如果该项发生变化,就会发现现在的item值与key值匹配不上,察觉数组更新,对这项的值重新渲染。
条件渲染
当你某个元素的属性为wx::if时,其对应属性的属性值处要为一个data中的布尔变量(或真或假)打上双中括号,若为真,则对这个方块渲染,若为假,则不渲染。
<block wx:if="{
{condition}}">
<text>这是一个条件渲染的元素</text>
</block>
此处具有block标签的元素的属性才可以为wx::if,
- wx:elif
- 用于在
wx:if后添加一个"否则如果"条件,可以有多个wx:elif。- wx:else
- 用于处理
wx:if和所有wx:elif条件都不满足时的情况。
wx::if与hidden的区别
1. wx:if
wx:if指令决定是否在页面中渲染该元素。如果wx:if的条件值为false,则与这个条件绑定的组件不会被渲染到页面上,它们就不存在于页面的结构中。- 这意味着使用
wx:if可以更有效地管理内存,尤其是当页面上有很多不必要渲染的部分时。如果条件为false,相关的数据绑定和生命周期函数将不会被触发。 wx:if适用于那些不频繁切换显示状态的组件,因为每次条件变化时,都会导致组件的重新渲染。
2. hidden
hidden是一个属性,可以绑定到任何标准组件上。当hidden的值为true时,组件仍然会被渲染到页面上,但是不会在界面上显示,通常是通过 CSS(如display: none)来实现的。- 即使组件被隐藏,它仍然存在于页面的结构中,所有的数据绑定和生命周期函数仍然会正常工作。这意味着它仍然消耗内存和处理时间。
hidden适用于需要频繁切换显示状态的组件。因为它避免了重新渲染的开销,改变显示状态更加迅速。
总结
- 使用
wx:if时,组件的创建和销毁是完全受条件控制的,适用于不需要频繁显示或隐藏的重量级组件。- 使用
hidden时,组件始终被加载并存在于DOM中,只是简单地在视觉上不可见,适用于需要频繁切换显示状态的轻量级组件。
通过currentTarget来确定究竟是哪个组件被点击
1、在wxml的button元素中添加 “data-什么"的属性来绑定该组件
<button bindtap="navigateToPage" data-type="type1">按钮1</button>
2、在.js文件中通过const 变量1 = event.currentTarget.dataset.什么; 的形式来获取究竟是哪个button元素被点击,并且在要前往的页面中通过 ” ? 变量2=${变量1}“来向要前往的页面传递参数。
Page({
navigateToPage: function(event) {
const a = event.currentTarget.dataset.type;
wx.navigateTo({
url: `/pages/target/target?type=${a}`
});
}
})
3、在目标页面的onLoad方法中获取传递的参数,根据参数显示不同内容
Page({
onLoad: function(options) {
const type = options.type;
if (type === 'type1') {
this.setData({
content: '这是按钮1的内容'
});
} else if (type === 'type2') {
this.setData({
content: '这是按钮2的内容'
});
}
},
data: {
content: ''
}
})
如果使用的是navigator组件也不用这么麻烦,直接在要去的页面绑定即可。
<!-- 在index.wxml文件中 -->
<view>
<navigator url="/pages/target/target?type=type1">按钮1</navigator>
<navigator url="/pages/target/target?type=type2">按钮2</navigator>
</view>
模板使用
个人认为模板的使用类似于小组件,但模板更多是将一个写好的页面的一部分直接应用在不同的页面上。
通过以下格式来规定一个模板,name即为该模板的名字: 此处是模板内容
当要使用该模板的时候,只需要在is之后填你要使用的模板名字即可:即可使用改模板
<template name="odd"> <view> odd </view> </template> <template name="even"> <view> even </view> </template> <block wx:for="{ {[1, 2, 3, 4, 5]}}"> <template is="{ {item % 2 == 0 ? 'even' : 'odd'}}"/> </block>以上代码就规定了两个模板,并在实际使用时当is后模板名为奇数,则渲染第二个模板,当is后模板名为偶数,就渲染第一个模板。
通过判断条件选择是否添加一个属性
<view class="navbar_item{ {activeindex==index?'bar_item_on':' '}}"> </view>这个view组件本身会自带 navbar_item属性,再通过判断activeindex和index是否相等,如果相等再添加bar_item_on属性,如果不相等,则添加' '空属性 。
(2).wxss文件
wxss中基本上存储的都是.wxml文件中元素具有的class属性的属性值。
格式 : .name{}
每种样式名之前都要有一个点,代表它为class属性具有的属性值,紧接着是样式名称name,{}内部就是你所要设置的样式的特点,包括什么长度,宽度,背景颜色之类的。
.name { font-size: 24px; color: red; }以上就是在.wxss中设置的一个样式。
当你在.wxml中使用该样式的时候,让某个元素的class属性值为该样式名称,就可以使用该样式了,这个元素的class属性值为该样式名称,就会让这个元素所代表的方块的属性都跟这个样式一致,包括长度,宽度,背景颜色等等。
<view class="name">Hello, World!</view>一般情况下style属性能够跟class达到同样的效果,可style的属性值不在.wxss文件中设置,而是直接在.wxml文件的元素属性值位置直接设置。
<view style="font-size: 24px; color: red;">Hello, World!</view>(3).js文件
这个文件里放的才是之前学过的类似于c++一样的编程语言。
.js文件里存放的是程序所用到的变量与函数。
经过微信规定,.js文件里所有的变量与函数都需放到 page({});的内部。
该页面所用到的所有局部变量都存放在data:{}
数组
要先在data里声明数组。
myArray: [1, 2, 3]也可以声明空数组
infor : []有一点要记住,如果已经声明了空数组,要再对数组进行赋值,就不能在data里进行赋值,只有在data外部用在函数里用wx.setdata()实现赋值。
跳转页面
从当前页面跳转到其他页面通常有两种方法:
1、使用navigator组件,当用户点击时就会自动跳转到那个页面(用url的属性来确定跳转到哪个页面)。
2、也可以在js文件里写bindtap的函数方法来实现操作,有以下两种跳转方法:
使用
wx.navigateTo方法:这种方法会保留当前页面,并在跳转页面上新增一个页面。用户可以通过左上角的返回按钮返回到原页面。function goToPage() { wx.navigateTo({ url: '/path/to/destination' // 将 '/path/to/destination' 替换为你想要跳转到的页面路径 }); }使用
wx.redirectTo方法:这种方法会关闭当前页面,跳转到应用内的某个页面。适用于不需要返回到当前页面的场景。function goToPage() { wx.redirectTo({ url: '/path/to/destination' // 将 '/path/to/destination' 替换为你想要跳转到的页面路径 }); }赋值
javascript中的赋值操作是用 “=“来完成的。
但在页面的data对象中对变量赋初值是用 变量:值的形式来进行赋初值的。
同时在赋完初值之后如果想修改data中变量的值,要调用 this.setdata({变量:值})的形式对变量的值进行修改。进行少量的本地缓存
微信小程序可以用wx.setStorageSync()来将一些必要的数据存放在本地,但基本只有10MB的存储空间,并且会拖慢启动速度,所以一般只记录用户的登录状态。
当你想将某些数据缓存到本地,名称位置是起一个针对于该变量的名称,方便当你再次打开小程序的时候,能够找到这个变量,而变量值的位置则要填写一个变量或者是变量值,将该变量的值赋值给这个名称对应的本地存储空间,这里的变量可以是任何类型的变量,布尔变量或者用户对象(里面包含用户的账号,名称等)都可以,代码如下:
wx.setStorageSync('名称', 变量值);当再次打开小程序想将你在本地存储的数据直接拿出来的时候 ,代码如下:
let 变量 = wx.getStorageSync('之前的名称');清除缓存用以下api
wx.removeStorageSync('key');如果请求失败了,得不到数据,则会得到 ' ',不是undefined或null。
在app.js文件中设置整个小程序的全局变量并调用
在
app.js中定义全局变量,然后在页面或组件中通过getApp()获取这些变量。设置全局变量:
App({ globalData: { userInfo: null, userId: null }, onLaunch: function() { // 这里可以进行一些初始化操作 } })调用全局变量:
Page({ onLoad: function(options) { const app = getApp() console.log(app.globalData.userInfo) console.log(app.globalData.userId) // 设置全局变量 app.globalData.userId = 'newUserId' }, someFunction: function() { const app = getApp() console.log(app.globalData.userId) } })如果要在app.js文件里修改全局变量的值,记得要用this.globalData.openid=…..;一定不要用以上的方法,以上的方法只适用于其他页面的.js文件。
强制用户退出小程序
wx.exitMiniProgram({ success: function() { console.log('成功退出小程序'); }, fail: function(err) { console.log('退出小程序失败', err); } });javascrpit中的严格判等
在javascrpit中,'=='是普通判等,可能会出现类型转换,'==='是严格判等,不会出现类型转换(这里指的类型转换指的是从' '转换为false)。
在字符串中使用变量
在一段字符串 'string' 如果要包含某个变量,则要使用内嵌表达式用 ${}包围。
const openid = 'oGZUI0egBJY1zhBYw2KhdUfwVJJE'; const cloudPath = `user_${openid}/myfile.jpg`;如果要访问的是res.data[0]中的某个具有动态名称的数据,在 JavaScript 中,访问对象属性时,如果属性名是动态的,应使用方括号语法
[propertyName],res.data[0].[propertyname]。原文链接: https://blog.csdn.net/m0_73837751/article/details/137969454