微信小程序

微信小程序

小程序官网

https://mp.weixin.qq.com/

开发工具

https://developers.weixin.qq.com/miniprogram/dev/devtools/stable.html

1 小程序概述

微信小程序是一种运行在微信内部的 轻量级 应用程序

小程序无需下载和安装,只需要在微信中下拉,搜一搜 或 扫一扫 搜索点击使用即可

2 创建项目

不使用云服务

# 云开发
# IaaS基础设施服务
IaaS: Infrastructure-as-a-Service(基础设施即服务)
第一层叫做IaaS,有时候也叫做Hardware-as-a-Service,几年前如果你想在办公室或者公司的网站上运行一些企业应用,你需要去买服务器,或者别的高昂的硬件来控制本地应用,让你的业务运行起来。
但是现在有IaaS,你可以将硬件外包到别的地方去。IaaS公司会提供场外服务器,存储和网络硬件,你可以租用。节省了维护成本和办公场地,公司可以在任何时候利用这些硬件来运行其应用。
一些大的IaaS公司包括Amazon, Microsoft, VMWare, Rackspace和Red Hat.
# paas平台即服务
第二层就是所谓的PaaS,某些时候也叫做中间件。你公司所有的开发都可以在这一层进行,节省了时间和资源。
PaaS公司在网上提供各种开发和分发应用的解决方案,比如虚拟服务器和操作系统。这节省了你在硬件上的费用,也让分散的工作室之间的合作变得更加容易。网页应用管理,应用设计,应用虚拟主机,存储,安全以及应用开发协作工具等。
一些大的PaaS提供者有Google App Engine,Microsoft Azure,Force.com,Heroku,Engine Yard。最近兴起的公司有AppFog, Mendix 和 Standing Cloud
# saas软件即服务
第三层也就是所谓SaaS。这一层是和你的生活每天接触的一层,大多是通过网页浏览器来接入。任何一个远程服务器上的应用都可以通过网络来运行,就是SaaS了。
你消费的服务完全是从网页如Netflix, MOG, Google Apps, Box.net, Dropbox或者苹果的iCloud那里进入这些分类。尽管这些网页服务是用作商务和娱乐或者两者都有,但这也算是云技术的一部分。
一些用作商务的SaaS应用包括Citrix的GoToMeeting,Cisco的WebEx,Salesforce的CRM,ADP,Workday和SuccessFactors
# 总结
iass基础设施服务(组装机):你买了一大堆电脑配件,cpu 主板..然后组装完成后 装上系统就可以上网。还要自己提供场地 环境
paas平台即服务(品牌机):买回来开机就行。需要自己提供场地,和环境(电源)
saas软件即服务(去网吧):电脑,场地,环境(电源,网线,饮料)都是网吧提供的服务

image-20240523153935721

本地开发支持http

# django 运行在 0.0.0.0 的地址
# 小程序默认只支持https,我们需要做如下配置,让其支持http,方便我们本地开发
右上角详情-->本地设置-->不校验合法域名

3 项目目录

# 1 项目主配置文件
项目主配置文件必须放到项目的根目录下,控制整个项目
- app.js: 小程序入口文件
- app.json:小程序的全局配置文件
- app.wxss:小程序的全局样式
-app.js 和 app.json 文件是必须的,不能没有
# 2 页面文件
小程序有一个个页面,每个页面所需的文件,都存放在 pages 目录下,一个页面一个文件夹
-xx.js: 页面逻辑 js代码存放位置
-xx.wxml:页面结构 类html文件存放位置
-xx.wxss:页面样式 css存放位置
-xx.json:小页面配置
-xx.js 文件和 xx.wxml 文件是必须的,不能没有
# 3 相关配置文档
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html
├── components 【页面中使用的组件】
├── pages 【页面文件目录】
│   ├── index 【页面】
│   │   ├── index.js 【页面JS】
│   │   ├── index.json 【页面配置】
│   │   ├── index.wxml 【页面HTML】
│   │   └── index.wxss 【页面CSS】
│   └── logs 【页面】
│   ├── logs.js ...
│   ├── logs.json ...
│   ├── logs.wxml ...
│   └── logs.wxss ...
├── utils 【自定义工具】
│ └── utils.js 【功能的定义】
├── app.js 【全局JS】
├── app.json 【全局配置】
├── app.wxss 【全局CSS】
├── project.config.json 【开发者工具默认配置】
├── project.private.config.json 【开发者工具用户配置,在这里修改,优先用这个,可以删除】
├── .eslintrc.js 【ESlint语法检查配置】
├── sitemap.json 【微信收录页面,用于搜索,上线后,搜索关键字就可以搜到我们】

3.1 配置文件

app.json

