目录
1.微信小程序是什么?
是一个基于微信app为开发和运行环境的一个小性软件
# 小程序项目结构
2.项目下的文件和文件夹的作用如下:
components: 小程序的自定义组件
images: 图片文件夹
pages: 存放页面文件的文件夹
index: 页面文件夹
index.js: 页面的js代码
index.json: 页面的配置
index.wxml: html模板文件
index.wxss: 页面的样式文件
app.js: 微信小程序的程序入口(程序入口:开始执行代码的地方)
app.json: 小程序应用程序的全局配置文件
app.wxss: 小程序的全局样式(.wxss文件是小程序的样式文件)
envList.js: 小程序云环境列表
project.config.json: 小程序项目的配置
sitemap.json: 小程序路由配置
3.常用标签
<!-- page 标签相当于 html 中的 body -->
<page></page>
<!-- view 标签相当于 html 中的 div -->
<view></view>
<!-- text 相当于 html 中的 span -->
<text></text>
<!-- image 相当于 html 中的 img -->
<image></image>
<!-- block 是一个自身不会显示的标签 -->
<block></block>
4 单位rem和rpx
## rem
rem 是 html 中的长度单位,代表相对根节点(html)上字体的大小
## rpx
rpx 是 微信wxml中的长度单位,iphone5 机器上1个像素长度等于1rpx
5模板语法
参考:https://developers.weixin.qq.com/miniprogram/dev/reference/wxml/
模板语法是微信规定的一套书写wxml的语法
## 插值
作用:用于将变量值插入页面
语法:
```wxml
<!-- name 变量,定义在 js 文件的 data 中 -->
{{name}}
> 注意:插值运算的花括号中{{}},填写的内容其实是js表达式
## 循环渲染
作用:可以将数组数据循环显示到页面中
语法:
```wxml
<!-- wx: 开头的写在标签头部的东西 称为指令 -->
<!-- array: 来自js data中的数组 -->
<!-- 使用 wx:for 一定要加上 wx:key,wx:key的值是array对象中的不可重复的属性 -->
<view wx:for="{{array}}" wx:key="id">
<!-- index: 是 wx:for 中隐式声明的变量,代表循环遍历array时的当前索引 -->
<!-- item: 是 wx:for 中隐式声明的变量,代表循环遍历array时的当前数组成员 -->
{{index}}: {{item}}
</view>
## 条件渲染
可以根据条件判断,选择性的渲染页面
语法:
```wxml
<view wx:for="{{table}}" wx:key="name">
<text>{{index}}: 姓名 = {{item.name}}; 年龄 = {{item.age}}; 性别 = </text>
<!-- wx:if 指令的值为布尔表达式,为true是渲染该节点,否则不渲染 -->
<text wx:if="{{item.sex==='male'}}">男</text>
<!-- wx:if 可以和 wx:elif、wx:else 连用 -->
<text wx:elif="{{item.sex==='female'}}">女</text>
<text wx:else>其他</text>
</view>
6页面底部选项卡
配置项:<https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html>
在 app.json 中 增加 tabBar 配置就能添加选项卡
```json
{
"tabBar": {
"selectedColor": "#444", // 选中的按钮的文本颜色
"list": [ // 按钮列表
{
"pagePath": "pages/read/read", // 跳转的页面路径
"text": "领读", // 按钮的文字描述
"iconPath": "image/tab_icon1.png", // 未选中时的图标路径
"selectedIconPath": "image/tab_icon1_active.png" // 选中时的图标路径
}
]
},
}
```
> 注意:要显示选项卡,按钮列表中,必须要有一个配置的 pagePath 属性值,是小程序的入口页面
> 注意:底部选项卡指定的页面不能是分包里的页面
## 自定义底部选项卡图标
可以在阿里适量图库下载需要的图标(一般来说是一个镂空图标和一个填充图标)
将下载后的图片复制到小程序项目目录下,然后再tabBar配置选项中配置即可
7 导航与页面间传参
导航:引导页面跳转到指定位置
导航方法有两种:1. 页面标签进行导航,类似 html 中的 a 标签;2. 使用js进行导航,类似于 location.href
## 使用 navigator 标签
文档:https://developers.weixin.qq.com/miniprogram/dev/component/navigator.html
语法:
```html
<!-- url:要跳转到的页面路径 -->
<!-- 若要传递参数,可以在url后面增加 ?key=value 的参数 -->
<navigator url="path"></navigator>
```
## 使用 wx.navigateTo 函数
文档:https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html
语法:
```js
function(){
wx.navigateTo({
// path: 要跳转的路径
// key=value: 要传递的参数
url: 'path?key=value'
})
}
// wx.navigateTo 跳转到某页 会新增堆栈
// wx.redirectTo 重定向到某页 不会新增堆栈
// wx.navigateBack 返回
```
> 参数的获取可以在另一个页面的 onLoad 声明周期函数中 options 变量中存放着参数
8组件开发
官网: <https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html>
## 什么是组件
高度封装独立运行的模块 组件有自己的数据 自己的标签模板 等等
组件的作用就是为了复用代码
## 创建组件
## 注册组件
## 组件结构
## 组件生命周期
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/lifetimes.html
## 组件属性
```js
// 在组件的配置中添加 properties 配置
Component({
/**
* 组件的属性列表
*/
properties: {
// 声明属性 value
// 具体声明方式可参考 https://developers.weixin.qq.com/miniprogram/dev/reference/api/Component.html#properties-%E5%AE%9A%E4%B9%89
value: {
type: String, // 属性类型 可以通过设置 optionalTypes 来接收多种类型的数据
value: 'o,k', // 属性默认值
// 属性变化监听器
observer: function (newVal, oldVal) {
console.log(newVal);
console.log(oldVal);
console.log(this)
}
}
},
})
```
组件内设置属性的方法和 `Page` 设置 `data` 是一样的
```js
// 使用 setData 设置属性
this.setData({value: 'hello'})
```
在 `Page` 中注册组件后就可以将组件作为标签使用了
```json
// 注册组件
{
"useingComponent": {
"my-component": "path/to/component"
}
}
```
```html
<!-- 使用组件 -->
<!-- _value 是当前页面 data 中的值 -->
<my-component value="{{_value}}"></my-component>
```
> 注意: 除了在组件内修改 `value` 值以外,还可以通过修改 `Page` 的 `_value` 来修改组件的 `value` 值
## 组件方法
### 获取组件并调用组件方法
```js
Page({
getComponent() {
// 给组件添加 class="my-component"
// 通过 selectComponent 获取组件
let com = this.selectComponent('.my-component')
// 假设组件 methods 中有个方法叫 myFn
// 调用组件方法
com.myFn()
}
})
```
## 组件事件
```html
<!-- 假设组件的模板如下 -->
<button bindtap="onClick">发送点击事件</button>
```
```js
// 组件声明如下
Component({
methods: {
onClick() {
// triggerEvent 可以发出事件
// 文档: https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/events.html#%E7%9B%91%E5%90%AC%E4%BA%8B%E4%BB%B6
// 第一个参数: 发出的事件名称
// 第二个参数: 事件传递出去的参数
// 第三个参数: 事件选项
this.triggerEvent('my-click', 'my detail')
}
}
})
```
```html
<!-- Page 的 wxml 如下 -->
<!-- 通过 bind:<event-name> 的方式绑定事件 -->
<my-component bind:my-click="myClickHandler"></my-component>
```
```js
Page({
// myClickHandler 将接收组件的 my-click 事件
myClickHandler(event) {
// event.detail 的值就是 triggerEvent 的第二个参数值
console.log(event.detail)
}
})
```
# 授权
官方文档: <https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html>
## 什么是授权
用户需要使用本地设备上的一些设备功能时,需要向系统获取设备权限,例如:摄像头,定位信息,联系人,陀螺仪等
此时就需要进行授权操作
## 什么时候使用授权
在用户即将使用一些需要授权才能使用的本地设备功能时(微信小程序已经把这些功能制作成了接口,当需要调用这些接口的时候就可以进行授权)
## 流程
- 读取当前权限
- 判断是否存在权限
- 不存在权限就进行授权
```js
// 可以通过 wx.getSetting 先查询一下用户是否授权了 "scope.record" 这个 scope
wx.getSetting({
success(res) {
if (!res.authSetting['scope.record']) {
// 调用 wx.authorize 进行授权
wx.authorize({
scope: 'scope.record',
success() {
// 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
wx.startRecord();
},
});
}
},
});
```
9 权限列表
文档: <https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/authorize.html#scope-%E5%88%97%E8%A1%A8>
## 授权期限
授权后,权限将一直存在,直到小程序被删除为止
## 关于二次授权
用户在进行授权时是可以拒绝的,若拒绝授权,我们可以使用 `wx.openSetting` 打开设置引导用户开启权限
例如以下代码
```js
wx.getSetting({
success: (res) => {
console.log(res);
if (!res.authSetting['scope.camera']) {
if (typeof res.authSetting['scope.camera'] === 'undefined') {
// 用户没有进行过授权
wx.authorize({
scope: 'scope.camera',
success: () => {
console.log('开启摄像头');
},
});
} else {
// 用户拒绝过授权
// openSetting 打开权限设置
// 设置中包含的是已经授权或被拒绝过的权限
wx.openSetting({
success(res) {
console.log(res);
},
});
}
} else {
console.log('开启摄像头');
}
},
});
```
10 云环境
## 什么是环境
程序运行的一个平台
一般开发来说有以下几种环境:
1. 开发环境:运行开发代码的
2. 生产环境:运行正式上线的代码的
3. 测试环境:运行测试代码的
4. 预发布环境:发布正式版前进行一个稳定测试的环境(可能采用线上数据库)
## 什么是云环境
云端(远程端)的运行程序的平台
## 云开发控制台
登录开发者工具,并在左上角找到云开发按钮

此时打开的窗口称为云开发控制台
可以在控制台上查看云函数 云数据库 云存储 和 云环境
## 使用第三方接口
若要使用第三方非小程序云的接口时,需要在小程序后台添加信任接口地址,为了开发方便可以在开发者工具中跳过接口验证,方法:选择右上角详情->本地设置->勾选不校验合法域名

11云函数
## 什么是云函数
云函数就是在云端(远程端)调用的函数
调用函数时,首先发起网络通信,让服务器调用函数,然后通过网络返回结果
## 定义云函数
1. 在编辑器的 cloudFunctions 文件夹中右键 新建node.js云函数
2. 编辑index.js中的main函数 返回想要的返回值
```js
// index.js 是入口文件,云函数被调用时会执行该文件导出的 main 方法
// event 包含了调用端(小程序端)调用该函数时传过来的参数,同时还包含了可以通过 getWXContext 方法获取的用户登录态 `openId` 和小程序 `appId` 信息
const cloud = require('wx-server-sdk')
exports.main = async (event, context) => {
let a = event.a // 获取函数参数
let b = event.b // 获取函数参数
let { OPENID, APPID } = cloud.getWXContext() // 这里获取到的 openId 和 appId 是可信的
let sum = a + b
return {
OPENID,
APPID,
sum
}
}
```
## 调用云函数
1. 必须先初始化云环境
```js
// 在 app.js 的 onLaunch 中初始化云环境
onLaunch() {
wx.cloud.init({
// env 参数说明:
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
// 如不填则使用默认环境(第一个创建的环境)
env: 'cloud1-xxxxxx',
traceUser: true,
})
}
```
2. 初始化完就可以使用 wx.cloud.callFunctions 调用函数了
```js
// 调用云函数
wx.cloud.callFunction({
// 云函数名
name: 'now',
// 要传递的参数
data: {
x: 1,
y: 2
},
// 通信成功的回调
success(res) {
console.log('success');
console.log(res);
console.log(new Date(res.result.now).toString());
},
// 通信失败回调
fail(reason) {
console.error('error');
console.error(reason);
},
// 无论成功还是失败
// 通信结束后都会调用complete
complete(res) {
console.info('complete');
console.info(res)
}
})
12 云数据库
## 什么是数据库
数据库是一个用于存放和组织数据的软件
## 什么是云数据库
数据库软件在服务器上运行
## 基本概念
### 如何存储数据?
小程序云开发使用的是文档型数据库,所以数据库中每条数据都是一个json对象,每个数据都有一个 _id 属性,该属性是本条数据的唯一标识符
### 数据库的增删改查
增删改查是数据库的四个操作
1. 增:添加数据
2. 删:删除数据
3. 改:修改数据
4. 查:查询数据
数据库的增删改查是数据库最基础的操作
## 数据库权限
这里的权限指的是数据库的读写权限,可以通过云开发控制台的数据库选行,对指定的表设置读写权限
## 小程序中使用数据库
### 初始化数据库连接
1. 在 app.js 的 onLaunch 中 初始化数据库
```js
//app.js
App({
onLaunch: function () {
......
this.globalData = {}
// 初始化数据库
const db = wx.cloud.database()
// 在全局对象中保存db对象
this.globalData.db = db
}
})
```
2. 在使用数据库的页面中获取db对象
```js
const db = getApp().globalData.db
```
3. 获取要操作的数据库表
```js
// 获取数据库表 参数为表名
const collection = db.collection('collectionName')
```
4. 通过表对象执行数据库操作
### 插入数据
```js
insert() {
// 获取插入数据的表格
// 参数是表格名
const students = db.collection('students')
// 使用add函数插入数据
students.add({
// 要插入到数据库的数据
data: {
name: '法外狂徒张三',
sex: 'other',
age: 30
},
success(res) {
console.log(res);
},
fail(reason) {
console.error(reason);
}
})
}
```
### 查询数据
从形式上来分,可以分为 列表查询和分页查询
列表查询:适用于手机等移动端查询一个数据列表的查询方法
分页查询:用于将数据像书页一样分页码进行查询
此处以列表查询为例
```js
// 获取数据库表
const students = db.collection('students')
// 查询数据并按照数据的更新时间进行排序
// orderBy 函数用于数据排序
// 第一个参数:排序字段
// 第二个参数:排序方法(是升序asc还是降序desc)
// limit 用于规定返回数据量
// get 查询函数 通常放在链式调用的尾部
students.orderBy('updateTime', 'desc').limit(2).get({
success(res) {
console.log(res);
}
})
// 添加查询条件和查询指令
// 查询指令:用于规定如何查询的一些查询方法
// 文档地址:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/query.html
const _ = db.command // 获取指令对象
// where 添加查询约束(where是约束的意思)
students.orderBy('updateTime', 'desc').limit(2).where({
// 参数是个对象
// key 要添加约束的对象
// value 什么样的约束 此处的例子 是查询 updateTime 字段小于指定值的数据
updateTime: _.lt(new Date('Mon Sep 13 2021 09:40:13 GMT+0800'))
}).get({
success(res) {
console.log(res);
}
})
```
### 更新数据
```js
update() {
const students = db.collection('students')
const _ = db.command // 获取指令对象
// 获取对应id的文档对象
const student = students.doc('cd045e75613eabf80d332db93f080137')
student.update({
// data 要修改的字段集合
data: {
// 规范的做法是使用 set 指令经行修改
// name: _.set('修成正果张三'),
name: '修成正果张三',
updateTime: new Date() // 更新时间
},
success(res) {
console.log(res);
}
})
// 多条数据的更新如下
// 调用表格的 where 函数添加查询条件
students.where({
sex: 'male'
}).update({ // 调用 update 函数进行更新
data: {
age: 16
},
success(res){}
})
}
```
### 删除数据
```js
remove() {
const students = db.collection('students')
// 获取对应id的文档对象
// 此处的id就是想要删除的数据的id
const student = students.doc('cd045e75613eabf80d332db93f080137')
// remove 删除对应id的数据
student.remove({
success(res) {
console.log(res);
}
})
// 批量删除
// 调用表格的 where 函数添加查询条件
students.where({
sex: 'male'
}).remove({ // 调用 remove 函数进行删除
success(res){}
})
}
```
13 小程序读取微信信息
由于微信小程序是独立于微信的,所以小程序想要获取用户的微信信息,需要微信进行授权
## 授权微信信息API
授权接口: <https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html>
通过调用 wx.getUserProfile 获取用户的个人信息
```js
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
// wx.getUserProfile 用于替代以前的 wx.getUserInfo
wx.getUserProfile({
// 返回数据的语言类型
// en 英文
// zh_CN 简体中文
// zh_TW 繁体中文
lang: 'en',
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
// this.setData({
// avatarUrl: res.userInfo.avatarUrl,
// userInfo: res.userInfo,
// hasUserInfo: true,
// })
console.log(res);
// 在返回的res对象中的userInfo属性就是用户的个人信息
// userInfo: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/UserInfo.html
}
})
}
```
## 最佳实践
通常微信小程序的账号系统登录流程可以是这样:
- 判断小程序数据库中是否存在当前用户信息
- 不存在,就调用 `wx.getUserProfile` 向微信申请
- 然后将用户信息计入数据库,妥善保管
- 存在,就读取数据库中的数据
- 用户若想修改个人信息,请参考: <https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/userProfile.html>