微信小程序
微信小程序
小程序官网
开发工具
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软件即服务(去网吧):电脑,场地,环境(电源,网线,饮料)都是网吧提供的服务
本地开发支持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",
纯净项目
新建页面
# 1 在pages上,新建文件夹,logs # 2 在文件夹上,右键--》新建页面,写上名字logs -创建出四个文件 # 3 新建页面可以直接在app.json中增加一行,pages下会自动创建出一个页面 "pages": [ "pages/index/index", "pages/logs/logs", "pages/login/login" ],
调整页面显示顺序
# 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; }
引入矢量图标库
# 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) }, })
<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: ['刘亦菲', '迪丽热巴', '古力娜扎', '马尔扎哈'] }, })
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>
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
上线项目发送网络请求的域名,必须在微信公众平台配置->开发管理->服务器域名
本地开发只需要勾上不校验合法域名即可
<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('用户确认了') } } }) } })
10.2 消息框
<button type="default" bind:tap="showToast">弹出消息框</button>
// index.js Page({ showToast(){ wx.showToast({ title: '你好heart!', icon:"success", duration:2000 }) } })
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() } })
异步
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() } } }) }) } })
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/" ],
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通