#1 小程序全局配置文件,用于配置小程序的一些全局属性和页面路由
#2 参考地址
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/app.html
# 3 app.json 配置
{
"entryPagePath": "pages/login/login", # 进入的时候访问的页面
"pages": [
"pages/index/index",
"pages/login/login"
],
"window": {
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "微信接口功能演示",
"backgroundColor": "#eeeeee",
"backgroundTextStyle": "light"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}

页面局部配置头

# 1 小程序页面配置文件,也称局部配置文件,用于配置当前页面的窗口样式、页面标题等
# 2 app.json 中的部分配置,也支持对单个页面进行配置,可以在页面对应的 .json 文件来对本页面的表现进行配置。
# 3 页面中配置项在当前页面会覆盖 app.json 中相同的配置项(样式相关的配置项属于 app.json 中的 window 属性,但这里不需要额外指定 window 字段),具体的取值和含义可参考全局配置文档中说明\
# 4 参考
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/page.html
# 5 参考配置
{
"usingComponents": {},
"navigationBarTitleText": "登录页面", # bar标题
"navigationBarBackgroundColor": "#fff",# bar颜色
"enablePullDownRefresh": true, # 是否下拉刷新
"backgroundTextStyle": "light"
}
{
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTitleText": "index"
}

整个项目配置文件

# project.config.jsonproject.private.config.json
# 小程序项目的配置文件,用于保存项目的一些配置信息和开发者的个人设置
# 参考
https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html

搜索相关配置

# 微信现已开放小程序内搜索,开发者可以通过 sitemap.json 配置,或者管理后台页面收录开关来配置其小程序页面是否允许微信索引。当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索词条触发该索引时,小程序的页面将可能展示在搜索结果中。 爬虫访问小程序内页面时,会携带特定的 user-agent:mpcrawler 及场景值:1129。需要注意的是,若小程序爬虫发现的页面数据和真实用户的呈现不一致,那么该页面将不会进入索引中
# 参考文档
https://developers.weixin.qq.com/miniprogram/dev/reference/configuration/sitemap.html

3.2 WebView渲染模式

# 1 默认使用Skyline 渲染模式,支持最新的基础库,不支持低版本客户端
-打开app.json ,去掉 三个配置项
"renderer": "skyline",
"rendererOptions": {
"skyline": {
"defaultDisplayBlock": true,
"disableABTest": true,
"sdkVersionBegin": "3.0.0",
"sdkVersionEnd": "15.255.255"
}
},
"componentFramework": "glass-easel",

纯净项目

image-20240523163657035

新建页面

# 1 在pages上,新建文件夹,logs
# 2 在文件夹上,右键--》新建页面,写上名字logs
-创建出四个文件
# 3 新建页面可以直接在app.json中增加一行,pages下会自动创建出一个页面
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/login/login"
],

image-20240523163802526

调整页面显示顺序

# app.json,谁在第一行,一打开小程序就显示哪个页面
"pages": [
"pages/index/index",
"pages/logs/logs",
"pages/login/login"
],
# 进入时显示的页面
"entryPagePath": "pages/index/index",

4 常用组件

https://developers.weixin.qq.com/miniprogram/dev/component/

  • text,类似于span

    <text>Justin</text>
  • view,类似于div

    <view>
    <view>Python山顶会</view>
    <view>Justin</view>
    <view>微信:616564099</view>
    </view>
  • image,类似于img标签

    <image src="/images/1.png" style="width: 750rpx;height: 400rpx;"></image>
  • icon

    <icon type="success" size='198rpx' color="red"/>
    <icon type="download" size='198rpx' color="#ddd"/>
    success, success_no_circle, info, warn, waiting, cancel, download, search, clear
  • 跳转,类似于a标签

    <navigator class="menu" url="/pages/login/login">
    <label class="fa fa-superpowers" style="color:#32CD32"></label>
    <view>登录</view>
    </navigator>
  • 绑定事件,在js中跳转

<view bindtap="clickMe" data-nid="123">点我跳转</view>
Page({
clickMe:function(e){
var nid = e.currentTarget.dataset.nid;
console.log(nid);
wx.navigateTo({
url: '/pages/login/login'
})
}
})
  • 跳转到其他页面之后,可以在onLoad中获取参数,例如:
wx.navigateTo({
url: '/pages/login/login?name=justin'
})
Page({
onLoad: function (options) {
console.log(options);
}
})

4.1 尺寸单位和样式

rpx

# rpx 可以根据不同的手机屏幕进行自动调整,自适应缩放
-无论什么手机--》屏幕宽度都是 750rpx
# xx.wxml
<view class="box">Justin</view>
# xx.wxss
.box {
width: 375rpx;
height: 500rpx;
background-color: pink;
}

局部样式app.wxss

.box {
width: 400rpx;
height: 400rpx;
background-color: greenyellow;
}

全局样式xxx.wxss

