小程序学习笔记
- 1.与网页的不同
- 2.项目基本结构
- 3.宿主环境
- 4.通信模型,渲染层和逻辑层
- 6.数据绑定(文本,属性)
- 7.修改数据
- 7.wx:if=" " 判断是否渲染
- 8.hidden 控制元素显示隐藏
- 9.wx:for =" "列表渲染
- 10 . < block> 包装元素
- 11.template模板引用
- 12. import和include引用方式
- 13.生命周期
- 14.事件
- 15.组件
- 16.WXS
- 17. 路由组件navigator
- 18. API
- wx.request(Object object)网络请求
- page页面事件处理函数
- 获取dom
- 下拉刷新和上拉加载
- 上传照片
- 上传文件wx.chooseMessageFile()、
- 下载图片
- 下载文档
- 自定义组件components
- 地图
- 地图组件map
- 使用腾讯地图
- 1.登录/注册腾讯地图api
- 2.申请开发者密钥(key):申请密钥
- 3.开通webserviceAPI服务:控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI -> 保存
- 4.下载微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2
- 5.安全域名设置,在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加https://apis.map.qq.com
- 6.页面使用(腾讯地图文档微信小程序JavaScript SDK)
- 坐标转地址(使用腾讯地图)
- 地址转坐标(使用腾讯地图)
- 搜索周边地点
- 获得城市列表(使用腾讯地图)
- 登录
- 获取手机号
- 云服务
- 云函数
- 云存储
- Mobx
- wx.getAccountInfoSync() 获取当前帐号信息。
- 微信支付
- 分享
- 自定义导航栏navigation
- 客服
- 自定义tabBar
- 分包
- 小技巧
- 上线流程
- 分享页面全局设置
- map ios不显示
- A—>B修改A的值
- setDate修改指定值
- 1px线
- 小程序下载文件,删除下载的临时文件downloadFile()
- 微信下载文件
- 左右列表联动
- 小程序骨架屏
- 消息订阅
- 网站扫描二维码,跳转小程序指定页面
- ios端省略号效果不对,超出部分隐藏收起
- 网站上此图片来自微信公众平台未经允许不可引用
- uv-waterfall 瀑布流 切换速度较快,数据混乱
1.与网页的不同
1.运行环境不同,网页运行在浏览器的环境,小程序在微信环境中
2.API不同,小程序没有DOM,BOM,但是可以提供各种API进行定位,扫码,支付
3.开发模式不同,小程序开发账号,开发工具
4.不需要下载就可以使用,(实际是包很小 下载很快看不出来下载)
2.项目基本结构
project.config.json 是项目配置文件,用来记录我们对小程序开发工具所做的个性化配置
setting 中保存了编译相关的配置
projectname 中保存的是项目名称
appid 中保存的是小程序的账号 ID
sitemap.json
微信现已开放小程序内搜索,效果类似于 PC 网页的 SEO。sitemap.json 文件用来配置小程序页面是否允许微信索引。
当开发者允许微信索引时,微信会通过爬虫的形式,为小程序的页面内容建立索引。当用户的搜索关键字和页面的索引匹配成功的时候,小程序的页面将可能展示在搜索结果中。
(注意: 默认开启的,如需要关闭 sitemap 的索引提示,可在小程序项目配置文件 project.config.json 的 setting 中配置字段 checkSiteMap 为 false
)
app.json
window 设置
用于设置小程序的状态栏、导航条、标题、窗口背景色。
navigationBar系列 | Value |
---|---|
navigationBarBackgroundColor | 导航栏背景颜色,如 #000000 |
navigationBarTextStyle | 导航栏标题颜色,仅支持 black / white |
navigationBarTitleText | 导航栏标题文字内容 |
navigationStyle | 导航栏样式(仅支持以下值:default 默认,custom 自定义,只保留右上角胶囊按钮) |
background系列 | Value (开启下拉刷新显示) |
---|---|
backgroundColor | 窗口的背景色 |
backgroundTextStyle | 下拉 loading 的样式,(仅支持 dark / light) |
其他 | Value |
---|---|
enablePullDownRefresh | 是否开启全局的下拉刷新(true/false)。(数据更新后关闭下拉刷新:wx.stopPullDownRefresh()) |
onReachBottomDistance | 页面上拉触底事件触发时距页面底部距离,50px。 |
tabBar 设置
如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
项目 | Value |
---|---|
color | 文字默认颜色,仅支持十六进制颜色 |
selectedColor | 文字选中时的颜色,仅支持十六进制颜色 |
backgroundColor | 背景色,仅支持十六进制颜色 |
borderStyle | tabbar 上边框的颜色, 仅支持 black / white |
list | tab 的列表,详见 list 属性说明,最少 2 个、最多 5 个 tab |
position | tabBar 的位置,仅支持 bottom / top |
custom | 自定义 tabBar,见详情 |
其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。tab 按数组的顺序排序,每个项都是一个对象,其属性值如下:
项目 | Value |
---|---|
pagePath | 页面路径,必须在 pages 中先定义 |
text | tab 上按钮文字 |
iconPath | 图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon。 |
selectedIconPath | 选中时的图片路径,icon 大小限制为 40kb,建议尺寸为 81px * 81px,不支持网络图片。当 position 为 top 时,不显示 icon。 |
WXML
WXML是小程序框架设计的一套标签语言,用来构建小程序页面结构,相当于HTML
WXSS
一套样式语言
rpx尺寸单位,只支持部分css选择器
小程序的屏幕固定为750rpx(即750个物理像素)。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
uniapp的rpx计算:750*元素的设计稿大小/设计稿总宽(750/640)
750/750*100=100rpx
750/640*100=117rpx
750/375*100=400rpx
3.宿主环境
网页运行在浏览器中,小程序运行在微信中
4.通信模型,渲染层和逻辑层
小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。其中,渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。
6.数据绑定(文本,属性)
// page.js
Page({
data: {
message: 'Hello MINA!',
classname:'active'
}
})
<view> {{message}} </view>
<view class="{{classname}}"> 123</view>//属性绑定
7.修改数据
普通数据
data: {
name:'张三'
},
this.setData({
name:'李四'
})
对象数据
data: {
user_info:{
name: 'li',
age: 10
},
cars:['nio', 'bmw', 'wolks']
},
this.setData({
['user_info.age']: 20,
['cars[0]']: 'tesla'
})
7.wx:if=" " 判断是否渲染
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
8.hidden 控制元素显示隐藏
<view hidden="{{true}}">123</view>
hidden | wx:if |
---|---|
hidden控制display属性,如选项卡 | 控制渲不渲染, 如以上来决定显不显示 |
有更高的初始渲染消耗 | if有更高的切换消耗 |
9.wx:for =" "列表渲染
data:[
{id:'001',message:'a'},
{id:'002',message:'b'}
]
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName" wx:key="id">
{{idx}}: {{itemName.message}}
</view>
wx:key=" index"和wx:key="*this"的区别
(*this 选中选项可以跟随变化)
*this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字
(index 选中选项不跟随变化)
10 . < block> 包装元素
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
wx:if vs hidden
11.template模板引用
用于重复的静态资源,不像component
1.创建tmp组件存放目录,内部包含wxml和wxss文件
2.用template标签定义一个代码片段,使用name属性指定模板的名称
//tmp1.wxml
<template name="a">
<view>
<image src="{{item.img}}"></image>
<text>{{item.name}}</text>
</view>
</template>
<view>111</view>
2.引入模板的样式,使用@import
//page1.wxss
@import '/tmp/tmp1/tmp1.wxss';
3.引入模板结构并且使用
//page1.wxml
<import src="/tmp/tmp1/tmp1"></import>//import:用来引用模板文件里面定义的模板内容块
<include src="/tmp/tmp1/tmp1">//include:用来引用目标文件内除了模板代码块的其他内容,显示<view>111</view> 的内容
<block wx:for="{{list}}" wx:key="id">
<template is="a" data="{{item}}"></template>
</block>
使用 is 属性声明需要的使用的模板利用data属性向模板传入需要的数据信息
12. import和include引用方式
WXML 提供两种文件引用方式 import和include
import可以在该文件中使用目标文件定义的template
<import src="item.wxml"/>
<template is="item" data="{{text: 'forbar'}}"/>
include 可以将目标文件除了 template , wxs外的整个代码引入,相当于是拷贝到 include 位置
<include src="header.wxml"/>//111
<template name="lis">
<view class="lis">
<image src="{{item.img}}"></image>
<text>{{item.name}}</text>
</view>
</template>
<view>111</view>
13.生命周期
小程序生命周期 | Value |
---|---|
onLaunch | 小程序初始化。 |
onShow | 小程序启动或切前台。 |
onHide | 小程序切后台。 |
onUnlaunch | 小程序卸载(在getApp()中可以找到) |
页面生命周期函数 | Value |
-------- | ----- |
onLoad | 页面加载(只调用一次) |
onShow | 页面显示 |
onReady | 页面初次渲染完成(只调用一次) |
onHide | 页面隐藏 |
onUnload | 页面卸载(只调用一次) |
14.事件
事件 | Value |
---|---|
tap | 类似click |
input | 文本框输入(获取值:e.detail.value) |
change | checkbox-group中选中项发生改变时,detail = {value:[选中的 checkbox 的value的数组]} |
touchstart | 手指触摸动作开始 |
touchmove | 手指触摸后移动 |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 |
touchend | 手指触摸动作结束 |
阻止事件冒泡catch
除 bind 外,也可以用 catch 来绑定事件。与 bind 不同, catch 会阻止事件向上冒泡。
<view catchtap="tapName"> Click me! </view>
事件对象event
event | Value |
---|---|
type | 事件类型 |
target | 触发事件组价的属性值集合 |
currenttarget | 事件绑定的当前组件 |
detail | 额外信息 |
touches | 触摸点信息 |
targetTouches | 当前元素目标上的触摸点 |
changedTouches | 发生改变的触摸点,几个手指发送了变化 |
<view id="tapTest" data-hi="Weixin" bindtap="tapName" mark:id="1001"> Click me! </view>
tapName(e){
e.currentTarget.dataset.hi //Weixin
e.mark.id //1001
}
绑定数据
方法一:data - 名字=“数据”
(为什么不用target是因为嵌套多了不一定点到元素),注意驼峰命名和-命名会转变
target是触发事件的元素,事件会冒泡到父级元素去,
currentTarget是绑定事件的元素
e.currentTarget.dataset.名字
方法二:mark:名字=“数据”
e.mark.名字
命名不会大小写转换
mark | dataset |
---|---|
mark 会包含从触发事件的节点到根节点上所有的 mark: 属性值 | dataset 仅包含一个节点的 data- 属性值。 |
如果存在同名的 mark ,父节点的 mark 会被子节点覆盖。 | |
在自定义组件中接收事件时, mark 不包含自定义组件外的节点的 mark 。 | |
不会字符和大小写转换 | 会大小写转换 |
15.组件
项目 | Value |
---|---|
view | 相当于div |
swiper | 滑块视图容器,只可放置swiper-item组件(轮播图) |
swiper-item | 仅可放置在swiper组件中,宽高自动设置为100%(滚动列表),scroll-x,scroll-y |
scroll-view | 可滚动视图区域 |
movable-area | 可移动区域 |
movable-view | 可移动容器,direction=‘all、vertical、horizontal、none’,bindchange拖动过程中触发的事件 |
text | 文本(长按选中文本,selectable) |
rich-text | 通过nodes属性把字符串渲染成对应ui结构 |
button | 按钮 open-type属性可以调用微信提供的功能 |
navigator | 导航相当于a |
image | 图片默认300*240 (mode属性指定模式,scaleToFill宽高拉伸填满,aspectFit图片长边显示,aspectFill图片短边,widthFix宽不变高自适应,heightFix高不变宽自适应) |
input | 输入框 |
picker | 从底部弹起的滚动选择器。 |
picker-view | 嵌入页面的滚动选择器。其中只可放置 picker-view-column组件,其它节点不会显示。 |
progress | 进度条percent(百分比0~100),stroke-width="4"宽度, activeColor="red"已走颜色 |
swiper
indicator-dots 指示点
indicator-color 指示点颜色
indicator-active-color 当前选中的指示点颜色
autoplay 是否自动切换
interval 自动切换时间间隔
duration 滑动动画时长
circular 是否采用衔接滑动
input
value 输入框的初始内容
type input 的类型
password 是否是密码类型
placeholder输入框为空时占位符
disabled是否禁用
maxlength 最大输入长度,设置为 -1 的时候不限制最大长度
confirm-type设置键盘右下角按钮的文字,仅在type='text’时生效(send 右下角按钮为“发送”,search 右下角按钮为“搜索”,next 右下角按钮为“下一个”,go 右下角按钮为“前往”,done 右下角按钮为“完成”)
bindinput eventhandle键盘输入时触发,
bindconfirm 点击完成按钮时触
movable-view 可移动的视图容器
可移动的视图容器,在页面中可以拖拽滑动。movable-view必须在 movable-area 组件中,并且必须是直接子节点,
项目 | Value |
---|---|
direction | movable-view的移动方向,属性值有all、vertical(垂直)、horizontal(水平) |
x | x偏移 |
y | y偏移 |
bindchange | 拖动过程中触发的事件,event.detail = {x, y, source} |
通过e.detail.source==‘touch’判断是否是拖拽过去的
scroll-view 可滚动视图区域
项目 | Value |
---|---|
scroll-x | 允许横向滚动 |
scroll-y | 允许纵向滚动 |
scroll-top | 设置竖向滚动条位置 |
scroll-left | 设置横向滚动条位置 |
scroll-with-animation | 在设置滚动条位置时使用动画过渡 1.0.0 |
refresher-enabled | 开启自定义下拉刷新 |
bindrefresherrefresh | 自定义下拉刷新被触发 |
refresher-triggered | 设置当前下拉刷新状态,true 表示下拉刷新已经被触发,false 表示下拉刷新未被触发 |
bindscroll | 滚动时触发,event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} |
bindscrolltolower | 滚动到底部/右边时触发 |
横向滚动
scroll-view要设置 scroll-x=“true” style=" white-space: nowrap;"
子组件设置style=“display: inline-block”
<scroll-view class="t2" scroll-x="true"
style=" white-space: nowrap; display: flex" >
<view class="t2" style="display: inline-block"></view>
<view class="t2" style="display: inline-block"></view>
<view class="t2" style="display: inline-block"></view>
</scroll-view>
纵向滚动
必须设置高度
<scroll-view scroll-y >
<view>1</view>
<view>2</view>
<view>3</view>
</scroll-view>
16.WXS
WXS(WeiXin Script)是小程序的一套脚本语言
创建wxs
//注意:函数内判断是否有值,没有就return要不会报错
function fnA(str){
if(!str){return}//注意:判断时候有值,没有就return要不会报错
return str+'A'
}
module.exports = {//导出
//必须用key:value的写法
fnA:fnA
};
使用
1.引用方式
{{m1.fnA(123)}}
<wxs module="m1" src="/util/1.wxs"></wxs>
页面.wxml中创建+使用
<view>{{wxs1.reverse(123)}}</view>
<wxs module="wxs1">
function reverse(str){
if(!str){
return
}
return str+'1111111'
}
module.exports={reverse:reverse}
</wxs>
wxs中引入wxs
创建第二个wxs
//2.wxs
function fnB(str){
return str+'B'
}
module.exports = {
fnB:fnB
};
//1.wxs 1里面引入2
var fnA=require('./2.wxs')
function fnB(str){
return str+'B'
}
module.exports = {
fnB:fnB
fnA:fnA.fnA
};
//page.wxml
<wxs></wxs>
17. 路由组件navigator
<navigator open-type="" url="/pages/home/home"></navigator>
传参:url=“/pages/home/home?id=10”
open-type | Value |
---|---|
navigate | 对应 wx.navigateTo 或 wx.navigateToMiniProgram (跳转普通页面) |
redirect | 对应 wx.redirectTo |
switchTab | 对应 wx.switchTab (跳转tabBar页面) |
reLaunch | 对应 wx.reLaunch |
navigateBack | 对应 wx.navigateBack 或 wx.navigateBackMiniProgram |
18. API
项目 | Value |
---|---|
事件监听 | 以on开头监听事件触发 (wx.onWIndowResize())窗口大小 |
同步 | 以sync结尾 (wx.setStorageSync(‘key’,‘value’))本地存储输入内容 |
异步 | 类似于jq中的$.ajax,需要success来接收结果(wx.request())网络请求 |
第一种:路由相关API(跳转页面)
1.wx.navigateTo() 保留当前页面跳转
保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层
// 隐藏当前页面,跳转非tabBar页面
// 传值:?后面传入数据多个数据用&链接
// 取值,在另一个页面onLoad函数参数中取值
wx.navigateTo({
url: '/pages/page6/page6?id=1001',
})
2. wx.redirectTo()卸载当前页面跳转
卸载当前页面跳转,不允许跳转到 tabbar 页面。
// 卸载当前页面跳转,不允许跳转到 tabbar 页面。
wx.redirectTo({
url: '/pages/page6/page6?id=1002',
})
3.wx.switchTab() 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面
// 卸载当前页面,跳tabbar页面,不能传参
wx.switchTab({
url: '/pages/page1/page1',
})
4. wx.reLaunch()关闭所有页面,打开到应用内的某个页面,可以打开tabBar页面
关闭所有页面,打开到应用内的某个页面,可以打开tabBar页面
//卸载当前页面,跳转应用中任意页面,可穿值
wx.reLaunch({
url: '/pages/page4/page4?id=1',
})
5.wx.navigateBack() 返回页面
关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages 获取当前的页面栈,决定需要返回几层。如果 delta 大于现有页面数,则返回到首页。
取值
onLoad: function(options) {
var objectId = options.objectId
}
区别
项目 | Value |
---|---|
navigateTo | 页面不是很多,推荐wx.navigateTo,后退不需要重新渲染 |
redirectTo | 相当于重定向跳转,销毁当前的页面 |
reLaunch | 销毁内存中所有保留的页面 |
官方规定小程序最多只能有五个页面同时存在,意思是在不关闭页面的情况下,最多新开五个页面,页面深度为5。
wx.navigateTo会增加页面栈大小,直到页面栈大小为5,wx.redirectTo不会增加页面栈大小;wx.navigateBack会减少页面栈大小,直到页面栈大小为1
第二种:界面相关API(弹窗) 4+2(关闭)
1.wx.showLoading()+ wx.hideLoading()
wx.showLoading({
title: '加载中...',
mask:true, // 设置蒙层,下面的东西不能点
})
setTimeout(()=>{
wx.hideLoading()
},3000)
2.wx.showToast()+wx.hideToast()消息提示框
wx.showToast({
title: '警告',
icon:'error',
duration:3000,
mask:true,
image:'/images/jd1.png'
})
setTimeout(()=>{
wx.hideToast()
},1000)
3. wx.showModal()模态框
//方式一:利用回调函数拿到模态框执行结果
wx.showModal({
title:'删除',
content:'您确认删除吗',
success:(res)=>{
if(res.confirm){
console.log('点击了确认按钮')
}
}
})
// 方式二:利用promise.then拿到模态框结果
wx.showModal({
title:'删除',
content:"您确定删除吗"
}).then((res)=>{
if(res.confirm){
console.log('点击了确认按钮')
}})
// 方式三:利用async和await (onModal加async),因为showModal支持promise,大部分api都支持promise
async onModal(){
const res= await wx.showModal({
title:'删除',
content:"您确定删除吗",
})
if(res.confirm){
console.log('点击了确认按钮')
}
},
4.wx.showActionSheet()操作菜单
不要在按完取消逻辑下写业务逻辑
async onSheet(){
const res=await wx.showActionSheet({
itemList:['1','2','3']
})
console.log(res.tapIndex)//用户点击的按钮序号,从上到下的顺序,从0开始
},
第三组 :界面导航栏相关API 4+1(隐藏)
1. wx.showNavigationBarLoading()+wx.hideNavigationBarLoading()
wx.showNavigationBarLoading()
setTimeout(()=>{
wx.hideNavigationBarLoading()
},3000)
2. wx.setNavigationBarTitle() 设置导航栏新标题
wx.setNavigationBarTitle({
title: '导航栏新标题',
})
3.setNavigationBarColor()设置页面导航条颜色
wx.setNavigationBarColor({
backgroundColor:'#000000',//仅支持 #ffffff 和 #000000
fontColor:'#ffffff',
animation: {//动画效果
duration: 400,
timingFunc: 'easeIn'
}
})
4. wx.hideHomeButton() 隐藏返回首页按钮
wx.hideHomeButton()
第四种: 缓存API (Sync同+异)
sync,当数据比较少,不会影响下面的程序的时候用同步
1.wx.setStorageSync() 和wx.setStorage() 存缓存
小程序的setStorageky 可以存任意格式,网页只能存字符串(JSON.stringify)
wx.setStorageSync('a', 123)
wx.setStorageSync('obj', {name:123})
wx.setStorage({
key:'car',
data:[{name:'张三',age:12}],
})
2.wx.getStorageSync() 和wx.getStorage() 取缓存
const a= wx.getStorageSync('a')
//方法一,利用回调函数取数据
wx.getStorage({
key:'b',
success:(res)=>{
console.log(res.data)
}
})
//方法二:利用promise
wx.getStorage({key:'b'}).then((res)=>{console.log(res.data)})
//方式三:async+await
async get(){
const res=await wx.getStorage({key:'car'})
console.log(res)
}
3.wx.removeStorageSync() 和wx.removeStorage() 移出缓存
wx.removeStorageSync('a')
wx.removeStorage({
key: 'b',
})
4.wx.clearStorageSync() 和wx.clearStorage() 清空缓存
wx.clearStorageSync()
wx.clearStorage()
背景音乐
1.页面.js中获取背景音乐管理对象
const bgm=wx.getBackgroundAudioManager()
Page({})
2.后台继续播放音频requiredBackgroundModes
//app.json
{
"requiredBackgroundModes": ["audio", "location"]
}
属性
项目 | Value |
---|---|
src | 音频的数据源。当设置了新的 src 时,会自动开始播放 |
startTime | 音频开始播放的位置(单位:s)。 |
title | 音频标题,(必填) |
epname | 专辑名 |
singer | 歌手名 |
coverImgUrl | 封面图 URL |
webUrl | 页面链接 |
protocol | 音频协议。 |
playbackRate | 播放速度。范围 0.5-2.0,默认为 1。 |
duration | 当前音频的长度(单位:s) |
currentTime | 当前音频的播放位置(单位:s) |
paused | 当前是否暂停或停止。(只读) |
buffered | 音频已缓冲的时间,仅保证当前播放时间点到此时间点内容已缓冲。(只读 |
onLoad(options) {
// 设置src和title
bgm.title="起风了"//名字
bgm.src="http://music.163.com/song/media/outer/url?id=167827.mp3"//音乐地址,用网络地址
bgm.singer="买辣椒也用卷"//歌手名字
bgm.coverImgUrl="https://scpic.chinaz.net/files/pic/pic9/202009/apic27858.jpg"//封面图
bgm.playbackRate=2.0//播放倍速
setTimeout(()=>{
console.log(bgm.duration)//总时长
console.log(bgm.currentTime)//当前播放时长
console.log(bgm.paused)//是否暂停
},5000)
// 监听背景音乐时间
// 监听背景音频是否可以播放
bgm.onCanplay(()=>{
console.log("音乐可以播放")
})
//2.监听有音乐播放
bgm.onPlay(()=>{
console.log("音乐在播放")
})
//3.监听音乐暂停
bgm.onPause(()=>{
console.log("音乐暂停")
})
//4.监听音乐播放过程
bgm.onTimeUpdate(()=>{
console.log( bgm.currentTime)
})
//5.监听音乐自然播放结束
bgm.onEnded(()=>{
console.log("音乐播完了")
})
//6.音频跳转中
bgm.onSeeking(()=>{
console.log('音频跳转中,请稍后')
})
//7.音乐跳转完成(真机测试)
bgm.onSeeked(()=>{
console.log('音频跳转完')
})
//8.监听下一首播放(真机测试)
bgm.onNext(()=>{
console.log('下一首')
})
},
play(){
bgm.play()//暂停
},
pause(){
bgm.pause()//播放
},
stop(){
bgm.stop()//停止关闭音乐,从头开始播放
},
seek(){
bgm.seek(200)//跳转播放位置
},
循环播放
方法
bgm | const bgm=wx.getBackgroundAudioManager() |
---|---|
bgm.play() | 播放音乐 |
bgm.pause() | 暂停音乐 |
bgm.seek(number currentTime) | 跳转到指定位置 |
bgm.stop() | 停止音乐 |
bgm.onCanplay(function callback) | 监听背景音频进入可播放状态事件。 但不保证后面可以流畅播放 |
bgm.onWaiting(function callback) | 监听音频加载中事件。当音频因为数据不足,需要停下来加载时会触发 |
bgm.onError(function callback) | 监听背景音频播放错误事件 |
bgm.onPlay(function callback) | 监听背景音频播放事件 |
bgm.onPause(function callback) | 监听背景音频暂停事件 |
bgm.onSeeking(function callback) | 监听背景音频开始跳转操作事件 |
bgm.onSeeked(function callback) | 监听背景音频完成跳转操作事件 |
bgm.onEnded(function callback) | 监听背景音频自然播放结束事件 |
bgm.onStop(function callback) | 监听背景音频停止事件 |
bgm.onTimeUpdate(function callback) | 监听背景音频播放进度更新事件,只有小程序在前台时会回调。 |
bgm.onNext(function callback) | 监听用户在系统音乐播放面板点击下一曲事件(仅iOS) |
bgm.onPrev(function callback) | 监听用户在系统音乐播放面板点击上一曲事件(仅iOS) |
wx.request(Object object)网络请求
小程序必须使用 HTTPS/WSS 发起网络请求
不支持Promise
开发阶段可以在详情——本地设置中——勾选不校验 就可以避开https
项目 | Value |
---|---|
url | 接口地址 |
data | 请求的参数 |
header | 设置请求的 header |
timeout | 超时时间,单位为毫秒。默认值为 60000 |
method | HTTP 请求方法(OPTIONS,GET ,POST,DELETE )… |
dataType | 返回的数据格式 (json)返回的数据为 JSON.parse后的 |
responseType | 响应的数据类型 (text 响应的数据为文本,arraybuffer 一段二进制数据,用来模拟内存里面的数据) |
success | 接口调用成功的回调函数 |
fail | 接口调用失败的回调函数 |
complete | 接口调用结束的回调函数(调用成功、失败都会执行) |
object.success | 成功的回调函数 |
---|---|
data | 返回的数据 |
statusCode | HTTP 状态码 |
header | HTTP Response Header |
cookies | 返回的 cookies,格式为字符串数组 |
object.fail | 失败的回调函数 |
---|---|
errMsg | 错误信息 |
errno | errno 错误码 |
1.发送网络请求
wx.request({
url: 'http://t.talelin.com/v2/movie/top250',
method:'GET',
data:{
start:0,count:2
},
success:(res)=>{
console.log('数据',res.data)
}
})
使用async发送请求
//request.js
class Base{
constructor(){
this.baseUrl='http://t.talelin.com/v2/movie/'//基础路径
}
request(url,data={},method="GET"){
return new Promise((resolve,reject)=>{
wx.request({
url: this.baseUrl+url,
data,
method,
success:(res)=>{
// 获取http状态码 只要以2开头就可以
const code=res.statusCode
if(code>=200&&code<300){
resolve(res.data)
}else{
reject(code)
}
},
fail:(err)=>[
//失败两种,服务器没找到,不允许
reject (err)
],
})
})
}
}
export default Base;
//page.js
import Base from '../../utils/request'
const base=new Base()
async getData2(){
const res=await base.request('top250')
console.log(res)
},
page页面事件处理函数
onPageScroll(Object object)监听用户滑动页面事件。
onPageScroll(e){
console.log(e)
},
wx.pageScrollTo(Object object)将页面滚动到目标位置
项目 | Value |
---|---|
scrollTop | 滚动到页面的目标位置,单位 px |
duration | 滚动动画的时长,单位 ms |
selector | 选择器(类似于 CSS 的选择器 id,class,子代,后代) |
offsetTop | 偏移距离,需要和 selector 参数搭配使用,可以滚动到 selector 加偏移距离的位置,单位 px |
success | 接口调用成功的回调函数 |
fail | 接口调用失败的回调函数 |
complete | 接口调用结束的回调函数(调用成功、失败都会执行) |
wx.pageScrollTo({
scrollTop: 0,
duration: 300
})
获取dom
1.创建查询器
在组件里面用this.createSelectorQuery()
在页面里面用wx.createSelectorQuery()
const query = wx.createSelectorQuery();
2.选择元素
集合:const el=query.selectAll(‘.traffic’)
单个:const el= query.select(‘.tripinfotitlelist’)
3.元素指定内容
//1.全部查询(跟上4.)
el.boundingClientRect(()=>{})
//2.自身查询(就不用写第四个)
el.fields({size:true},res=>{
console.log(res)//只查询size属性
}).exec()
size:宽高
daraset:自定义dataset
rect:布局 left,top...
//3.canvas节点查询
el.node((res)=>{}).exec()
4.执行查询
query.exec(function (res) {
//res就是 所有标签为mjltest的元素的信息 的数组
});
canvas
<canvas type="2d" class="myCanvas"></canvas>
<button bindtap="onDrawImg">绘制图形</button>
<button bindtap="onDrawImg1">绘制图形1画布变大</button>
onDrawImg(){
const query=wx.createSelectorQuery();
const el=query.select('.myCanvas');
el.node((res)=>{
// 获取canvas实例
const canvas=res.node;
// 获取画布绘制环境
const ctx=canvas.getContext("2d");
// 绘制图形
ctx.fillStyle="pink";
ctx.fillRect(50,50,100,100);
// 画圆
ctx.arc(100,100,50,0,2*Math.PI);
ctx.stroke(); // 描边
});
query.exec();
},
onDrawImg1(){
const query=wx.createSelectorQuery();
const el=query.select('.myCanvas');
el.fields({size:true,node:true},(res)=>{
// 获取canvas实例
const canvas=res.node;
// 将画布尺寸设置成跟画板尺寸一样大
canvas.width=res.width;
canvas.height=res.height;
// 获取画布绘制环境
const ctx=canvas.getContext("2d");
// 画扇形
ctx.beginPath();
ctx.moveTo(150,150);
ctx.arc(150,150,100,0,(45*Math.PI)/180,false);
ctx.closePath();
ctx.fill();
});
query.exec();
},
修改画板大小
当画板变大时候,画布会自动拉满,图形就会变形
因此要手动修改大小,h5中width和height写在标签内的原因
下拉刷新和上拉加载
页面的下拉刷新和上拉加载
enablePullDownRefresh:true 下拉刷新
enablePullDownRefresh:true 在页面.json 或app.json中设置
在页面Page()构造器中的全局事件onPullDownRefresh()处理逻辑
在json中设置背景的样式
API
(1)wx.startPullDownRefresh()触发下拉刷新,调用后触发下拉刷新动画,效果与用户手动下拉刷新一致
(2)wx.stopPullDownRefresh()可以停止当前页面的下拉刷新
需要手动设置wx.stopPullDownRefresh() 下拉窗口才会回去
onReachBottom() 监听用户上拉触底事件
onReachBottomDistance:300
局部的下拉刷新和上拉加载
<scroll-view
scroll-top='{{y}}' //滚动到某个位置
scroll-with-animation //缓冲滚动到某个位置
scroll-y //允许纵向滚动
bindscroll="onScroll" //滚动时候触发:ScrollLeft, scrollTop...
bindscrolltolower="onReachBottom" //触底事件处理函数
refresher-enabled //开启自定义下拉刷新
bindrefresherrefresh="onPullDownRefresh" //下拉刷新处理函数
refresher-triggered="{{flag}}" //下拉刷新的状态控制,用于关闭下拉框
>
<block wx:for="{{list}}" wx:key="*this">
<view class="item">{{item}}</view>
</block>
</scroll-view>
页面 | 局部(scroll-view) |
---|---|
上拉加载 : onReachBottom() | bindscrolltolower=“fn” |
下拉刷新(开启): json/“enablePullDownRefresh”: true, | refresher-enabled |
下拉刷新时间: onPullDownRefresh | bindrefresherrefresh=“fn” |
关闭下拉刷新: wx.stopPullDownRefresh() | refresher-triggered=“{{flag}}” |
上传照片
wx.chooseMedia()拍摄或从手机相册中选择图片或视频
项目 | Value |
---|---|
count | 最多可以选择的文件个数(默认9个) |
mediaType | [‘image’, ‘video’]文件类型 |
sourceType | [‘album’, ‘camera’]图片和视频选择的来源 |
camera | 仅在 sourceType 为 camera 时生效,使用前置或后置摄像头 |
object.success 回调函数
tempFiles// 本地临时文件列表
tempFilePath//本地临时文件路径 (本地路径)
size//本地临时文件大小,单位 B
success(res) {
console.log(res.tempFiles.tempFilePath)
console.log(res.tempFiles.size)
}
<button bind:tap="chooseImg">选择本地图片</button>
async chooseImg(){
const res=await wx.chooseMedia({//默认最多9个
count:3
})
const arr=res.tempFiles.map(item=>{//过滤出照片的地址
return item.tempFilePath
})
console.log(arr)
},
长按保存图片wx.saveImageToPhotosAlbum(Object object)
bindlongpress=“saveImg”
bindlongpress:手机触摸后超过350ms离开,如果指定回调就用回调,tap事件不会触发
保存图片到系统相册。
saveImg(e){//长按保存图片
const src=e.mark.src
wx.saveImageToPhotosAlbum({
filePath:src ,
})
},
点击预览照片wx.previewImage(Object object)
在新页面中全屏预览图片。预览的过程中用户可以进行保存图片、发送给朋友等操作。
wx.previewImage({
current: '', // 当前显示图片的 http 链接
urls: [] // 需要预览的图片 http 链接列表
})
上传文件wx.chooseMessageFile()、
下载图片
onSavePic() {
// #ifdef MP-WEIXIN
uni.getImageInfo({
src: _this.imageUrl, // 图片下载网络地址
success: function(e) {
// e.type=png/jpg 扩展名
// filePathNew: 指定文件下载后存储的路径 (本地路径)
var filePathNew = wx.env.USER_DATA_PATH + "/" + new Date().valueOf() +'.'+e.type;
uni.downloadFile({
url: _this.imageUrl,
filePath: filePathNew,
success: (res) => {
if (res.statusCode === 200) {
uni.saveImageToPhotosAlbum({
filePath: filePathNew,
success: function() {
uni.showToast({title: '保存到相册成功'});
},
fail: function(err){}
});
}
}
});
},
complete: function(e) {}
});
// #endif
},
下载文档
需要配置合法域名
1.wx.downloadFile()传入路径会返回一个临时文件路径
2.wx.saveFile()保存临时地址
3.wx.openDocument()打开文档
onOpenDocment() {
uni.downloadFile({
url: this.fileUrl,// 网络文档地址
success: (data) => {
if (data.statusCode === 200) {
uni.saveFile({
tempFilePath: data.tempFilePath, //临时路径
success: function(res) {
// 保存路径
uni.showToast({ title: "文件已保存:"+res.savedFilePath,duration:3000 })
setTimeout(()=>{
//打开文档查看
uni.openDocument({
filePath:res.savedFilePath,
success:function(res){
console.log('打开文档成功')
}
})
}, 3000);
}
});
}
},
fail: (err) => {
uni.showToast({
title: '失败请重新下载'
});
},
});
},
自定义组件components
和普通页面的区别
1.组件的json文件要声明component:true
2.组件的js文件调用component()函数,普通页面调用page()
3.组件的方法函数定义在methods中,普通页面和data平级
4.组件生命周期定义在lifetimes
组件样式不受外界影响
修改样式隔离
修改样式隔离app.wxss 或页面的 wxss 中使用了标签名选择器(或一些其他特殊选择器)来直接指定样式,这些选择器会影响到页面和全部组件。通常情况下这是不推荐的做法。指定特殊的样式隔离选项 styleIsolation 。
项目 | Value |
---|---|
isolated | 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(一般情况下的默认值); |
apply-shared | 表示页面影响自定义组件,但自定义组件不会影响页面; |
shared | 表示页面样式影响自定义组件,自定义组件的样式也会影响页面和其他设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用。) |
/写法一
Component({
options: {
styleIsolation: 'isolated'
}
})
//写法二在json中
{
"styleIsolation": "isolated"
}
1.创建组件文件夹
2.引入方式(全局+局部)
//全局 app.json中
{
"usingComponents":{
"c-text":"components/text/text"
}
}
//局部 页面.json中
{
"usingComponents":{
"c-text":"/components/text/text"
}
}
3.在页面中使用
<c-text></c-text>
组件间传值
1.父——>子 (自定义属性)
//父
<c-book1 book="{{bookData}}"></c-book1>
//子
properties: {
book:Object
},
properties: {//完整定义
book:{
type:Object,
value:{}//默认值
}
},
流程:父组件绑定自定义属性=要传递是数据,子组件在properties中定义该属性,接收传递下来的数据,讲数据绑定到子组件页面上
2.子——> 父(自定义事件)
//父
<c-book1 wx:if="{{flag}}" book="{{bookData}}" bind:getId="fn"></c-book1>
fn(e){
console.log(e.detail)//传来的值
}
//子
<view class="book" bindtap="onTap">
methods: {
onTap(){
//通知父组件事件被触发,携带数据
this.triggerEvent('getId',{id:id},{bubbles:true})
// 第一个参数:父组件的事件名字
//第二个参数:要携带的数据
//第三参数:是否冒泡
},
},
流程:给子组件绑定一个事件,在事件处理程序中利用this.triggerEvent(‘父组件的自定义事件名’,{要传递的数据})激活父组件的自定义事件,在父组件事件处理程序中e.detail拿到数据
组件的生命周期
lifetimes:{}中写
lifetimes:{} | Value |
---|---|
created(){} | 组件实例被创建 |
attached(){} | 组件进入页面 |
ready(){} | 组件在页面布局完成 |
moved(){} | 组件位置发生变化 |
detached(){} | 组件在页面销毁 |
lifetimes:{
created(){
console.log('组件实例被创建')
},
attached(){
console.log('组件进入页面')
},
ready(){
console.log('组件在页面布局完成')
},
moved(){
console.log('组件位置发生变化')
},
detached(){
//利用wx:if
console.log('组件在页面销毁')
}
}
组件所在页面的生命周期
pageLifetimes
项目 | Value |
---|---|
show | 组件所在页面被展示时执行 |
hide | 被隐藏时执行 |
resize | 尺寸发生变化时 |
Component({
pageLifetimes:{
hide(){},
show(){},
resize(size){}
}
})
插槽
单个插槽
单插槽:组件中利用slot标签占位,使用组件在组件内部写子元素。
//组件.wxml
<c-tag content="{{txt1}}">
<text>+1</text>
</c-tag>
//插槽.wxml
<view>
<!-- 插槽占位符slot -->
<slot></slot>
</view>
多个插槽
多插槽:组件利用slot标签的name属性指定插槽名字,使用时候在组件的js中开启多插槽支持 options:{ //开启多插槽 multipleSlots:true },
使用组件时在组件内部写元素用slot="footer"属性区分
//组件.wxml
<c-tag content="{{txt2}}">
<image src="/images/jd.png" slot="avatar" class="img"></image>
<text slot="add">+1</text>
</c-tag>
//插槽.wxml
<view>
<slot name="avatar"></slot>
<text>{{content}}</text>
<slot name="add"></slot>
</view>
Behavior({}) 抽离组件公共逻辑(作用于组件)
包含组件的属性和方法,声明周期
一个组价可以有多个behavior,behavior也可以引用behavior
1.创建文件夹
2.创建behavior文件+共享
export default Behavior({
//组件公共的属性
properties:{
content:String
},
//组件的公共的方法
methods:{
onTap(){
console.log(this.properties.content)
}
},
lifetimes:{}
})
组件中使用
import bh from '../behaviors/bh'
Component({
//整合公共逻辑
behaviors:[bh]
})
外部样式类
//1.wxml 页面
<c-tag1 content="tag1的标题" ex-green="green" img="/images/1.jpg"></c-tag1>
<c-tag1 content="tag1的标题" ex-pink="pink" img="/images/1.jpg"></c-tag1>
//1.wxss 页面
.green{
background-color: chartreuse !important;
}
.pink{
background-color: pink !important;
}
// 组件.wxml
<text class="title ex-green ex-pink" bindtap="onTap">{{content}}</text>
// 组件.js
import bh from '../behaviors/bh'
Component({
//整合公共逻辑
behaviors:[bh],
//接收外部传入的样式类
externalClasses:["ex-green","ex-pink"],
})
observer/observers 监听器(在组件中使用)
//监听单一值
properties: {
a:{
type:Number,
value:0,
observer(newVal,oldVal){
console.log('新值'+newVal+'旧值'+oldVal)
}
},
}
//多个属性用,号隔开
observers:{
'a,b,obj.c':function(newA,newB,newC){
console.log(newA,newB,newC)
},
}
//监听对象的多个属性
observers:{
'obj.**':function(newObj){
console.log(newObj.a)
},
}
地图
app.json设置
requiredPrivateInfos(有的时候不加也出来了)
//app.json
"requiredBackgroundModes": ["audio","location"],
"requiredPrivateInfos": [ "getLocation","choosePoi" ],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
wx.getLocation(Object object)获取当前的地理位置、速度
const res=await wx.getLocation();
console.log("地理位置",res);
// 获取当前位置的经纬度
const {latitude,longitude}=res;
// 以当前点为中心展开一片地图
wx.openLocation({
latitude,
longitude,
})
项目 | Value |
---|---|
type | wgs84 返回 gps 坐标,gcj02 返回可用于 wx.openLocation 的坐标 |
altitude | 传入 true 会返回高度信息,由于获取高度需要较高精确度,会减慢接口返回速度 |
isHighAccuracy | 开启高精度定位 (true/false) |
highAccuracyExpireTime | 高精度定位超时时间(ms),指定时间内返回最高精度,该值3000ms以上高精度定位才有效果 |
success | 接口调用成功的回调函数 |
success成功回调 | Value |
---|---|
latitude | 纬度,范围为 -90~90,负数表示南纬 |
longitude | 经度,范围为 -180~180,负数表示西经 |
speed | 速度,单位 m/s |
accuracy | 位置的精确度,反应与真实位置之间的接近程度,可以理解成10即与真实位置相差10m,越小越精确 |
altitude | 高度,单位 m |
wx.choosePoi()打开 POI 列表选择位置,支持模糊定位(精确到市)和精确定位混选。
success回调 | Value |
---|---|
type | 选择城市时,值为 1,选择精确位置时,值为 2 |
city | 城市名称 |
name | 位置名称 |
address | 详细地址 |
latitude | 纬度,浮点数 |
longitude | 经度,浮点数 |
async choosePoint(){
const res=await wx.choosePoi();
console.log("您的位置是",res);
},
wx.openLocation()使用微信内置地图查看位置
项目 | Value |
---|---|
latitude | 纬度 |
longitude | 经度 |
scale | 缩放比例,范围5~18 |
name | 位置名 |
address | 地址的详细说明 |
success | 接口调用成功的回调函数 |
wx.getLocation({
type: 'gcj02', //返回可以用于 wx.openLocation 的经纬度
success (res) {
const latitude = res.latitude
const longitude = res.longitude
wx.openLocation({
latitude,
longitude,
scale: 18
})
}
})
wx.chooseLocation()
wx.chooseAddress()获取用户收货地址。
wx.chooseAddress({
success (res) {
console.log(res.userName)//收件人姓名
console.log(res.postalCode)//邮编
console.log(res.provinceName)//一级地址
console.log(res.cityName)//二级地址
console.log(res.countyName)//三级地址
console.log(res.detailInfo)//详细地址
console.log(res.nationalCode)//新选择器详细收获地址
console.log(res.telNumber)//收获地址国家码
}
})
地图组件map
项目 | Value |
---|---|
longitude | 中心经度 1.0.0 |
latitude | 中心纬度 1.0.0 |
markers | 标记点 |
circles | 圆 |
polyline | 路线 |
<map name="myMap"
longitude="{{lng}}"
latitude="{{lat}}"
markers="{{markers}}"
circles="{{circles}}"></map>
showMarker(){//展示标记点
const marker={
id:1,
latitude:this.data.lat,
longitude:this.data.lng,
iconPath:'https:....',
width:30,
height:30,
}
this.setData({
markers:[marker],
})
},
showCircle(){//展示圆圈
const circle={
latitude:this.data.lat,
longitude:this.data.lng,
radius:200,
}
this.setData({
circles:[circle],
})
},
使用腾讯地图
1.登录/注册腾讯地图api
2.申请开发者密钥(key):申请密钥
3.开通webserviceAPI服务:控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI -> 保存
4.下载微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2
复制到小程序里( 这俩那个都行)
5.安全域名设置,在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加https://apis.map.qq.com
6.页面使用(腾讯地图文档微信小程序JavaScript SDK)
//第一步引入腾讯地图
const QQMap=require('../../utils/qqmap-wx-jssdk')
//实例化腾讯地图
const qqmap=new QQMap({key:'DGKBZ-VZ4CV-CETPR-UDGJ5-CO5V6-****'})
坐标转地址(使用腾讯地图)
async getAddress(){//坐标转地址
const res=await wx.getLocation();
const {latitude,longitude}=res;
//使用腾讯地图将坐标点转为具体地址
qqmap.reverseGeocoder({
location:{latitude,longitude},
success:res=>{
console.log('当前坐标点对应的地址是',res)
}
})
},
地址转坐标(使用腾讯地图)
qqmap.geocoder({
address:'北京市昌平区......',
success:res=>{
const {lat:latitude,lng:longitude}=res.result.location;
//以当前经纬度展开地图
wx.openLocation({
latitude,
longitude
})
//利用腾讯地图搜索周边
qqmap.search({
keyword:"餐饮",
location:{latitude, longitude},
success:res=>{
console.log('搜索结果',res)
}
})
}
})
搜索周边地点
//利用腾讯地图搜索周边
qqmap.search({
keyword:"餐饮",
location:{latitude, longitude},
success:res=>{
console.log('搜索结果',res)
}
})
获得城市列表(使用腾讯地图)
qqmap.getCityList({
success:res=>{
console.log("城市列表",res)
}
})
登录
wx.getSetting()获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限。
wx.getSetting({
withSubscriptions: true,
success (res) {
console.log(res.authSetting)
// res.authSetting = {
// "scope.userInfo": true,
// "scope.userLocation": true
// }
console.log(res.subscriptionsSetting)
// res.subscriptionsSetting = {
// mainSwitch: true, // 订阅消息总开关
// itemSettings: { // 每一项开关
// SYS_MSG_TYPE_INTERACTIVE: 'accept', // 小游戏系统订阅消息
// SYS_MSG_TYPE_RANK: 'accept'
// zun-LzcQyW-edafCVvzPkK4de2Rllr1fFpw2A_x0oXE: 'reject', // 普通一次性订阅消息
// ke_OZC_66gZxALLcsuI7ilCJSP2OJ2vWo2ooUPpkWrw: 'ban',
// }
// }
}
})
wx.login ()获取登录凭证code
- 使用 wx.checkSession 检查当前用户小程序登录态是否有效
- 使用 wx.getStorageSync(‘token’) 检查本地缓存中是否保存有后端返回的 token
- 如果小程序登录态已失效,或者 token 为空,须先执行登陆流程
- wx.login 获取code(code有时效) 并 wx.request 提交 code 给己方服务器
- 服务器 提交Appid (小程序编号)+ appSecret(小程序密钥) + code 到微信方服务器 获取 session_key (密匙)& openid(每个用户在每个小程序中的唯一固定编号)
- 服务器 根据 session_key & openid 返回 一段密文 到小程序端
- 小程序端 wx.setStorage 存储 密文 在后续用户操作需要凭证时 附带该参数
wx.login({
success (res) {
if (res.code) {
//发起网络请求
wx.request({
url: 'https://example.com/onLogin',
data: {
code: res.code
}
})
} else {
console.log('登录失败!' + res.errMsg)
}
}
})
用户第一次登录之后若再次登录,则进行自动登录或登录态过期需要手动授权登录,自动登录需要检查用户信息及登录态是否过期
wx.checkSession(Object object)检查登录态是否过期
//如果app.js中有wx.login就会一直显示success
wx.checkSession({
success () {
//session_key 未过期,并且在本生命周期一直有效
},
fail () {
// session_key 已经失效,需要重新执行登录流程
wx.login() //重新登录
}
})
获取个人信息wx.getUserProfile(),头像和名字
wx.getUserProfile({
desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
传统开发模式登录流程
1.获取身份信息
登录wx.login拿到code码
wx.login({
success:(res)=>{
const code=res.code
wx.request({
url:'登录接口',
data:{code},
success:(res)=>{
//获取身份令牌,保存到本地
const token=res.data.token
wx.setStorageSync('token',token)
}
})
}
})
//获取我的订单列表
wx.request({
url:'订单请求地址',
header:{//因为get在地址栏后面数据不安全,所以在请求头里面携带数据
token:wx.getStorageSync('token')
},
success:(res)=>{
if(验证通过){
//返回订单数据
}else{
//验证不通过(没有token,token过期,权限不够)
重新获取token(走上面12-19的步骤)或者换一个权限高的
}
}
})
获取手机号
getPhoneNumber 返回的 code 与 wx.login 返回的 code 作用是不一样的,不能混用
- 新版获取手机号不需要login。需要用户自己点击button,返回 加密的手机号,发送code和openid到己方服务器
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"></button>
Page({
getPhoneNumber (e) {
console.log(e.detail.code)//decf01b9011837d57a60a6cc9....
}
云函数获取身份标识
见下面
云服务
1.打开云服务
如果第一次用需要注册
2. 初始化云能力, wx.cloud.init()
//app.js
onLaunch(){
// 初始化云能力
wx.cloud.init({
env:'lianxi-6g94su9j2e6cd4d9'//id
})
}
3.获取数据库
//页面.js
//获取数据库
const db=wx.cloud.database();
//获取集合
const userList=db.collection("userList")
4.操作数据库
(1)增
userList.add({
data:{name:"张三",age:"20",sex:"男"}
})
(2)删 .remove()
userList.doc('6842667962df62750a10484a5676d23c').remove()
(3)改
(3.1)更新数据.update()
userList.doc("0a4ec1f962df6289124ce78e2f9a7038").update({
data:{age:23}
})
(3.2)重置数据.set()
userList.doc('6842667962df62750a10484a5676d23c').set({
data:{age:20}
})
没有_openid就只读不能改
(4)查.get()
(4.1)获取全部数据.get()
const res=await userList.get()
console.log(res.data)
(4.2)获取某个数据.doc(id)
const res1=await userList.doc('0a4ec1f962df6289124ce78e2f9a7038').get()
console.log(res1.data)
(4.3)有条件的查询(查询性别为男的).where()
const res2=await userList.where({
sex:'男'
}).get()
console.log(res2.data)
(4.4)查询限制个数查询limit(num)
const res3=await userList.limit(3).get()
console.log(res3.data)
(4.5)指定查询起点 .skip(num)
4.4+4.5可以做分页效果
const res4=await userList.skip(2).get()
console.log(res4.data)
(4.6)查询数据并排序 (取年级从小到大排列) (asc升序)(desc降序).orderBy()
const res5=await userList.orderBy('age','asc').get()
console.log(res5.data)
(4.7)筛选查询字段 (取只返回name).field()
const res6=await userList.field({name:true}).get()
console.log(res6.data)
//总结:这几个方法可以任意组合 const res7=await userList.where({ sex:'男'}) .orderBy('age','asc') .limit(2) .field({name:true,age:true}) .get() console.log(res7.data)
数据操作符
//先获取数据操作符
const _=db.command;
//条件可以是范围20岁以上的(_.gt(20)大于20)
const res8=await userList.where({ age:_.gt(20)}).get();
console.log("年级超过20岁的同学",res8.data)
(4.8) 获取数据总数.count()
和 get() 区别只返回数量,不会返回对象数组
async onTotal(){
const res=await userList.count()
console.log(res)
},
云函数
1.在project.config.json中指定云函数的根目录
"cloudfunctionRoot": "functions/",
2.新建云函数
右键新建Node.js云函数
3.在新建的云函数index.js中编写代码
4.云能力初始化
// 云函数入口文件
const cloud = require('wx-server-sdk')
//云能力初始化
cloud.init({
env:'lianxi-6g94su9j2e6c****'
})
// 云函数入口函数
//传入的都在event
exports.main = async (event, context) => {
const s=event.a+event.b
return s
}
5.写完长传并部署云端安装依赖
在云函数里操作数据库
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init({
env:'lianxi-6g94su9j2e6cd4d9'
})
//获取数据库
const db=cloud.database()
//获取集合
const userList=db.collection("userList")
// 云函数入口函数
exports.main = async (event, context) => {
return await userList.get()
}
页面中使用
//可以利用success回调/promise.then/async+await拿到数据
wx.cloud.callFunction({//要调用的那个云函数
name:'add',
data:{a:1,b:3},
success:(res)=>{//使用回调拿到
console.log(res)
}
})
云函数获取身份标识
wx.cloud.callFunction({
name:'getID',
success:(res)=>{
console.log(res.result)//和数据库的openid相同
}
})
//getID的云函数的index.js
// 云函数入口函数
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return wxContext.OPENID //openid
}
获取服务器时间db.serverDate()
云存储
wx.cloud.uploadFile()将本地资源上传至云存储空间
如果上传至同一路径则是覆盖写
项目 | Value |
---|---|
filePath | 要上传文件资源的路径 |
cloudPath | 云存储路径 |
上传图片到云内存,并在页面显示出来
async uploadFiles(){
const res=await wx.chooseMedia();
// 获取多张图片路径数组
const pathArr=res.tempFiles.map(item=>{
return item.tempFilePath;
});
// 创建匹配后缀的正则表达式
const reg= /\.\w+$/;
const arr=[];
pathArr.forEach(path=>{
// 获取当前这张图片的后缀
const suffix=reg.exec(path)[0];
const p= wx.cloud.uploadFile({
filePath:path,
cloudPath:`***/img${Math.random()}${suffix}`,//保存到***下的文件夹里面
})
arr.push(p)
})
//当图片所有图片都成功拿到结果,执行下一次操作
const result=await Promise.all(arr)//上传多个图片要,都上传完才能拿到所有的
const imgArr=result.map((item)=>{
return item.fileID
})
this.setData({imgArr})
},
上传文件
//选择本地文件
const res = await wx.chooseMessageFile();
console.log("选择结果", res);
// 选择上传的第一个文件
const file = res.tempFiles[0];
// 拿到该文件的名字和路径
const { name, path } = file;
// 将该文件上传至云存储
const result = await wx.cloud.uploadFile({
filePath: path,
cloudPath: "2009b/" + name,
});
console.log("上传结果", result);
wx.cloud.downloadFile()下载文件
下载图片或文件
const res=await wx.cloud.downloadFile({
fileID:'cloud://lianxi-6***1241440970242.png',})
//res 拿到一个本地的临时id
//将下载的图片保存到相册
wx.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
})
// 打开该文件
wx.openDocument({
filePath: path,
});
wx.cloud.deleteFile()删除文件
wx.cloud.deleteFile({
fileList: [
"cloud://cloud1-7***.docx",
"cloud://cloud1-7gna5m2cd***.jpg",
],
});
wx.cloud.getTempFileURL()获取真实链接
async geturl() {
const res = await wx.cloud.getTempFileURL({
fileList: [
"cloud://cloud***477825.jpg",
],
});
console.log("真实链接", res);
},
Mobx
https://github.com/wechat-miniprogram/mobx-miniprogram-bindings
修改数据
export const store = observable({
// 数据字段
obj:[{
name:'张三',
}],
// actions
update: action(function (num) {
this.obj=[...this.obj,num]
}),
update2: action(function (num) {
this.obj=[...this.obj.slice(0,1)]
}),
});
page里面打印数据
wx.nextTick(()=>{
console.log(this.data.obj)
})
wx.getAccountInfoSync() 获取当前帐号信息。
开发环境
微信支付
支付方式
1.展示固定的收款码,扫码支付
2.动态生成收款码,微信扫码支付
3.第三方网站/app,跳转到微信支付,支付完跳转回去
4.公众号嵌入的网页中,不用跳转,直接唤起微信支付
5.小程序中,直接唤起微信支付
微信小程序支付过程
- 已登录用户在小程序中调用商户系统后台接口下单
- 商户系统后台生成平台订单,并调用微信支付系统下单接口生成预付单
- 商户系统后台生成带签名的支付参数信息返回给小程序
- 用户在小程序中使用收到的参数调用wx.requestPayment发起微信支付
- 微信支付系统异步通知商户系统后台支付结果,并返回给小程序执行
wx.requestPayment的回调函数 - 用户在小程序中调用商户系统后台查单接口查询支付状态
const order = await request.post('/order', {
phone,
meal_time: '立即取餐',
meal_type: '打包带走',
products: [{ id: 181, count: 1 }],
pay_type: '微信支付',
desc: '7日包5G-wyx'
});
let payInfo={};
if (order.errmsg === '已存在未完成的订单') {
const info = await request.get('/order/current');
payInfo=info.data.pay_info;
}else{
payInfo=order.data;
}
wx.requestPayment(payInfo);
//requestPayment,success不一定就付钱了,需要再请求一个接口判断是否真付钱了
1.先调用后端支付接口,获取requestPayment需要的数据
2.使用wx.requestPayment(Object object),把接口获取到的数据传过去
项目 | Value |
---|---|
timeStamp | 时间戳,从 1970 年 1 月 1 日 00:00:00 至今的秒数,即当前的时间 |
nonceStr | 随机字符串,长度为32个字符以下 |
package | 统一下单接口返回的 prepay_id (预付单)参数值,提交格式如:prepay_id=*** |
signType | 签名算法,应与后台下单时的值一致 |
paySign | 签名,具体见微信支付文档 |
wx.requestPayment({
timeStamp: '',
nonceStr: '',
package: '',
signType: 'MD5',
paySign: '',
success (res) { },
fail (res) { }
})
二次支付
第一次请求是吧(预设单id)prepay_id存起来,第二次是使用第一次的prepay_id发起支付
从前端的角度来梳理微信支付(小程序、H5、JSAPI)的流程
云函数统一下单
分享
1.button open-type="share"设置
<button open-type="share">分享给好友</button>
2.onShareAppMessage设置
Page({
onShareAppMessage() {//分享
return {
title: '充值优惠',
path: '/pages/pay/pay',
imageUrl:'../../images/banner-top.jpeg',
// promise 属性可以动态设置这些
}
},})
自定义导航栏navigation
1.“navigationStyle”: “custom”
局部的.json文件或者app.json全局设置
wx.getSystemInfo()获取屏幕全部信息
wx.getMenuButtonBoundingClientRect()获取按钮的
// app.js
App({
onLaunch() {
//自定义导航栏 获取设备顶部窗口的高度(不同设备窗口高度不一样,根据这个来设置自定义导航栏的高度)
wx.getSystemInfo({
success: (res) => {
let custom = wx.getMenuButtonBoundingClientRect()
this.globalData.statusBarHeight = res.Hieght
}
})
},
globalData: {
statusBarHeight: 0,
}
})
//在页面getapp().globalData.statusBarHeight获取
客服
1.点击按钮接入客服
<button open-type="contact">客服</button>
2.在微信公众平台添加客服
3.用户向客服发起对话
- 客服人员可以登录移动端/网页版客服
客服回话
自定义tabBar
1、app.json中修改tabBar:{custom:true}
如果自定义显示不了,就显示list里面的数据
自定义样式需要取消样式隔离
{
"tabBar": {
"custom": true,
"color": "#000000",
"selectedColor": "#000000",
"backgroundColor": "#000000",
"list": [{
"pagePath": "page/component/index",
"text": "组件"
}, {
"pagePath": "page/API/index",
"text": "接口"
}]
},
"usingComponents": {}
}
2. 创建根目录custom-tab-bar文件夹+四个文件
index.js
index.json
index.wxml
index.wxss
3.点击跳转切换
样式参考 vant-ui自定义tabBar
//使用list遍历
data:{
list:[{
"pagePath": "page/component/index",
"text": "组件"
}, {
"pagePath": "page/API/index",
"text": "接口"
}]
}
//通过数据遍历渲染tabBar
或者使用navigator
<view>
<navigator open-type="switchTab" url="/pages/pay/pay" class="{{active=='pay'?'active':''}}">
充值
</navigator>
<navigator open-type="switchTab" url="/pages/welfare/welfare" class="{{active=='welfare'?'active':''}}">
福利
</navigator><navigator open-type="switchTab" url="/pages/my/my" class="{{active=='my'?'active':''}}">
我的
</navigator>
</view>
data: {
active: 'pay',//当前高亮
},
//在每个页面
onShow(options) {
const tabbar=this.getTabBar()
tabbar.setData({
active:'pay',
})
},
4.全局数据中设置选中的那一项的索引getTabBar修改索引
通过getTabBar()可以拿到tabBar页面的实例,然后setData
每次跳转页面修改索引,才能做到tabBar样式跟着页面动
const tabbar= this.getTabBar()
tabbar.setData({
active:'pay',
})
或者获取当前的页面栈getCurrentPages(),查找对应修改active
init() {
const page = getCurrentPages().pop();
this.setData({
active: this.data.list.findIndex(item => item.url === `/${page.route}`)
});
}
//每个页面设置
this.getTabBar().init();
分包
一个完整的项目,按需求分为不同子包,构建时打包成不同分包,使用时按需加载
优点:优化小程序首次启动下载时间,解耦操作
1主包+多个分包<=16M
主包:启动页面+tabBar页面
分包:只包含分包有关的页面+资源<2M
主包不能引用私包的资源,分包不能互相引用
分包可以引用主包的
在app.json的subpackages字段声明项目分包结构:
{
"pages":[ 主包
"pages/index",
"pages/logs"
],
"subpackages": [ 分包
{
"root": "packageA",
"pages": [
"pages/cat", 相对于root分包的路径
"pages/dog"
]
}, {
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
],
independent:true|false分包是否是独立分包
},
]
}
独立分包
可以独立于主包和其他分包单独运行(使用独立分包就可以打开程序)
和普通分包的区别:是否依赖主包
普通分包必须依赖主包,独立分包不下载主包,可以独立运行
(不能引用彼此资源)
independent:true|false分包是否是独立分包
{
"root": "packageB",
"name": "pack2",
"pages": [
"pages/apple",
"pages/banana"
],
independent:true//独立分包
},
分包预下载
在进入小程序某个页面的时候,自动下载可能需要的分包,提升启动速度,如点击我的页面,自动下载dog和cat页面<2M
"preloadRule": { //进行预下载
"pages/index": { //触发下载的页面路径
"network": "all", //指定网络下载,all不限网络、wifi:仅wifi下预下载
"packages": ["packageB"] //进入页面之后预下载那些包可以是分包的root或name
},
}
小技巧
输入框
<view>
<text>a输入的值</text>
<input type="text" confirm-type="search" bindconfirm="onComfirm1"/>
// confirm-type="search" 修改确认按钮文字
//bindconfirm按确认按钮之后
</view>
将数据写入全局数据
//App.js
App({
globalData:{
userInfo:123
}
})
整个小程序只有一个 App 实例,是全部页面共享的。开发者可以通过 getApp 方法获取到全局唯一的 App 实例,获取 App 上的数据或调用开发者注册在 App 上的函数。
//组件.js 写法一
onLoad(options) {
getApp().globalData.userInfo=456
getApp().globalData.abc=45555556
console.log(getApp().globalData.userInfo)
},
//组件.js 写法二
var app = getApp();
Page({
...
app.globalData.userInfo
...
});
数据存到缓存和全局的区别
缓存中的数据一直存在,全局中的数据只在小程序运行的时候存在,关掉之后就没有了,用于存(背景音乐id,是否有歌曲等)
更换图标
人气星星
//stars=48
<block wx:for="{{5}}" wx:key="*this">
<image src="{{stars>(index+1)*10?'/images/icon/star.png':'/images/icon/no-star.png'}}"></image>
</block>
//使用wxs
<block wx:for="{{util.toArr(stars)}}">//wxs处理数据传入48返回[ true,true,true,true,false],根据数组判断图片是否显示
<image src="{{item?'/images/icon/star.png':'/images/icon/no-star.png'}}"></image>
</block>
//util.wxs
function toArr(num){
if(!num){
return
}
var arr=[]
var num1=Math.floor(num/10)
for(var i=0;i<num1;i++){
arr.push(true)
}
// arr.fill(false,num1-1)
var num2=5-arr.length
for(var i=0;i<num2;i++){
arr.push(false)
}
return arr
}
module.exports={toArr:toArr}
小程序显示svg图标 通过转=>base64
1.转base64网站
2.页面
<view class="v1"></view>
.v1{
width:50rpx;
height: 50rpx;
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bW...");
background-repeat: no-repeat;
background-size: 100% 100%;
}
使用和风天气
开发文档地址:https://dev.qweather.com/docs/api/
(1)注册和风天气账号,申请key
登录账号->登录控制台->应用管理->创建应用->添加数据key
(2)配置小程序合法安全域名
小程序管理后台->开发>开发管理->开发设置->修改->合法域名配置request字段
使用icon图标
1.阿里巴巴选择需要的添加到项目
2.修改base64
3.下载
4.添加到小程序修改iconfont.css=>wxss
5.使用
<view class="iconfont icon-shoujitaobao"></view>
获取当前时间
let dataTime
let yy = new Date().getFullYear()//年
let mm = new Date().getMonth()+1//月
let dd = new Date().getDate()//日
let hh = new Date().getHours()//
let mf = new Date().getMinutes()<10?'0'+new Date().getMinutes():new Date().getMinutes()
let ss = new Date().getSeconds()<10?'0'+new Date().getSeconds():new Date().getSeconds()
dataTime = `${yy}-${mm}-${dd} ${hh}:${mf}:${ss}`;
//2022-10-23 12:23:43
flex布局第二行两边对齐问题
.cont{
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
// 这里使用伪元素
.cont::after {
display:block;
content: '';
width: 400px;
}
wx.showToat()跟着wx.showToat()
wx.showToast({
title: '123',
icon:'loading',
duration:5000,
success:()=>{
setTimeout(()=>{
wx.showToast({
title: '678',
duration:4000
})
},5000)
}
})
获取当前页面栈 getCurrentPages()
使用表单form统一获取表单项的值
监听form的submit
每一个表单项加name
提交按钮form-type=“submit”
通过form 的bindsubmit事件的回调参数event获取所有表单项的值
<form bindsubmit="onSubmit">
<input name="phone" placeholder="手机号"/>
<input name="label" placeholder="标签"/>
<button form-type="submit">确定</button>
</form>
小程序json-server环境搭建
1.安装
npm install -g json-server
2.跟目录创建myserver文件夹,创建json数据
3.进入myserver文件夹
//执行这个
json-server --watch db.json
//db.json,存放数据
{
"tabList": [
{
"id": 1,
"image": "http://vivo.njzykeji.com/static/img/xuangou.jpg"
}
]
}
4.package.json设置快捷打开服务,默认打开3000服务器
{
"scripts": {
"mock": "json-server db.json --port 3000"
}
}
5.npm run mock打开服务
6.使用数据
wx.request({
url: 'http://localhost:3000/tabList',
method:'GET',
success:(res)=>{
this.setData({
tabList:res.data
})
}
})
上线流程
如果是uniapp开发,使用小程序预览,先切换为线上url地址,从新运行到小程序,然后点击上传,输入修改信息,然后登录微信公众平台,版本管理进行上传审核
在小程序公众平台 上传
版本管理分为开发,审核,线上。先提交开发版本,然后审核,上线(上线可以一开始都传上去,也可以一点点更新)
分享页面全局设置
微信小程序没有全局分享配置,只能用页面onShareAppMessage 才可以。
// app.js
/**
* 全局分享配置,页面无需开启分享
* 使用隐式页面函数进行页面分享配置
* 使用隐式路由获取当前页面路由,并根据路由来进行全局分享、自定义分享
*/
// app.js
App({
globalData: { },
onLaunch() { this.overShare()},
overShare: function() {
// 调用隐藏路由回调
wx.onAppRoute(function(res) {
//获取加载的页面
let pages = getCurrentPages(),
//获取当前页面的对象
view = pages[pages.length - 1],
if (view) {
data = view.data;
if (true || !data.isOverShare) {
data.isOverShare = true;
view.onShareAppMessage = function() {
//重写分享配置
return {
title: '分享标题',
path:'page/index/index',
imageUrl:'/utils/未标题-1.jpg'
};
}
}
}
})
},})
map ios不显示
不能是number,必须是string
A—>B修改A的值
//b页面点击一个事件,
<view bindtap='supItemClick' data-id="{{item.id}}" data-name="{{item.name}}"></view>
supItemClick:function(e){
var name=e.currentTarget.dataset["name"];
var pages = getCurrentPages();
var prevPage = pages[pages.length - 2] //上一个页面
prevPage.setData({
["selectedSup.supName"]:name
});
wx.navigateBack({
delta: 1,
});
},
})
setDate修改指定值
改变对象的值
Page({
data: {
// 默认的数据
objs: {
sex: "女",
},
},
// 点击事件
btnClick() {
this.setData({
['objs.sex']: "男",
})
},
})
改变数组的值
const app = getApp()
Page({
data: {
// 默认的数据
imgData: [{
imgTit: "风景图1",
imgUrl: "https://img0.baidu.com/it/u=530426417,2082848644&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1656522000&t=0050fe01b5db9476166821b30d44655c",
}],
},
// 点击事件
btnClick() {
//数组动态赋值
const imgOne = "imgData[0].imgUrl";
this.setData({
[imgOne]: "https://img0.baidu.com/it/u=3643895624,2552772604&fm=253&fmt=auto&app=120&f=JPEG?w=1200&h=675",
})
},
})
1px线
.no-more--line {
position: relative;
width: 80rpx;
}
/* 1px边框 */
.no-more--line:after {
position: absolute;
box-sizing: border-box;
-webkit-transform-origin: center;
transform-origin: center;
content: ' ';
pointer-events: none;
top: -50%;
right: -50%;
bottom: -50%;
left: -50%;
border: 0 solid #eee;
border-width: 1px;
-webkit-transform: scale(0.5);
transform: scale(0.5);
}
小程序下载文件,删除下载的临时文件downloadFile()
wx.downloadFile({
url: url,
success: (res) => {
var savePath = wx.env.USER_DATA_PATH + '/' + this.getFileName(url);
const fs = wx.getFileSystemManager();
fs.saveFile({ //下载成功后保存到本地
tempFilePath: res.tempFilePath,
filePath: savePath,
success(res2) {
//获取了相册的访问权限,使用 wx.saveImageToPhotosAlbum 将图片保存到相册中
wx.saveImageToPhotosAlbum({
filePath: savePath,
success: () => {
// 保存完成后删除本地缓存文件
fs.unlink({
filePath: savePath,
fail(errmsg) {
console.log('remove file fail:', errmsg);
}
});
},
fail(err) {
}
});
},
fail(err2) {
}
});
},
fail: (err) => {
console.log('download error', err);
}
});
微信下载文件
downloadFileOpen(){
let link = 'https://www.gjtool.cn/pdfh5/git.pdf'
//下载文件
wx.downloadFile({
url: link,
success (res) {
if (res.statusCode === 200) {
const filePath = res.tempFilePath
wx.openDocument({
filePath: filePath,
showMenu:true, //关键点
success: function (res) {
console.log('打开文档成功')
}
})
}
}
})
}
左右列表联动
小程序骨架屏
点击省略号自动生成骨架屏
<import src="logs.skeleton.wxml"/>
<template is="skeleton" wx:if="{{loading}}" />//使用loading控制
<view class="" wx:else="{{!loading}}">//其他内容eles判断隐藏
消息订阅
操作步骤1:在微信公众号平台获得合适的模板
操作步骤2:wx.requestSubscribeMessage
wx.requestSubscribeMessage({
tmplIds: [''],//模板id号
success (res) { }
})
获取 uni.getUserProfile({})失效
//具体看官网
<button open-type="chooseAvatar" bindchooseavatar="getAvatar">
<input type="nickname" placeholder="请输入昵称" model:value="{{nickname}}" />
//有个问题不能监听到nickname填入值改变,输入可以监听到,
给input nickname一个id值,@blur="getnickname"
uni.createSelectorQuery().in(this) // 注意这里要加上 in(this)
.select("#nickname-input")
.fields({
properties: ["value"],
})
.exec((res) => {
const nickName = res?.[0]?.value
this.userData.name = nickName
this.upUserData(1)
})
网站扫描二维码,跳转小程序指定页面
onLoad: function(option) {
//通过二维码打开小程序 // scene 需要使用 decodeURIComponent 才能获取到生成二维码时传入的 scene
if (option.mediatorId != undefined) {
this.mediatorId = option.mediatorId;
this.getMediatorDetailFun();
}
//通过二维码打开小程序
if(option.scene) {
let scene = decodeURIComponent(option.scene);
this.mediatorId=scene.split('=')[1]
this.getMediatorDetailFun();
}}
ios端省略号效果不对,超出部分隐藏收起
<view style="display: -webkit-box;
text-overflow: ellipsis;
-webkit-line-clamp: 13;//控制这个
-webkit-box-orient: vertical;
overflow: hidden;" :style="{'-webkit-line-clamp':isHiddentHeight?'initial':'13'}">
<text>{{item.content}} </text>//需要在外面包裹一个元素
</view>
网站上此图片来自微信公众平台未经允许不可引用
//nuxt3 设置
app: {
head: {
meta: [
{
name: "referrer",
content: "never",
}]},
},
//其他设置
<meta name="referrer" content="never">
uv-waterfall 瀑布流 切换速度较快,数据混乱
//如果页面还没渲染结束,页面就跳走,但此时@changeList回调还在返回数据,可能会造成渲染出错,所以要想办法停止渲染,
<script>
export default {
onHide() {
this.$refs.waterfall.clear();
}
}
</script>