HTTP
协议的状态管理
由于HTTP
协议是一款基于短连接模型的协议,所以同一个客户端发送的请求是无状态的。即服务端没有将同一个客户端发送的多次请求当成一个整体来看待,也没有将同一个客户端涉及到的数据保存下来以后使用。这就是无状态协议的特点。
HTTP
协议状态的管理办法:
-
cookie
机制
- 客户端发送第一次请求,服务端接收请求,处理请求。
- 服务端在响应数据包中添加
cookie
信息,返回给客户端让客户端保存 - 客户端接收到响应,解析到
cookie
信息,将这些数据存入本地cookie
存储区。 - 客户端发送后续请求时,将会自动携带域名匹配的
cookie
数据一起发送请求,这样,服务端就可以获取上一次请求所存储的信息,从而知道当前客户端的状态,实现http
的状态管理。
cookie
不安全,无法存储敏感数据
-
session
机制
- 客户端发送第一次请求,服务端接收请求,处理请求。
- 服务端将敏感数据存入
session
区域,并且为该用户分配一个SESSIONID
。在返回响应时,以cookie
形式发给客户端。 - 客户端接收
cookie
,将SESSIONID
存起来。 - 当客户端发送下次请求时,将会自动带着
SESSIONID
一起发送请求,这样服务端就可以通过SESSIONID
找到以前存过的数据,从而获取用户的状态信息,完成http
状态管理。
-
token
机制
https://pan.baidu.com/s/1B3YUiJnd3A2vOGKmkEu0_Q
2prs
- 下载对应版本的微信开发者工具。
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
- 强烈建议申请新邮箱账号。
百度:网易邮箱。
https://mail.163.com/register/index.htm?from=163mail&utm_source=163mail
https://mp.weixin.qq.com
服务号:为企业和组织提供的进行用户管理和服务的账号类型。订阅号:为企业、组织和个人提供的进行信息发布的账号类型。
小程序:为企业、组织或个人提供的可以达到与原生
app
功能相近的应用程序。在微信内部运行,其优点在于小,无需下载安装包,用完就走。小程序接入流程
在微信公众平台首页,注册小程序开发者账号。
- 注册账号。
- 验证邮箱。
- 填写主体信息(个人)。
- 注册成功。
安装微信开发者工具
IDE
。扫码登录后,点击+新建小程序项目。
填写基本信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uuNrJkkO-1648187335442)(C:\Users\web\AppData\Roaming\Typora\typora-user-images\1645601263836.png)]
目录:不能有中文、不能有空格,最后一个目录得是空目录。
AppID
:下拉列表中可以选择AppID
。? 后台管理网站 – 开发管理 – 开发设置 – 看到
AppID
。小程序项目的文件结构
小程序项目中包含的文件类型:
-
.json
文件 配置文件
app.json
在项目的根目录下,定义项目的全局配置参数。
页面.json
在pages
文件夹下,定义单个页面的配置参数。
-
.wxml
文件
模板文件(类似于html
,定义页面结构。但是此处不能使用任何html
标签)
-
.wxss
文件 样式文件
app.wxss
项目的根目录下。定义全局样式。
页面.wxss
在pages
文件夹下。定义单个页面的样式。
-
.js
文件 脚本文件
app.js
项目根目录下。用于创建App
对象。小程序启动时调用,全局唯一。可以把一些共享数据、全局生命周期相关代码定义在这里。
页面.js
pages
文件夹下。每一个页面都会有一个js
文件。通过该js
文件来创建Page
对象来管理当前页面中的脚本代码。当需要显示某页面时就会创建Page
对象,用于初始化页面数据,声明事件处理函数,声明生命周期等脚本代码。
app.json
app.json
用于对小程序进行全局配置。pages
配置项 pages
配置项用于定义当前小程序包含哪些页面(index
)"pages": [
"pages/index/index",
"pages/test/test"
],
新建配置项:
"pages/test/test"
,将会在pages
目录下新增test
目录,test
目录下新增test
四件套。意味着项目又多了一个页面。如果将该配置写在数组的首位,那么test
将会作为项目的首页,启动时自动显示首页。JSON
文件配置的语法
JSON
文件不能写注释。- 字符串必须在双引号之间。
JSON
对象的属性名也必须在双引号之间。 - 数组或对象的最后一个成员后不能加逗号。
window
配置项
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle": "black"
},
tabbar
配置项
"tabBar": {
"color": "#333",
"selectedColor": "#f00",
"list": [{
"text": "电影",
"pagePath": "pages/index/index",
"iconPath": "/images/index_disable.png",
"selectedIconPath": "/images/index_enable.png"
},{
"text": "影院",
"pagePath": "pages/theatre/theatre",
"iconPath": "/images/theatre_disable.png",
"selectedIconPath": "/images/theatre_enable.png"
},{
"text": "我的",
"pagePath": "pages/me/me",
"iconPath": "/images/me_disable.png",
"selectedIconPath": "/images/me_enable.png"
}]
},
style
基础库 2.8.0 开始支持,低版本需做兼容处理。微信客户端 7.0 开始,UI 界面进行了大改版。小程序也进行了基础组件的样式升级。app.json 中配置
"style": "v2"
可表明启用新版的组件样式。本次改动涉及的组件有
button icon radio checkbox switch slider
。可前往小程序示例进行体验。sitemapLocation
用于指明 sitemap.json 的位置;默认为 ‘sitemap.json’ 即在 app.json
同级目录下名字的 sitemap.json
文件。sitemapLocation
的作用是定义一些通用的爬虫规则,指定小程序中那些页面被允许索引注:
sitemap
的索引提示是默认开启的,如需要关闭 sitemap
的索引提示,可在小程序项目配置文件 project.config.json
的 setting
中配置字段 checkSiteMap
为 false
app.wxss
app.wxss
用于定义全局样式。app.js
app.js
在小程序项目根目录下。是小程序全局的初始化脚本。当小程序启动时,就会执行该文件,创建App
对象。 该文件仅执行一次,也就意味着App
对象全局单例(唯一)。App
对象用于定义整个应用程序的生命周期回调方法,全局共享的数据等内容。微信小程序组件库 小程序中
wxml
用于定义页面内容,它由各式各样的组件构成,这些组件都是微信自定义的,原生html
标签不能用。关于组件属性的使用
- 小程序中的组件若含有布尔类型的属性,无论设置为
true
还是false
,小程序都会当做字符串来进行解释,都会被解释为true
。除非用空字符串""
。但是这么写有点野,推荐通过{{}}
引用js
脚本变量,为属性赋值。
- 小程序中组件属性的属性名,既可以使用驼峰命名法,也可以使用短横线命名法,两种属性名的命名习惯小程序都支持。
view
组件view
组件为视图容器组件(类似div
)。 其基本语法:1.如果组件的属性为布尔类型,当我们直接设置属性值为true或false时,都会被当做true来看待(js中非空字符串都为true);除非使用空字符串“ ”,但这么写有点野
属性一般默认false,写上就是true,不写就是false
建议用以下方法:
hover-stop-propagation="{{false}}"
2.小程序组件的属性名既可以使用驼峰命名法,也可以使用短横线命名法,二者够可以正确设置属性
案例:
- 新建页面:
pages/testing/view/view
。 - 该页面中测试应用
view
组件。
let f = true
1 f = 'true'
2 f = 'false'
3 f = 'abc'
4 f = ''
5 f = 1
6 f = -1
7 f = 0
8 f = undefined
9 f = nullif(f){
console.log('真...')
}
image
组件image
组件为图片组件,用于显示图片。支持GIF
、JPG
、PNG
、SVG
、WEBP
等图像格式。其语法如下: mode="aspectFill" //图片在容器居中全部显示,多余的切除
mode="aspectFit" //图片完全在容器中显示,其余空间留黑
mode="scaleToFill"//图片在容器铺满,会失真
案例:
pages/testing/image/image
。wxss
是小程序提供的一套样式语言,也会经过编译来渲染组件样式。wxss
具备了css
的大部分特性。并且对css
进行了扩展,新增了rpx
尺寸单位。rpx
响应式像素 使用rpx
作为尺寸单位来定义组件的宽高,可以根据屏幕的分辨率进行自动转换,在不同的屏幕下会转成不同的px
物理像素值。从而实现屏幕适配。设计规定:无论任何设备,屏幕的宽度都是
750rpx
。由此可知
iphone6
下原始宽度为375px
,用rpx
表示为750rpx
。意味着在iphone6
平台下,1px = 2rpx
。设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
swiper
组件swiper
组件为轮播图组件,其语法为:autoplay="是否自动播放"
indicator-dots="是否显示指示器"
circular="是否采用前后循环播放"
interval="多长时间换下一页"
duration="切换动画的持续时间"
....>
>
>
>
案例:新建
pages/testing/swiper/swiper
。text
组件text
组件用于显示文本的组件,其语法:文本
navigator
组件navigator
组件是页面链接组件,用于控制页面的跳转。其基本语法:
链接文本
open-type
跳转方式有以下几种:navigate
,默认的跳转方式,可以从当前页跳转到非tabbar
页面。跳转的过程将会保留当前页,新建目标页,而后跳转过去,称为保留跳转。navigateBack
,返回上一级页面。这种操作将会销毁当前页,从而显示上一页。可以配合属性delta
实现上n
页的跳转。switchTab
,字面理解为切换标签页(底部选项卡页面)。这种跳转方式用于跳转到tabbar
页面。一旦这么做,就会销毁所有非tabbar
页面。redirect
,这种跳转方式将会关闭当前页,跳转到非tabbar
的目标页面。这种方式也将创建新页面。reLaunch
,字面理解为: 重新启动应用。这种方式将会销毁所有页面。重新打开小程序中的某一个目标页面。
testing/a/a tesing/b/b testing/c/c
。scroll-view
组件scrollview
组件用于实现可滚动的视图容器(支持水平、垂直滚动)。基本结构如下:style="height:200px;
"
scroll-x="是否允许水平方向滚动"
scroll-y="是否允许垂直方向滚动">
....
....
....
...非常多....
案例:
pages/testing/scroll/scroll
。scroll-view
组件scrollview
组件用于实现可滚动的视图容器(支持水平、垂直滚动)。基本结构如下:style="height:200px;
"
scroll-x="是否允许水平方向滚动"
scroll-y="是否允许垂直方向滚动">
....
....
....
...非常多....
案例:
pages/testing/scroll/scroll
。input
组件input
组件为输入框组件,其语法结构:
案例:
pages/testing/input/input
。基于小程序的
input
组件实现双向数据绑定,让文本框中值与data
中的某一个变量实现动态绑定。简易双向数据绑定
wxml
:
输入的是:{{name}}
js
:Page({
data: {
name: ''
}
})
而早期小程序的双向数据绑定需要借助于
bindinput
事件来进行处理。一旦用户在文本框中更新了内容,就会触发该事件,在事件处理函数中获取文本框的值,然后更新data
。标准的双向数据绑定
wxml
{{pwd}}
js
Page({
data:{
pwd: ''
},
inputPwd(event){
let val = event.detail.value// 文本框的值
// 第一种更新data的方式:不会更新界面
this.data.pwd = val
// 第二种更新data的方式:可以自动更新界面中使用pwd的位置
this.setData({ pwd:val })
}
})
WXML
语法基础wxml
是一套标签语言,符合标签语言的相关语法,用于定义页面的结构、内容。在wxml
中经常需要呈现动态数据(动态文本、动态样式、动态属性等),而这些动态数据来源于对应js
文件中data
里声明的变量。就需要使用{{}}
来动态引用。大概有以下几类需求:内容绑定
Page({
data:{
name: 'zs',
age: 15,
userInfo: {}
}
})
{{name}}
{{age}}
属性绑定 当需要动态设置组件的属性值时,就需要使用属性绑定:
Page({
data:{
url: '/images/1.jpg',
num: 1,
d: 'images'
}
})
样式绑定 动态更新组件的
wxss
样式:Page({
data:{
className: 'blue',
c: 'red',
bw: 1
}
})
.red{ color:red;
}
.blue{ color:blue;
}
内容文本
内容文本
列表渲染 基于小程序的提供的列表渲染的语法,可实现遍历数组中每个元素动态输出列表数据的需求。类似
vue
中的v-for
。data: {
foods: [
{id:1, name:'臭豆腐', price:18.0},
{id:2, name:'螺蛳粉', price:15.0},
{id:3, name:'鲱鱼罐头', price:66.0},
{id:4, name:'毛鸡蛋', price:5.0}
]
}
Vue
应如下遍历输出foods
:
id: {{item.id}}
name: {{item.name}}
price: {{item.price}}
微信小程序的语法,应如下遍历输出
foods
:
index: {{index}}
id: {{item.id}}
name: {{item.name}}
price: {{item.price}}
设置后,发现控制台有一个警告,需要为
wx:for
提供一个wx:key
。如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 input 中的输入内容,switch 的选中状态),需要使用
wx:key
来指定列表中项目的唯一的标识符。wx:key
的值以两种形式提供- 字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
- 保留关键字
*this
代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字。
如不提供
wx:key
,会报一个 warning
, 如果明确知道该列表是静态,或者不必关注其顺序,可以选择忽略。
序号:{{index}}
ID: {{item.id}}
菜名:{{item.name}}
价格:{{item.price}}
wx:for
将会为这次遍历默认新增两个变量:item
,index
。这两个变量可以自定修改,语法如下:
序号:{{i}}
ID: {{f.id}}
菜名:{{f.name}}
价格:{{f.price}}
条件渲染 使用条件渲染可以动态处理是否渲染某一个元素,类似
vue
中的v-if
。data:{
islogin: true
}
欢迎:XXX
登录 注册
常见写法有以下几种:
xxx
---------------------------------------------
xxx
xxx
---------------------------------------------
xxx
yyy
zzz
aaa
bbb
小程序常用组件
radio-group
组件radiogroup
组件为单选框组组件,包含一组单选按钮。基本结构:
男
女
radio-group
中的radio
只有一个可以被选中。案例:
testing/form/form
。checkbox-group
组件复选框组件,其语法:
...
...
...
小程序的事件处理
事件是视图层到逻辑层的通讯方式,它可以将用户的行为反馈到逻辑层进行后续处理。
bindscrolltolower="">
bindscrolltoupper="">
bindscroll="">
小程序中的事件类型 微信小程序中,事件类型大致分为两大类:
- 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
- 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
类型 | 触发条件 |
---|---|
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 设备,重按时会触发 |
bind
的方式绑定事件可以应用于任何组件,而bind:
的方式不能应用于原生组件。原生组件指由操作系统直接控制的组件。如:获取焦点后的input
组件、video
组件、camera
组件等。原生组件的特点是由Android
或IOS
操作系统直接处理,并非微信自己实现的UI
或功能。
bind
方式与bind:
方式绑定的事件不能阻止事件冒泡,而catch
方式可以自动阻止事件冒泡。小程序中事件参数的传递 无论组件绑定的是冒泡事件还是非冒泡事件,事件处理函数名称都严禁出现小括号:
问题:如何完成事件参数的传递?
需求:
商品信息.....
商品信息.....
商品信息.....
data: {
items: [{购物项1}, {购物项2}, {购物项3}]
}tapDel(event){
// event.target 获取触发事件的事件源对象 --> Button对象
// event.target.dataset 获取Button上封装了所有的data-*属性的对象
// event.target.dataset.i 获取button组件上的data-i属性值
let i = event.target.dataset.i
}
案例:购物车。
案例:吃饭睡觉打豆豆。
- 查询并显示待办事项列表。
- 添加新的待办事项。
- 删除代办事项。
API
小程序界面交互类API
wx.showToast()
提示框wx.showModal()
模态对话框小程序路由跳转相关
API
- wx.switchTab
- wx.reLaunch
- wx.redirectTo
- wx.navigateTo
- wx.navigateBack
navigator
组件的5中opentype
一一对应,功能完全一致。wx.navigateTo
跳转时的参数传递问题 wx.navigateTo
可以保留当前页,新建目标页,跳转过去。不能跳转到tabbar
页面。在跳转的过程中可以传参,有两种传参的方案:正向传参
假设A跳转到B,同时携带参数,A传参,B接收,这种方式为正向传参。
A页面:
wx.navigateTo({
url: '/pages/testing/b/b?id=10&name=张三&pwd=1234'
})
B页面:
Page({
data: {},
// 系统自动调用,options系统自动传入
// options封装了上一个页面传进来的参数,在此使用options形参接收
onLoad(options){}
})
反向传参
假设A跳转到B,在B页面中进行操作的时候,将参数回传给A,这种方式为反向传参。
A页面,定义一个事件处理函数,接收B返回回来的数据:
wx.navigateTo({
url: 'xxx',
events: {
acceptCity(data){
console.log('接受到了回传回来的数据',data)
}
}
})
B页面处理完业务后,通过事件通道(
EventChannel
)回传数据:let ec = this.getOpenerEventChannel()
ec.emit('acceptCity', 回传的数据)
小程序的生命周期
- 页面的生命周期
- 小程序应用的生命周期
Page.js
中进行定义,基本结构如下:Page({
/** 页面的初始数据 */
data: {
},/** 生命周期函数--监听页面加载 */
onLoad: function (options) {
},/** 生命周期函数--监听页面初次渲染完成 */
onReady: function ()
},/** 生命周期函数--监听页面显示 */
onShow: function () {
},/** 生命周期函数--监听页面隐藏 */
onHide: function () {
},/** 生命周期函数--监听页面卸载 */
onUnload: function () {
},
})
小程序的生命周期
- 页面的生命周期
- 小程序应用的生命周期
Page.js
中进行定义,基本结构如下:Page({
/** 页面的初始数据 */
data: {
},/** 生命周期函数--监听页面加载 仅执行一次 */
onLoad: function (options) {
},/** 生命周期函数--监听页面初次渲染完成 仅执行一次 */
onReady: function ()
},/** 生命周期函数--监听页面显示 执行多次 */
onShow: function () {
},/** 生命周期函数--监听页面隐藏 执行多次 */
onHide: function () {
},/** 生命周期函数--监听页面卸载 仅执行一次 */
onUnload: function () {
},
})
小程序应用的生命周期 整个微信小程序从启动到销毁也会涉及到生命周期,称为小程序应用的生命周期。涉及到的相关生命周期钩子方法需要在
app.js
中进行定义:// app.js
App({
onLaunch(){/** 当应用冷启动时(无运行状态中启动),执行 */},
onShow(){/** 当小程序显示时执行 */},
onHide(){/** 当小程序隐藏到后台时执行 */},globalData: {
// 全局共享数据存储区
}
})
如果需要在页面中访问
globalData
,操作方式如下:向
globalData
中存数据:getApp().globalData.cityname = '北京'
getApp().globalData.userInfo = {id:1, name:xxx,...}
从
globalData
中取数据:getApp().globalData.cityname
getApp().globalData.userInfo.id
getApp().globalData.userInfo.name
小程序网络相关
API
小程序对于发送请求时的一些限制:
在浏览器中验证一个请求资源路径:
- 请求资源路径只支持
https
协议。- 必须使用域名,不能使用
IP
。域名必须经过ICP
备案。- 域名必须在小程序后台管理网站中注册。(登录管理后台,选择开发管理、开发设置、服务器域名配置,新增:
https://api.tedu.cn
)注册完毕的域名才可以在小程序中向该地址发送请求。
https://api.tedu.cn/index.php?cid=1
如果在公司网络访问不了,尝试修改
DNS
:打开资源管理器 – 右键 网络 – 更改适配器设置
右键所使用的网卡 – 属性 – 双击选择
TCP/IP V4
使用下方的
DNS
服务器地址:114.114.114.114
– 确定 – 确定.wx.request()
wx.request({
url: '',
data: '',
method: '',
header: '',
success: (res)=>{},
fail: (err)=>{},
completed: (com)=>{}
})
案例:点击按钮,发送请求
项目案例: 初始化项目
- 新建项目。
- 项目目录不准有空格、中文特殊字符。最后一个目录为空目录。
- 选择正确的
appid
。
- 选择不适用云服务。
- 项目目录不准有空格、中文特殊字符。最后一个目录为空目录。
- 搭建项目的主体结构。
- 准备3个页面:
index
、theatre
、me
。 - 拷贝所有相关资源,搭建底部选项卡的基本结构。
- 准备3个页面:
- 项目细节调整。
在小程序目录里找到project.config.json
,找到setting
配置对象,将checkSiteMap
设置为false
。
实现思路
- 重写
Index.js
中的onLoad
方法。在页面初次加载时发请求,获取热映类别下的首页电影列表数据。 - 通过
wx:for
,完成电影列表渲染。
说明 | |
---|---|
接口地址 | https://api.tedu.cn/index.php |
请求方式 | GET |
请求参数 | cid : 类别ID 热映ID:1 待映ID:2 经典ID:3 offset : 读取记录时的起始下标位置 |
返回值 | 相应类别下的电影列表。 |
https://api.tedu.cn/index.php?cid=1热映电影列表 首页
https://api.tedu.cn/index.php?cid=2待映电影列表 首页
https://api.tedu.cn/index.php?cid=3经典电影列表 首页
访问不同类别的后续数据:
https://api.tedu.cn/index.php?cid=1&offset=20热映电影列表
https://api.tedu.cn/index.php?cid=2&offset=20待映电影列表
https://api.tedu.cn/index.php?cid=3&offset=20经典电影列表
所以当前接口将会返回相应类别下的电影列表数据,返回从
offset
位置开始向后读取20条电影信息组成的数组。[{电影},{电影},{电影},{电影},{电影},{电影}......]
控制顶部导航的选中项
实现思路
- 当选择某一个顶部导航项后,将该导航项改为激活状态,其它导航项改为默认样式。
- 选择某一个顶部导航后,需要获取当前选中项的类别
cid
(1/2/3),向服务端发送请求,获取响应类别下的首页电影列表数据。 - 获取数据后,重新更新电影列表即可。
需求:当列表滚动到底部后,加载当前类别的下一页数据。
实现思路
- 监听列表滚动触底事件。(
Page
中重写onReachBottom
) - 整理请求参数,
cid
类别id
,offset
起始位置。发送新的列表请求,访问下一页电影列表数据。 - 当加载到新数据后,把新电影列表追加到旧电影列表的末尾。
loadData
方法// 该方法的作用:传递两个参数:cid,offset,帮忙发请求
// 返回查询得到的结果
loadData(cid, offset){
return new Promise((resolve, reject)=>{
wx.request({
url: 'https://api.tedu.cn/index.php',
method: 'GET',
data: {cid: cid, offset: offset},
success: (res)=>{
resolve(res.data)
}
})
})
}onLoad(){
this.loadData(1, 0).then(movielist=>{
this.setData({movies: movielist})
})
}
tapNav(){
this.loadData(1, 0).then(movielist=>{
this.setData({movies: movielist})
})
}onReachBottom(){
this.loadData(动态cid, 动态offset).then(movielist=>{
push.......
this.setData()
})
}
小程序缓存设计方案
什么是缓存? 客户端向服务端发送第一次请求试图获取一组数据,当数据下载完毕后,客户端可以将这些数据存入客户端本地缓存中。当下次发送相同请求时,先去本地缓存中搜索,看以前有没有存过,如果有,则直接获取后加载显示;如果没有,再发请求。
所以缓存的机制并不复杂,关键是找对时机进行缓存的存储与读取。
在小程序中如何处理缓存? 微信小程序将
html5
中的webstorage
封装了,提供了一些wxAPI
用于向storage
中存,从storage
中取。缓存的设计方案 一个项目如何实现缓存还需要注重这个项目的业务形态。不同的业务,本地缓存到底存多久需要思考讨论。最终设计一个比较合理的更新缓存的方案。
一般列表展示都会配套一个下拉刷新来更新列表、更新缓存。
有些应用,每次打开时(
App.onLaunch()
)将数据缓存清空。有些应用,更新的频率更高些,就需要在应用使用时,每隔一段时间更新数据缓存。
基于下拉刷新更新缓存
- 在页面的
.json
配置文件中,开启当前页面的下拉刷新。 - 重写
Page
的onPullDownRefresh
方法,监听下拉刷新事件。 - 发送请求,加载当前了类别的首页电影数据,更新列表、更新缓存。
获取小程序的位置,可以使用:
wx.getLocation({
type:'gcj02',
altitude: true,
isHighAccuracy: true,
success:(res)=>{ .... }
})
在
app.json
中配置权限声明:{
"pages": ["pages/index/index"],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
}
如果希望获取当前城市名称等业务数据,就需要接入第三方位置服务。小程序天然配套腾讯位置服务。
腾讯位置服务
打开腾旭位置服务的官方网站:
https://lbs.qq.com
开发文档
=>
微信小程序JS SDK
Hello world!
- 申请开发者密钥(key):申请密钥
- 开通
webserviceAPI
服务:控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI
-> 保存
(小程序SDK
需要用到webserviceAPI
的部分服务,所以使用该功能的KEY
需要具备相应的权限)
- 下载微信小程序
JavaScriptSDK
,微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2
- 安全域名设置,在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加
https://apis.map.qq.com
- 小程序示例
// 引入SDK核心类,js文件根据自己业务,位置可自行放置 var QQMapWX = require('../../libs/qqmap-wx-jssdk.js'); var qqmapsdk = new QQMapWX({ key: '申请的key' }); qqmapsdk.reverseGeocoder({ success: (res)=>{....} })
需求:当点击某一个电影列表项后,跳转到电影详情页面,显示当前电影的详细信息。(需要通过电影
ID
,获取电影详情) 。实现思路
- 准备好电影详情页面。
pages/movie/movie
。 - 点击电影列表项后,跳转到电影详情页,并且传递选中项的电影
id
。 - 在详情页中获取
id
参数,通过id
查询电影详细信息,渲染页面。
ID
查询电影详情接口
说明 | |
---|---|
接口地址 | https://api.tedu.cn/detail.php |
请求方式 | GET |
请求参数 | id: 电影ID |
返回结果 | object 类型,返回电影的详细数据。 |
cover: "https://p1.meituan.net/movie/f6ec2a022d3644ef493f881d359f65303190471.jpg@218w_300h_1e_1c"
description: "如果你喜欢的女孩,得了抑郁症,你该怎么办?辛唐(孙晨竣 饰)拥有通过声音给他人制造快乐的能力,但对同一人使用三次后,性命就会和此人绑定,只有对方开心,辛唐才能活命。偶然,辛唐救下准备自杀的同校网络红人吉择(章若楠 饰),两人借此绑定。吉择表面开朗,但实际患了抑郁症。辛唐最初为了活下去,费尽心思让吉择开心,而后续也真的投入深情。遗憾辛唐的秘密总会败露,而吉择暗黑的过往也在网络上被人揭开....愿爱情的温暖,能治愈抑郁的青春。"
director: [{…}]
moviename: "如果声音不记得"
movietype: "爱情/青春/奇幻"
score: "8.2"
showingon: "2020-12-04"
star: "章若楠/孙晨竣/王彦霖"
thumb: (29) ['', ''......]
完成电影详情的页面渲染
渲染基本信息 渲染演职人员列表 渲染剧照列表
- 图片懒加载。
- 添加
mode
,防止图像比例失真。
- 点击图片后,全屏大图浏览器剧照列表。
wx.previewImage({ current: newUrls[i], urls:newUrls })
开发者可以使用腾讯提供的云服务器来开发微信小程序、小游戏的服务端程序。而无需搭建服务器。
云开发提供的基础能力有:
- 云数据库
云数据库是一个可以在小程序前端直接操作的云端数据库。它与mysql
不同,是一个json
类型的非关系型数据库。
- 云存储
云存储是微信云服务器提供的一块存储空间,可以让小程序前端通过响应API
代码直接针对云存储空间进行上传和下载。
- 云函数
云函数是一个在小程序端进行编写,而后通过开发工具部署到云服务器中,并且提供给小程序远程调用的函数。
打开开发工具,点击工具栏中的云开发按钮。
云数据库 云数据库是一个可以在小程序前端直接操作的云端数据库。它与
mysql
不同,是一个json
类型的非关系型数据库。开通云开发服务
打开开发工具,点击工具栏中的云开发按钮。
云数据库 云数据库是一个可以在小程序前端直接操作的云端数据库。它与
mysql
不同,是一个json
类型的非关系型数据库。mysql
存储数据的结构:id | name | gender | school_id |
---|---|---|---|
1 | zs | m | 1 |
2 | ls | m | 2 |
3 | ww | f | 1 |
… | … | … | … |
school_id | name | loc | area |
---|---|---|---|
1 | 清华大学 | 五道口 | 1000 |
2 | 北京大学 | 中关村 | 850 |
… | … | … | … |
[
{
"id":1,
"name":'zs',
"gender":'m',
"school": {
id: 1,
name: '清华大学',
loc: '五道口',
area: 1000
}
},{
"id":2,
"name":'ls',
"gender":'m',
"school": {
id: 1,
name: '清华大学',
loc: '五道口',
area: 1000
}
},{
"id":3,
"name":'ww',
"gender":'f',
"school": {
id: 2,
name: '北京大学',
loc: '中关村',
area: 850
}
},
]
描述一个云数据库存储的数据:
在云数据库中有一个集合,里面存储了3条记录(3条文档),每一条记录包含四个字段,他们有不同的数据类型,其中school字段又是一个对象,该对象中又包含4个属性,用于描述学校的基本信息。
云数据库的操作
https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/init.html
插入数据
const db = wx.cloud.database({
// env: '云环境的ID (云开发控制台中复制过来)'
env: 'cloud2012-9gl0qd6g8dc72b1c'
})
db.collection('test').add({
data: {新增的对象},
success: (res)=>{
新增数据成功后的回调
}
})
上述代码可以方便的向
test
集合中新增一条记录,我们发现,小程序将会自动为该记录分配唯一的_id
(主键ID
)。同时也会新增字段:_openid
。不同的用户插入数据将会有不同的_openid
,同一个用户添加的记录_openid
是一样的。_openid
字段标识了当前这一条记录属于谁(是哪一个用户创建的)。小程序将会通过
_openid
字段来确定用户对该集合中数据的访问权限。查询数据
db.collection('test').doc('记录的 _id').get({
success: (res)=>{
返回结果后执行回调方法。 res中就是返回的结果
}
})
删除数据 修改数据 实现学子影院项目中的评论列表
- 创建一个新的云开发项目。
xzyycloud
- 将
xzyy
中已经写好的内容,直接拽到新项目中,覆盖相关资源。 - 将
comments.json
中的评论数据导入comments
集合中。 - 在
xzyycloud
项目中,找到电影详情页,在onLoad
生命周期方法中,查询云数据库,获取当前电影的评论列表,遍历渲染。
Collection
对象的常用方法
方法 | 描述 |
---|---|
collection.doc() | 通过id查询一条记录 |
collection.where() | 添加筛选条件 |
collection.get() | 发送请求,查询云数据库 |
collection.add() | 添加数据 |
collection.skip(n) | 跳过前n条 |
collection.limit(n) | 向后查询n条 |
collection.orderby() | 排序 |
collection.remove() | 删除 |
collection.update() | 更新 |
db.collection('test')
.where({
price: _.gt(10)
})
.field({
name: true,
price: true,
})
.orderBy('price', 'desc')
.skip(1)
.limit(10)
.get()
查询指令
假设我们需要查询进度大于 30% 的待办事项,那么传入对象表示全等匹配的方式就无法满足了,这时就需要用到查询指令。数据库
API
提供了大于、小于等多种查询指令,这些指令都暴露在 db.command
对象上。API 提供了以下查询指令:
查询指令 | 说明 |
---|---|
eq | 等于 |
neq | 不等于 |
lt | 小于 |
lte | 小于或等于 |
gt | 大于 |
gte | 大于或等于 |
in | 字段值在给定数组中 |
nin | 字段值不在给定数组中 |
- 准备一个城市列表页面:
pages/citylist/citylist
.
- 完善城市列表页中的列表显示内容。
当点击右侧导航时,控制scrollview
滚动到相应位置。
scroll-into-view="C">
....
- 点击首页左上角城市时,跳转到
citylist
页面,选择城市。
- 城市选择完毕后,后退到首页,并且将选中的城市名称回传回来,更新首页城市名。
选择城市后,将城市名称存入globalData
,然后navigateBack
。
在首页重写onShow
生命周期方法,将会在onShow
时区globalData
中获取城市名称,更新左上角。
- 准备一个城市列表页面:
pages/citylist/citylist
.
- 完善城市列表页中的列表显示内容。
当点击右侧导航时,控制scrollview
滚动到相应位置。
scroll-into-view="C">
....
- 点击首页左上角城市时,跳转到
citylist
页面,选择城市。
- 城市选择完毕后,后退到首页,并且将选中的城市名称回传回来,更新首页城市名。
选择城市后,将城市名称存入globalData
,然后navigateBack
。
在首页重写onShow
生命周期方法,将会在onShow
时区globalData
中获取城市名称,更新左上角。
- 当点击进入城市列表页后,需要重新调用
getLocation
进行定位。(需要把index.js
中封装好的getLocation
方法复制过来一份直接用) - 获取到当前定位城市名后,将
cityname
存入globalData
,更新citylist
页面顶部的定位城市名称。 - 当点击顶部当前定位城市按钮时,需要将城市名称存入
globalData
,返回上一页即可。 - 首页将会在
onShow
是更新首页左上角,完成业务流程。
- 拒绝授权。
- 点击城市名,进入城市列表页。定位失败后提示重试。
- 点击重试弹出引导授权窗口。
- 授权成功后重新定位,完成业务。
影院页面左上角城市与首页左上角城市实现联动
- 重写影院页面的
onShow
生命周期方法,读取globalData.cityname
,更新左上角城市名。
https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/methodSearch
实现思路
- 将获取
qqmapsdk
的方法封装到app.js
中,通过globalData
暴露qqmapsdk
的引用。 - 什么时候需要,就直接从
globalData
中读取qqmapsdk
即可。index.js
中需要。citylist.js
中需要。theatre.js
中需要。
- 通过
qqmapsdk
调用search
方法,获取选中城市的影院列表。 - 将
theatreList
存入data
,在页面中渲染显示该列表。 - 细节处理:
- 若影院没有电话,则样式有问题。
- 距离应该显示
km
,保留两位小数。 - 如果不是当前城市的电影院,不会返回距离。
event.target
与event.currentTarget
之间的区别
tapV1(event){
// 当用户点击了v2, 触发tapv1,那么:
event.target // 指的是v2,因为真正直接被点击的元素是v2
event.currentTarget // 指的是v1,因为bindtap绑定到了v1上// 当用户点击了v1,触发tapv1,那么:
event.target // 指的是v1,因为真正直接被点击的元素是v1
event.currentTarget // 指的是v1,因为bindtap绑定到了v1上
}
自定义组件 从小程序基础库版本 1.6.3 开始,小程序支持简洁的组件化编程。所有自定义组件相关特性都需要基础库版本 1.6.3 或更高。
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
doubletapEvent(){
console.log('么么哒..')
}
自定义简单组件
- 对
components
右键,新建Component
, 起名字,新建组件。
- 编写
组件.wxml 组件.wxss
。
- 在需要引用组件的页面中,通过自定义组件名使用该组件。
- 前提就是在该
页面.json
,需要声明引入该组件:
{ "usingComponents": { "my-button": "/components/mybutton/mybutton" } }
开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
doubletapEvent(){
console.log('么么哒..')
}
自定义简单组件
- 对
components
右键,新建Component
, 起名字,新建组件。
- 编写
组件.wxml 组件.wxss
。
- 在需要引用组件的页面中,通过自定义组件名使用该组件。
- 前提就是在该
页面.json
,需要声明引入该组件:
{ "usingComponents": { "my-button": "/components/mybutton/mybutton" } }
Vant
组件库- 安装
vant
。
# 进入项目根目录, xzyycloud文件夹下执行命令: npm init# 输入命令后一路回车,将会自动创建package.json npm i @vant/weapp -S --production
- 修改
app.json
.
将app.json
中的"style": "v2"
去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。
- 修改
project.config.json
。
"packNpmManually": true, "packNpmRelationList": [ { "packageJsonPath": "./package.json", "miniprogramNpmDistDir": "./miniprogram/" } ],
如上配置的目的,是希望小程序开发工具在构建npm
时,可以找到package.json
, 还需要定义编译后的输出目录(./miniprogram/
)。
- 在小程序开发工具中构建
npm
。
一旦构建npm
成功,将会在miniprogram
目录下新增miniprogram_npm
文件夹,里面就是打包好的组件源码。接下来就可以直接引入,使用。
Vant
组件库中的Button
: 引入在页面的
.json
文件中引入该组件:{
"usingComponents": {
"my-button": "/components/mybutton/mybutton",
"van-button": "@vant/weapp/button/index"
}
}
使用
默认按钮
主要按钮
信息按钮
警告按钮
危险按钮
显示失败的,清除编译缓存,重新编译多尝试。
实现微信登录业务
- 当点击登录时,申请用户授予获取用户基本信息的权限。
- 一旦用户允许,则可以得到用户的昵称、头像的等基本数据。
- 更新界面(昵称、头像)。
API
方法,可以获取用户数据:wx.getUserProfile()
:实现重新选择图片,更新头像
- 点击头像后,选择新图片。
- 获取选中图片的路径,替换头像路径。(
userInfo.avatarUrl
)
选择图片的方法:
wx.chooseImage()
wx.getUserProfile()
的作用是让用户方便的提供个人微信昵称与头像。以此来证明当前用户的身份。而一个完整的微信登录业务,必然需要将这些用户信息存入自己家数据库中。(例如,存入mysql
中的user
表里)id | _openid | name | phone | nickName | avatarUrl | gender | … |
---|---|---|---|---|---|---|---|
1 | ovoaabbc | xuming | 13333… | 徐铭 | https://xx.jpg | m | … |
2 | aabbcdefg | lisi | 144 | … | https://xxxx.jpg | f | … |
所以一个正确的微信登录业务如下:
- 通过微信登录,获取用户的基本信息。
- 通过用户的信息,判断,该用户在自己家数据库中是否已注册:
- 如果没有注册,则在自己家数据库中新增一条数据,保存该用户信息,显示界面即可。
- 如果已经注册过,则找到自己家数据库中最新的用户数据(有可能头像、昵称已经被改过),将自家数据库中的信息更新到界面。
- 在云开发控制台中新建一个集合:
users
。 保存用户信息。 - 完成用户登录业务。
- 查询云数据库,检索当前用户以前是否已经注册过信息。
- 如果没有找到数据,则执行注册业务。将用户信息存入云数据库
users
集合。 - 如果找到了数据,则执行登录业务,将这些用户最新的数据,更新到界面中。
当登录成功后,点击头像,选择本地图片,将头像更新为选中的图片临时路径既可以修改显示的头像。但是这种方式只是纯客户端版本的更新头像,无法持久化保存信息。意味着下次登录时,还会显示微信头像。这是有问题的。
真正的修改头像业务流程如下:
- 点击头像选择一张新图片,获取图片路径。
wx.chooseImage()
- 将该头像上传至服务器,存到服务器某个目录下,并且返回可以访问它的网络路径。
http://api.tedu.cn/avatar/23dfad6fas98df6sdf5sd8fads9f.jpg
- 获取访问路径后,将该路径更新到云数据库中
users
集合里当前用户的avatarUrl
字段。
let db = wx.cloud.database() db.collection('users').doc('_id').update({ data: { avatarUrl : xxxxxx } })
- 一旦数据库中头像地址变了,下次登录时将会加载最新的头像路径,从而访问到上传的头像图片,完成业务。
云存储类似云盘,可以在小程序客户端方便的上传、下载文件。可以在云开发控制台中测试相应功能。
小程序提供了
API
,方便的实现文件上传操作:wx.cloud.uploadFile({
filePath: '本地文件路径',
cloudPath: '云存储服务端的目标文件路径',
success: (res)=>{}
})
思考:如果没有使用云数据库,使用的是自己家的mysql数据库存储用户数据,那么如何完成头像路径的更新?
没有使用小程序云数据库意味着什么?
- 注册用户时,向自建的
users
表中添加一条新纪录。
insert into users(id, nickName, avatarUrl, gender, ) values(?,?,?,?)
- 注册业务看似简单,但是有个棘手的问题,注册之前得先判断
users
表中是否包含当前用户的信息?
答案:通过每个用户每个应用唯一的_openid
来解决这个问题。
id
(_openid
)。用户一旦进入小程序,就会被分配一个openid
。获取openid
的方式比较麻烦:- 客户端需要先调用
wx.login
方法,获取一个校验码。 - 将校验码发给后端
nodejs
接口,后端将会通过该校验码,访问腾讯服务器,换取openid
返回给客户端。
openid
。云函数
云函数是一种在小程序端编写、定义,通过开发工具部署到云服务器中,在小程序端可以远程调用的函数。这种函数在云服务器中执行。所以云函数可以简单替代
nodejs
后端接口。【web前端|微信小程序】体验云函数。
推荐阅读
- 浙里办|浙里办接入h5(vue项目)------相关流程说明
- GitHub|GitHub克隆项目没数据,后台管理权限项目等,解决方法
- 前端优秀开源项目|cnchar - 功能全面、支持多端的汉字拼音笔画开源 JS 库
- java|深入理解JavaScript作用域和作用域链
- js高级程序设计|js高级程序设计(第二章)
- Linux|Let‘s Encrypt申请ssl证书
- webpack 配置以及手写 plugins
- 一文读懂蓝绿发布、A/B 测试和金丝雀发布的优缺点
- 图表|9款主流图表控件轻松实现数据可视化