# 局部覆盖全局
.box {
width: 375rpx;
height: 600rpx;
background-color: pink;
}

5 tabbar配置

"tabBar": {
"selectedColor": "#b4282d",
"position": "bottom",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "images/home.png",
"selectedIconPath": "images/home_select.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "images/my.png",
"selectedIconPath": "images/my_select.png"
}
]
},

6 首页案例

轮播图

swiper+swiper-item

<swiper
autoplay
interval="2000"
indicator-dots
indicator-color="#00FF00"
indicator-active-color="#70DB93"
circular
>
<swiper-item>
<image src="/images/banner1.jpg" mode="widthFix"/>
</swiper-item>
<swiper-item>
<image src="/images/banner2.png" mode="widthFix"/>
</swiper-item>
<swiper-item>
<image src="/images/banner3.jpg" mode="widthFix"/>
</swiper-item>
</swiper>

提示

<view class="tips"><text class="iconfont icon-tongzhi2">欢迎使用物业平台,消息提示~~</text></view>
.tips {
margin: 30rpx 10rpx 30rpx 10rpx;
background-color: #f5eedf;
color: #e9ab4e;
padding: 18rpx;
border-radius: 50rpx;
font-size: 18rpx;
}

flex布局

<view class="menu">
<view class="item">
<image src="/images/menu/ht.png" class="img"/>
<text class="title">物业合同</text>
</view>
<view class="item">
<image src="/images/menu/wyf.png" class="img"/>
<text class="title">物业费</text>
</view>
<view class="item">
<image src="/images/menu/wygl.png" class="img"/>
<text class="title">物业管理</text>
</view>
<view class="item">
<image src="/images/menu/wylx.png" class="img"/>
<text class="title">物业维修</text>
</view>
<view class="item">
<image src="/images/menu/ht.png" class="img"/>
<text class="title">物业合同</text>
</view>
<view class="item">
<image src="/images/menu/wyf.png" class="img"/>
<text class="title">物业费</text>
</view>
<view class="item">
<image src="/images/menu/wygl.png" class="img"/>
<text class="title">物业管理</text>
</view>
<view class="item">
<image src="/images/menu/wylx.png" class="img"/>
<text class="title">物业维修</text>
</view>
</view>
.menu{
display: flex;
justify-content: space-between;
padding: 16rpx;
border-radius: 10rpx;
flex-wrap:wrap;
background-color: powderblue;
}
.item{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 150rpx;
height: 200rpx;
border: rgb(192, 251, 255) solid 1rpx ;
margin: 1rpx;
background-color: powderblue;
}
.title{
margin-top: 12rpx;
font-size: 24rpx;
}
.img{
width: 88rpx;
height: 88rpx;
border-radius: 10rpx;
}

通知布局

<view class="notice">
<image src="/images/home/board.png" mode="aspectFit" style="width: 200rpx; height: 100rpx;"/>
<text>通知公告</text>
</view>
.notice{
display: flex;
justify-content: flex-start;
margin-top: 20rpx;
margin-bottom: 20rpx;
}
.notice text{
flex-grow:1
}

底部布局

<view class="bottom">
<view>
<image src="/images/home/cute_1.jpg" mode="scaleToFill" />
</view>
<view >
<image src="/images/home/cute_2.jpg" mode="scaleToFill" />
</view>
<view>
<image src="/images/home/cute_3.jpg" mode="scaleToFill" />
</view>
<view >
<image src="/images/home/cute_4.jpg" mode="scaleToFill" />
</view>
</view>
.bottom{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.bottom>view>image{
width: 345rpx;
padding: 10rpx;
height: 200rpx;
}

引入矢量图标库

https://www.iconfont.cn/

# 1 我的项目--项目设置--》打开base64
# 2 选择font class --》生成代码--》点击链接地址打开
# 3 把打开的链接地址内容复制到项目中
-static/css/iconfont.wxss
# 4 在app.wxss中引入
@import "/static/css/iconfont.wxss";
# 5 在想用图标的位置,加入text组件
<text class="iconfont icon-anquan">

7 bindtap事件绑定

默认会触发事件冒泡,如果不想有冒泡使用catch:tap

写法一

bind:tap=''

写法二

bindtap=''

// 方式一
<button size='mini' type="primary" loading bind:tap='handleClick'>点我</button>
// 方式二
<button size='mini' type="primary" loading bindtap='handleClick'>点我</button>
// index.js
Page({
handleClick(){
console.log('我的第一个点击事件')
}
})

7.1 catchtap阻止事件冒泡

<view style="height:300rpx;display: flex;justify-content: center;align-items: center; background-color: pink;" bind:tap="handleView1">
<button type="warn" plain bind:tap="handleButton1">冒泡案例</button>
</view>
<view style="height:300rpx;display: flex;justify-content: center;align-items: center; background-color: orange;" bind:tap="handleView2">
<button type="primary" plain catch:tap="handleButton2">阻止事件冒泡</button>
</view>
handleView1() {
console.log("view1被点了")
},
handleButton1() {
console.log("button1被点了")
},
handleView2() {
console.log("view2被点了")
},
handleButton2() {
console.log("button2被点了")
},

7.2 事件对象和传参

data-自定义属性名=''

mark:自定义属性名=''

currentTarget:
指向事件绑定的元素。
无论点击的实际元素是哪一个,currentTarget 始终是事件监听器所绑定的那个元素。
target:
指向事件触发的实际元素。
target 表示用户触发事件时的最深层的元素,即用户实际点击的那个元素。
<view>
# 默认会携带一个event过去
<button bindtap="handleButton">点我传参</button>
</view>
// index.js
Page({
handleButton(event){
console.log(event)
},
})

image-20240524151837264

<view>
<button bindtap="handleButton" data-name="heart" data-age="19" mark:height="181">点我传参</button>
</view>
// index.js
Page({
handleButton(event){
console.log(event) // {type: "tap", timeStamp: 47356, target: {…}, currentTarget: {…}, mark: {…}, …}
console.log(event.mark.height) // 181
console.log(event.currentTarget.dataset.name) // heart
console.log(event.target.dataset.age) // 19
}
})

7.3 navigator页面跳转

wxml跳转 : 组件跳转,声明式导航

# 普通跳转
<view>
<navigator url="/pages/test/test"><button>跳转</button></navigator>
</view>

open-type 属性

navigate : 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面

redirect : 关闭当前页面,跳转到应用内的某个页面。但不能跳转到 tabbar 页面

switchTab : 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

reLaunch : 关闭所有页面,打开到应用内的某个页面

navigateBack : 关闭当前页面,返回上一页面或多级页面,默认只能返回一页,通过delta控制返回层级,delta="2"

携带参数跳转

注意跳转tabbar不能携带参数

<view>
<navigator url="/pages/log/log?name=heart&age=18" open-type="navigate">跳转到log页</navigator>
</view>
# 在log中的js里onLoad的options中获取参数
onLoad(options) {
console.log(options) # {name: "heart", age: "18"}
}

js跳转 : 编程式导航

<button type="default" bind:tap="handlenavigateTo">navigateTo</button>
<button type="warn" bind:tap="handleredirectTo">redirectTo</button>
<button type="primary" bind:tap="handleswitchTab">switchTab</button>
<button type="default" bind:tap="handlereLaunch">reLaunch</button>
<button type="warn" bind:tap="handlenavigateBack">navigateBack</button>
// index.js
Page({
handlenavigateTo(){
wx.navigateTo({
url: '/pages/test/test?name=heart&age=18',
});
},
handleredirectTo(){
wx.redirectTo({
url: '/pages/log/log',
})
},
handleswitchTab(){
wx.switchTab({
url: '/pages/test/test',
})
},
handlereLaunch(){
wx.reLaunch({
url: '/pages/log/log',
})
},
handlenavigateBack(){
// 关闭当前页面,返回上一页或上某一页,传入数字
wx.navigateBack()
wx.navigateBack({
delta:2
})
}
})

8 wxml语法

8.1 模版语法

  • 在页面 xx.js 的 Page() 方法的 data 对象中进行声明定义
  • 在xx.wxml 中使用 {{}} 包裹,显示数据
  • 可以显示如下,不能编写js语句或js方法
    • 变量
    • 算数运算
    • 三元运算
    • 逻辑判断
  • 只是单纯通过赋值,js中变量会变化,但是wxml中的页面不会变化,没有联动效果,需要使用setData()方法修改
  • input 双向绑定 model:value='{{变量}}'

8.2 setData

8.1.1 修改变量

<view>{{name}}</view>
<view><button bind:tap="handleChange">点我换名字</button></view>
// index.js
Page({
data:{
name:'heart'
},
handleChange(){
/this.data.name='god'
this.setData({
name:'god'
})
}
})

8.1.2 修改对象

<view>{{userinfo.name}}</view>
<view>{{userinfo.age}}</view>
<view><button bind:tap="handleChange">点我换名字</button></view>
// index.js
Page({
data:{
userinfo:{
name:'heart',
}
},
handleChange(){
this.setData({
'userinfo.name':'god',
'userinfo.age':20
})
}
})

简写形式1 解压赋值

// index.js
Page({
data: {
userinfo: {
name: 'heart',
}
},
handleChange() {
// 修改多个数据--》简便方案--》展开运算符
const userinfo = {
...this.data.userinfo,
name: '新名字',
hobby: '乒乓球'
}
this.setData({
// userinfo:userinfo
userinfo //简写形式
})
}
})

**简写形式2 **Object.assign 更新

// index.js
Page({
data: {
userinfo: {
name: 'heart',
}
},
handleChange() {
// 修改多个数据--》简便方案-->assign
const userinfo = Object.assign(this.data.userinfo, {
name: 'god',
hobby: '烫头'
})
this.setData({
// userinfo:userinfo
userinfo //简写形式
})
}
})

删除数据

// index.js
Page({
data: {
userinfo: {
name: 'heart',
}
},
handleChange() {
//删除数据-->单个
delete this.data.userinfo.name // 页面删除不了,需要用setData更新
this.setData({
userinfo: this.data.userinfo
})
//删除数据-->多个--解构赋值
const {
name,
age,
...res
} = this.data.userinfo
this.setData({
userinfo: res
})
}
})

8.1.3 修改数组

增加数组

// 增加再设置值
// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
handleChange() {
this.data.names.push('彭于晏')
this.setData({
names: this.data.names
})
}
})

通过数组拼接

// 增加再设置值
// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
handleChange() {
const newList=this.data.names.concat("吴彦祖")
this.setData({
names:newList
})
}
})

通过解构赋值

// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
handleChange() {
const newList = [...this.data.names, "李白"]
this.setData({
names: newList
})
}
})

修改数组

// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
handleChange() {
this.setData({
'names[1]': 'heart'
})
}
})

删除数组

删除数组中第一个位置的参数(不是索引)

// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
handleChange() {
this.data.names.slice(1)
this.setData({
names: this.data.names.slice(1)
})
}
})

8.3 列表渲染

<view wx:for="{{names}}" wx:key="*this" wx:for-item='goods' wx:for-index="in">
{{goods}}
{{in}}
</view>
// index.js
Page({
data: {
names: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈']
},
})

image-20240524163357940

8.4 条件渲染

<view>
<input type="text" model:value='{{score}}' style="border:orange solid 1rpx"/>
<view wx:if="{{score>=90&&score<=100}}">优秀</view>
<view wx:elif="{{score>=80&&score<90}}">良好</view>
<view wx:elif="{{score>=60&&score<80}}">及格</view>
<view wx:else>不及格</view>
</view>

image-20240524163444805

wx:if和hidden

  • 使用 wx:if:适用于需要条件渲染,并且元素在隐藏时不需要保留在 DOM 中的场景。适合需要频繁切换显示状态,并且希望提高性能的场景。
  • 使用 hidden:适用于需要频繁显示和隐藏,但不希望元素被销毁和重新创建的场景。适合需要保留元素在 DOM 中,不希望触发生命周期函数的场景。
<view>
<image src="/static/img/b.jpg" mode="widthFix" wx:if="{{showPhoto}}"/>
<button bind:tap="handleShowPhoto" plain="true" type="primary" size="mini">显示隐藏图片(if)</button>
<view></view>
<image src="/static/img/b.jpg" mode="widthFix" hidden="{{showPhotoHidden}}"/>
<button bind:tap="handleShowPhotoHidden" plain="true" type="primary" size="mini">显示隐藏图片(hidden)</button>
</view>
// index.js
Page({
data: {
showPhoto:true,
showPhotoHidden:true
},
handleShowPhoto(){
this.setData({
showPhoto:!this.data.showPhoto
})
},
handleShowPhotoHidden(){
this.setData({
showPhotoHidden:!this.data.showPhotoHidden
})
},
})

9 发送网络请求

wx.request

上线项目发送网络请求的域名,必须在微信公众平台配置->开发管理->服务器域名

image-20240524164333718

本地开发只需要勾上不校验合法域名即可

image-20240524164402589

<swiper autoplay interval="2000" indicator-dots indicator-color="#00FF00" indicator-active-color="#70DB93" circular>
<swiper-item wx:for="{{bannerlist}}" wx:key="*this">
<image src="{{item.image}}" mode="widthFix" />
</swiper-item>
</swiper>
<button type="warn" plain bindtap="handleLoad">点我加载
</button>
// index.js
Page({
data: {
bannerlist: []
},
handleLoad() {
wx.showLoading({
title: '正在加载',
mask:true // 显示透明蒙层
})
wx.request({
url: 'http://127.0.0.1:8000/api/v1/home/banner/',
method: 'get',
success: (res) => {
this.setData({
bannerlist: res.data.results
})
},
fail: err => {
console.log(err)
},
complete: () => {
console.log('无论如何都执行')
wx.hideLoading()
}
})
}
})
wx.request({
url: 'https://example.com/api', // 请求的 URL
method: 'GET', // 请求方法
data: {}, // 请求参数 带在request.GET中
header: {}, // 请求头
success: function(res) {
// 成功回调函数
console.log(res.data);
},
fail: function(err) {
// 失败回调函数
console.error(err);
},
complete: function() {
// 完成回调函数(成功或失败都会执行)
}
});
wx.request({
url: 'https://example.com/api',
method: 'POST',
data: {
param1: 'value1',
param2: 'value2'
},
header: {
'Content-Type': 'application/json' // 根据需要设置请求头
},
success: function(res) {
console.log(res.data);
},
fail: function(err) {
console.error(err);
}
});

10 对话框

10.1 模态框

res.confirm : 确认

res.cancel : 取消

<button type="default" bind:tap="showModel">弹出模态框</button>
// index.js
Page({
showModel(){
wx.showModal({
title: '这是标题',
content: '这是内容',
complete: (res) => {
if (res.cancel) {
console.log('用户取消了')
}
if (res.confirm) {
console.log('用户确认了')
}
}
})
}
})

image-20240524165705183

10.2 消息框

<button type="default" bind:tap="showToast">弹出消息框</button>
// index.js
Page({
showToast(){
wx.showToast({
title: '你好heart!',
icon:"success",
duration:2000
})
}
})

image-20240524165711338

11 本地存储

在调试窗口中可以通过appdata看到当前页面中的变量,及变量变化

同步

wx.setStorageSync : 设置数据

wx.getStorageSync : 获取数据

wx.removeStorageSync : 删除指定数据

wx.clearStorageSync : 清空数据

<button type="default" plain bind:tap="handleSave">存储数据</button>
<button type="primary" plain bind:tap="handleGet">获取数据</button>
<button type="default" plain bind:tap="handleDelete">删除数据</button>
<button type="primary" plain bind:tap="handleClear">清空数据</button>
// index.js
Page({
handleSave() {
wx.setStorageSync('name', "heart")
wx.setStorageSync('userinfo', {name:'god',age:18})
},
handleGet() {
const name=wx.getStorageSync('name')
const userinfo=wx.getStorageSync('userinfo')
console.log(name)
console.log(userinfo)
},
handleDelete() {
wx.removeStorageSync('name')
},
handleClear() {
wx.clearStorageSync()
}
})

image-20240524165941234

异步

wx.setStorage : 设置数据

wx.getStorage : 获取数据

wx.removeStorage : 删除指定数据

wx.clearStorage : 清空数据

// index.js
Page({
handleSave() {
wx.setStorage({
key:'name',
data:"heart"
})
wx.setStorage({
key:'userinfo',
data:{name:'god',age:18}
})
},
async handleGet() {
const name= await wx.getStorage({
key:'name',
success:res=>{
console.log(res) // {errMsg: "getStorage:ok", data: "heart"}
const data = res.data
console.log(data) // heart
}
})
const userinfo= await wx.getStorage({key:'userinfo'})
},
handleDelete() {
wx.removeStorage({key:'name'})
},
handleClear() {
wx.clearStorage()
}
})

12 上拉下拉加载

下拉刷新 : onPullDownRefresh,stopPullDownRefresh

上拉加载 : onReachBottom

12.1 方式一

index.js

// index.js
Page({
data: {
page: 1,
goods: []
},
refresh(page) {
wx.showLoading({
title: '加载中',
mask: true
})
wx.request({
url: 'http://127.0.0.1:8000/api/v1/course/actual/?page=' + page,
method: 'GET',
success: (response) => {
if (page == 1) {
this.setData({
goods: response.data.results
})
} else {
const resData = this.data.goods.concat(response.data.results)
this.setData({
goods: resData
})
}
},
complete: () => {
wx.hideLoading()
}
})
},
onLoad(options) {
this.refresh(this.data.page)
},
onReachBottom() {
this.data.page++
console.log('上拉了')
// 发送请求,加载数据
this.refresh(this.data.page)
},
onPullDownRefresh() {
this.data.page = 1
this.refresh(this.data.page)
if(this.data.goods.length==3){
wx.stopPullDownRefresh()
}
},
})

index.wxml

<view wx:for="{{goods}}" wx:key="index">{{item.name}}</view>

index.wxss

view{
height: 400rpx;
display: flex;
justify-content: center;
align-items: center;
}
/* 奇数 */
view:nth-child(odd){
background-color: pink;
}
/* 偶数 */
view:nth-child(even){
background-color: green;
}

index.json

{
"usingComponents": {},
"navigationBarTitleText": "首页", // 标题
"onReachBottomDistance": 50, // 距离多少位置
"enablePullDownRefresh": true, // 开启下拉刷新
"backgroundColor": "#efefef", // 下拉刷新背景色
"backgroundTextStyle":"dark" // 下拉刷新点颜色
}

12.2 方式二

scroll-view

wxml

<scroll-view
class="scroll"
scroll-y # 运行y轴滑动
lower-threshold="100" # 距离底部还有100px时,触发事件
bindscrolltolower="handleGetData" # 事件处理函数
refresher-enabled="true" # 开启 下拉刷新
refresher-default-style="black" # 下拉默认样式
refresher-background="#f0f0f0" # 下拉背景色
bindrefresherrefresh="handleReload" # 下拉触发事件
refresher-triggered="{{isRefresh}}" # 设置下拉回弹,false允许回弹
enable-back-to-top="true" # 快速回到顶部,ios点顶部,安卓点tabbar
>
<view wx:for="{{goods}}" wx:key="index">{{item.name}}</view>
</scroll-view>

wxss

.scroll{
/* 100vh就是指元素的高度等于当前浏览器的视窗高度,即浏览器内部的可视区域的高度大小 */
height: 100vh;
background-color: grey;
}
view{
height: 400rpx;
display: flex;
justify-content: center;
align-items: center;
}
/* 奇数 */
view:nth-child(odd){
background-color: pink;
}
/* 偶数 */
view:nth-child(even){
background-color: green;
}

js

// pages/my/my.js
Page({
data: {
page: 0,
goods: [],
isRefresh: false
},
handleGetData() {
this.data.page++
console.log('上拉了')
// 发送请求,加载数据
wx.showLoading({
title: '加载中',
mask: true
})
wx.request({
url: 'http://127.0.0.1:8000/api/v1/course/actual/?page=' + this.data.page,
method: 'GET',
success: (response) => {
const resData = this.data.goods.concat(response.data.results)
this.setData({
goods: resData
})
},
complete: () => {
wx.hideLoading()
}
})
},
handleReload() {
console.log('下拉刷新了')
wx.showToast({
title: '下拉刷新',
})
wx.request({
url: 'http://127.0.0.1:8000/api/v1/course/actual/?page=' + 1,
method: 'GET',
success: (response) => {
this.setData({
goods: response.data.results
})
},
complete: () => {
wx.hideLoading()
}
})
this.setData({
isRefresh: false
})
}
})

13 更新

# 1 访问小程序,微信会将小程序代码包,下载到微信本地,打开使用
# 2 当小程序更新版本后,微信会检查小程序版本有没有更新,并下载最新小程序
# 3 更新方式:启动时同步更新,启动时异步更新
### 同步更新:
-启动时同步更新:微信运行时,会定期检查最近使用的小程序是否有更新。如果有更新,下次小程序启动时会同步进行更新,更新到最新版本后再打开小程序。如果 用户长时间未使用小程序时,会强制同步检查版本更新
-如果更新失败,还是会使用本地版本
-新版本发布24小时后,基本会覆盖全部用户
### 异步更新####
启动时异步更新:在启动前没有发现更新,小程序每次 冷启动 时,都会异步检查是否有更新版本。如果发现有新版本,将会异步下载新版本的代码包,将新版本的小程序在下一次冷启动进行使用,当前访问使用的依然是本地的旧版本代码
## 强制更新###
在启动时异步更新的情况下,如果开发者希望立刻进行版本更新,可以使用 wx.getUpdateManager API 进行处理。在有新版本时提示用户重启小程序更新新版本
# 4 在app.js中加入
App({
// 生命周期函数,启动小程序就会执行
onLaunch(){
const update=wx.getUpdateManager()
update.onUpdateReady(function(){
wx.showModal({
title: '发现新版本',
content: '重启应用,更新版本新版本?',
success:(res)=>{
if(res.confirm){
update.applyUpdate()
}
}
})
})
}
})

image-20240527170352023

image-20240527170854787

14 生命周期

14.1 应用生命周期

onLaunch : 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)

onShow : 当小程序启动,或从后台进入前台显示,会触发 onShow

onHide : 当小程序从前台进入后台,会触发 onHide

// app.js
App({
/**
* 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
*/
onLaunch: function () {
console.log('小程序启动了')
},
/**
* 当小程序启动,或从后台进入前台显示,会触发 onShow
*/
onShow: function (options) {
console.log('后台切前台了')
},
/**
* 当小程序从前台进入后台,会触发 onHide
*/
onHide: function () {
console.log('进后台了')
},
})

14.2 页面生命周期

onLoad : 监听页面加载

onReady : 监听页面初次渲染完成

onShow : 监听页面显示

onHide : 监听页面隐藏

onUnload : 监听页面卸载

Page({
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
console.log('1 页面加载了')
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
console.log('3 初次渲染完成')
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
console.log('2 页面显示')
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
console.log('4 页面隐藏')
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
console.log('5 页面卸载')
},
})

15 分享及获取头像昵称手机号

具体参考官方文档

https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/share-timeline.html

15.1 分享到朋友圈

onShareTimeline(){
return {
title:"这是一个神奇的页面",
query:'name=justin&age=19',
imageUrl:'/images/b.jpg'
}
},

15.2 转发

# 1 方式一:通过右上方 ...
# 2 方式二:通过按钮, 需要给button设置 open-type="share"
<button open-type="share">转发</button>
# 3 js中编写
onShareAppMessage() {
return {
title:"是朋友就点一下",
path:"/pages/my/my", //当前转发的页面
imageUrl:'/images/b.jpg'
}
},

15.3 获取头像

js

Page({
data:{
phono:'/images/b.jpg'
},
choosePhoto(event){
console.log(event.detail.avatarUrl)
this.setData({
phono:event.detail.avatarUrl
})
}
})

wxml

<button class="btn" open-type="chooseAvatar" bindchooseavatar="choosePhoto">
<image src="{{phono}}" class="photo"/>
</button>

wxss

.btn{
/* 透明的 */
background-color: transparent;
}
/* 去掉边框 */
.btn::after{
border: none;
}
.photo{
height: 250rpx;
width: 250rpx;
border-radius: 50%;
}

15.4 获取昵称

wxml

<input  type="nickname" placeholder="输入或获取昵称" model:value="{{username}}"/><button type="primary" plain bind:tap="showName">提交</button>

js

Page({
data:{
username:"",
},
showName(){
console.log(this.data.username)
}
})

wxss

input {
border: 1rpx solid pink;
border-radius: 10rpx;
padding: 10rpx;
margin: 10rpx;
}

15.5 获取手机号

# 1 手机号接口,必须是非个人开发者,并且完成了认证的小程序
# 2 两种验证方式需要付费使用,每个小程序账号有1000次体验额度
# 3 小程序端
# https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
# 用在快速注册、登陆

15.5.1 手机号快速验证

# 步骤1:需要将 button 组件 open-type 的值设置为 getPhoneNumber,当用户点击并同意之后,通过 bindgetphonenumber 事件获取回调信息;
# 步骤2:将 bindgetphonenumber 事件回调中的动态令牌code传到开发者后台,并在开发者后台调用微信后台提供的 phonenumber.getPhoneNumber 接口,消费code来换取用户手机号。每个code有效期为5分钟,且只能消费一次。
# 步骤3:后端拿到code --》调用getuserphonenumber 换取手机号
https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
# 步骤4:去咱们自己用户表中查
-能查到---之前用过,注册了--》签发token
-查不到--》第一次用--执行注册--》签发token

15.5.2 手机号实时验证

# 步骤1:需要将 button 组件 open-type 的值设置为 getRealtimePhoneNumber,当用户点击并同意之后,通过 bindgetrealtimephonenumber 事件获取回调信息;
# 步骤2:将 bindgetrealtimephonenumber 事件回调中的动态令牌code传到开发者后台,并在开发者后台调用微信后台提供的 phonenumber.getPhoneNumber 接口,消费code来换取用户手机号。每个code有效期为5分钟,且只能消费一次

wxml

<button type="warn" open-type="getPhoneNumber"
bindgetphonenumber="getPhoneNumber">快速手机号</button>
<button type="default" plain open-type="getRealtimePhoneNumber"
bindgetrealtimephonenumber="getRealPhoneNumber"
>快速手机号</button>

js

getPhoneNumber(event) {
console.log(event)
// 通过获取手机号返回的code--传递给后端--后端调用:POST https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=ACCESS_TOKEN -->获取手机号--》后端签发token给前端
云调用
wx.request({
url: '我们后端地址',
method:'POST',
data:{
code:event.detail.code
},
success:(res)=>{
//在此返回登录信息,用户登录
}
})
},
getRealPhoneNumber(event) {
console.log(event)
}

15.6 客服功能

# 微信为小程序提供客服消息能力,以便小程序用户可以方便快捷地与小程序服务提供方进行沟通
https://developers.weixin.qq.com/miniprogram/introduction/custom.html

wxml

## wxml##
<button type="default" plain open-type="contact">联系客服</button>

16 vant-app

https://vant-ui.github.io/vant-weapp/#/home

16.1 使用npm包

# 1 生成package.json文件
npm init -y
# 2 package.json 能看到下载完成,项目目录下有node_modules
npm i @vant/weapp -S
# 3 将 app.json 中的 "style": "v2" 去除
# 4 project.config.json 的settings中加入
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./"
}
]
# 5 构建npm
# 6 在app.json中加入需要的
"usingComponents": {
"van-button": "@vant/weapp/button/index"
}
#7 复制代码放入wxml中即可
<van-button type="default">默认按钮</van-button>
<van-button type="primary">主要按钮</van-button>
<van-button type="info">信息按钮</van-button>
<van-button type="warning">警告按钮</van-button>
<van-button type="danger">危险按钮</van-button>

16.2 引入报错解决

https://blog.csdn.net/cwb_2120/article/details/131561833

"packNpmRelationList": [
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram_npm/"
],
posted @   ssrheart  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示