微信公众平台
公众号
订阅号
小程序:
基本语法
组件
api
业务逻辑
1,原生开发,
2,vue开发,,uniapp,wepy,mpvue
3,react 方式taro
微信开发者工具
小程序ID:开发,开发设置
个人服务器关联微信服务器:
开发 -开始开发-接入指南
配置服务器接收token
body-parser-xml:解析xml
基础
wxml html 页面骨架
wxss css 样式
xx.js js 业务逻辑
xx.json json配置文件(所有页面写在pages里)
pages里数组的第一项就是首页
view 相当于div块级元素
home.model做业务逻辑
home:只做业务处理
utils
api:接口文件
:base类
<template name=''>:创建模板
<template is= name>:调用模板
使用模板 import导入<import src='路径'/>
页面中写上标签<template is='文件名'></template
data传参
路由传参方式
switchTab:只能往tabbar页面(不带参)
reLaunch:哪一个页面都能跳(可以带参)
redirectTo:跳转非tabbar页面(可以)
navigateTo:带后退符号(可以)
传参:
1,地址栏拼接参数
2,目标页 onLoad接受传递的参数
下拉刷新
wx.stopPullDownRefresh
案列
const req = require('../../req/index.js'); //接口
Page({
data: {
list:[],
params:{
p:1
}
},
onLoad: function (options) {
let data ={
p:1
}
this.getList(this.data.params)
},
getList(data){
req.my.getrecord(data)
.then((res) => {
if (res.status == 1) {
this.setData({
user:res.data.user,
})
let list = res.data.integral_log
if(data.p==1){
this.setData({
list: list
})
wx.stopPullDownRefresh()
}else {
this.setData({
list: list ? this.data.list.concat(list) : this.data.list
})
}
}
})
.catch(req.err.show);
},
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
this.setData({
['params.p']: 1
})
this.getList(this.data.params)
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
this.setData({
['params.p']: ++this.data.params.p
})
this.getList(this.data.params)
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
样式
宽度:vw,高度:vh,
任何宽度都是750rpx
事件:
bindtap 点击事件 tap:事件名
bindlongtap:长按事件
cathtap:
bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。
事件传参:data-事件名= ‘value’
修改数据,this.setData({key:value})
适配 rpx 宽度 都是750prx
弹性盒布局
跳转传参
../notice_info/notice_info?id=${id}&type=${type}
缓存站10个页面
没有跨域问题。
请求的api放在列表中
开发,配置服务器信息api接口是https 的
http数据是明文传输,
生命周期
在app.js里的生命周期 onLaunch,onShow,onHide,onError。
onLaunch:初始化完成触发 全局触发一次。
onShow:小程序启动,或从后台进入前台显示会触发。
onHide:前台进入后台会触发。
onError:小程序脚本错误,或者api调用失败时,会触发。
执行了onLaunch和onShow
== 在页面里的生命周期==
onLoad 生命周期函数–监听页面加载
onReady生命周期函数–监听页面初次渲染完成
onShow 生命周期函数–监听页面显示
onHide 生命周期函数–监听页面隐藏
onUnload 生命周期函数–监听页面卸载
打开小程序后会依次执行onLoad,onReady,onShow方法
前后台切换会分别执行onHide和onShow方法,
当小程序页面销毁时会执行 onUnload方法
缓存优化:
取数据之前先判断数据是否存在缓存
有:读取缓存
没有:请求数据,存到缓存里
优先从缓存中获取
清除localstore,设置事件戳,超时时间
谁用直接引入
购物车逻辑:
加入购物车让你登录,
本地存一份
没有登录可以加入购物车:数据存到缓存中的
都在购物车页面写,
加入购物车,缓存
数量的加减
删除购物车,清空购物车
获取数量,总价钱
选中全选,反选
选中数量,选中总价格
提交
登录:
先调用wx.longin获取code
再调用自己后端的接口获取用户基本信息和token
微信支付
微信服务器:生成收款订单(prepay_id),预付款id
商户系统:库存数量,生成订单id,添加订单数据(未付款)
**用户系统 :**下单:商品,调ajax接口
1,生成订单id,添加订单数据,(未服款)
微信:生成收款订单(prepay_id)(预订单id,预付款id)
1。调用后端的下单接口,返回5个参数(时间戳,随机字符串,package预订单id,signType签名)
2。调用wx.requestPayment 进行支付,处理返回结果
前端:
1,调用后端下单接口,返回5个参数
2,调用wx.requestPayment,进行支付,处理返回结果
API
获取用户授权:
wx.getUserInfo
验证登录状态:wx服务器的登录状态
wx.checkSession
公众号
消息回复
1,配置服务器,公众号的消息可以转发到自己的服务器
公众号本身开发
1.消息回复
2.自定义菜单
用户在公众号发送消息 将消息发给微信的服务器 微信服务器做处理返回数据
用户在公众号发送消息 将消息发给微信的服务器 微信服务器不做处理 将消息转发给开发者服务器
需要一台外网访问的服务器
内网穿透(9+3)natapp
将一台局域网的服务器映射到外网 可以实现外网访问
公众号网页开发
1.分享朋友圈
2.调用微信的扫一扫,摇一摇
消息回复 (周公解梦 星座运势 情侣匹配 天气查询 。。。 每日音乐 点歌平台)
- 配置服务器 公众号的消息可以转发到自己的服务器
- 接受公众号消息 xml post url
- 处理消息
- 返回xml 数据格式
创建自定义菜单 调用微信的api接口
创建自定义菜单
1.获取access_token (当前的微信账号有权限,去申请公众号测试账号)
2.调用相关的接口
jssdk 微信的网页开发
网页 可以调用微信的功能
O7pxPBNkfsueenY6
1.安全域名的配置
2.通过模板ejs引擎将后端的数据注册到网页上
3.产生签名数据
a.获取jsapi_ticket
b.产生时间戳 以s为单位
c.产生16进制随机字符串
d. jsapi_ticket 时间戳 随机字符串 以及要调用微信功能的网页地址 进行加密产生签名
4.将签名数据注册到网页上
5.调用接口 所有接口必须在apiList 声明
保存照片到相册
let _this = this
wx.downloadFile({
url: _this.data.imgUrl, //图片地址后台传来的
success (res) {
if (res.statusCode === 200) {
let img = res.tempFilePath
wx.saveImageToPhotosAlbum({
filePath:img,
success(arr){
wx.showToast({
title: '保存成功',
icon:'success'
})
_this.setData({
isShow:false
})
}
})
}
}
})
video全屏展示
this.videoContext = wx.createVideoContext('myVideo', this);
this.videoContext.requestFullScreen({ direction: 90 });
搜索关键字标红
const getInf =(str, key) =>str.replace(new RegExp(`${key}`, 'g'), `%%${key}%%`).split('%%');
请求接口返回列表成功执行:this.searchTap();
searchTap:function(){
var list = this.data.list //list接口返回数据
for (var i = 0; i < list.length; i++) {
var dic = list[i];
var text = dic.name; //name接口存在的参数需要改变颜色的参数
if(list !=''){
dic.name =getInf(text, this.data.params.name); // this.data.params.name搜索关键字
}else {
return
}
}
this.setData({
list: list
});
},
页面
<view class="{{item== params.name?'e1':''}}" wx:for="{{item.name}}" wx:key="name">{{item}}</view>
富文本展示
页面:
<import src="../../wxParse/wxParse.wxml" />
<template is="wxParse" data="{{wxParseData:article.nodes}}" />
JS:
const WxParse = require('../../wxParse/wxParse.js')
接口请求成功后:
let _this = this;
let article = res.data.content
WxParse.wxParse('article', 'html', article, _this,5)
富文本:<wxParse nodes="{{htmlText}}" />(json引入wxParse)
"wxParse": "../../components/wxParse/wxParse"
scroll-view组件
//隐藏横向滚动条
::-webkit-scrollbar{
width: 0;
height: 0;
color: transparent;
display:none;
}
遮罩层
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background-color: rgba(0, 0, 0, .5);
z-index: 999;
授权点取消,再次进入再授权
let that = this;
// 获取位置信息
wx.getSetting({
success: (res) => {
if (res.authSetting['scope.userLocation'] != undefined && res.authSetting['scope.userLocation'] != true) { //非初始化进入该页面,且未授权
wx.showModal({
title: '是否授权当前位置',
content: '需要获取您的地理位置,请确认授权,否则无法获取您所需数据',
success: function (res) {
if (res.cancel) {
that.setData({
isshowCIty: false
})
wx.showToast({
title: '授权失败',
icon: 'error',
duration: 1000
})
} else if (res.confirm) {
wx.openSetting({
success: function (dataAu) {
console.log(dataAu)
if (dataAu.authSetting["scope.userLocation"] == true) {
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1000
})
that.getLocation(that);
} else {
wx.showToast({
title: '授权失败',
icon: 'error',
duration: 1000
})
}
}
})
}
}
})
} else if (res.authSetting['scope.userLocation'] == undefined) { //初始化进入
that.getLocation(that);
} else { //授权后默认加载
that.getLocation(that);
}
}
})
},
//重复点击
1,
data:{
lock:false
}
if (!this.data.lock) {
this.setData({
lock: true //true可以点击
});
2:
var lasttime = 0;
let d = new Date();
let nowtime = d.getTime(); //获取点击时间
if (nowtime - lasttime > 1500) { //1500ms内无法识别再点击
this.ping() //提交接口
}
lasttime = nowtime;
倒计时
gettimer: function () {
let time = 60;
this.setData({
timer: setInterval(() => {
time--
this.setData({
hint: time + '秒后重发'
})
if (time == 0) {
clearInterval(this.data.timer)
this.setData({
hint: '获取验证码',
})
}
}, 1000)
})
},
数字取整
<wxs module="filters" src="../../utils/addmul.wxs" />
---
var filters = {
toFix2: function (value) {
return parseFloat(value).toFixed(2)//此处2为保留两位小数
},
toFix1: function (value) {
return parseFloat(value).toFixed(1)//此处1为保留一位小数
},
toFix: function (value) {
return parseFloat(value).toFixed(0)//此处0为取整数
}
}
module.exports = {
toFix2: filters.toFix2,
toFix1: filters.toFix1,
toFix: filters.toFix
}
---
自定义tabbar
闪烁问题
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
this.getTabBar().setData({
selected: 0 //索引
})
}
分页
"enablePullDownRefresh": true,
"backgroundTextStyle": "dark"
data:定义params:{ }
onLoad:{
this.getList(data)
}
-------
onPullDownRefresh: function () {
this.setData({
['params.page']: 1
})
this.getList(this.data.params)
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
this.setData({
['params.page']: ++this.data.params.page
})
this.getList(this.data.params)
},
------
bindinput(e) {
const value = e.detail.value
const num = parseInt(e.detail.value.length)
if (num <= 200) {
this.setData({
value: value,
num: num
})
} else if(num>200){
$.toast('最多输入200字')
this.setData({
num:200,
value:''
})
}
},
分享
onShareAppMessage: function (res) {
if (res.from === 'button') {}
return {
title: this.data.Info.work_name,
path: 'pages/productionInfo/productionInfo?id='+this.data.Info.work_id,
imageUrl: this.data.Info.cover_id,
}
},
地理位置
腾讯地图api
地理位置获取城市
引入
var QQMapWX = require('../../utils/qqmap-wx-jssdk.js');
var qqmapsdk;
onLoad(){
qqmapsdk = new QQMapWX({
key: 'YUUBZ-T6C3X-RVI4M-7P2EQ-AEQWH-RTBCJ'
});
this.getUserLocation()
},
getUserLocation: function () {
let that = this;
wx.getSetting({
success: (res) => {
if (res.authSetting['scope.userLocation'] != undefined && res.authSetting['scope.userLocation'] != true) {
wx.showModal({
title: '请求授权当前位置',
content: '需要获取您的地理位置,请确认授权',
success: function (res) {
if (res.cancel) {
wx.showToast({
title: '拒绝授权',
icon: 'none',
duration: 1000
})
} else if (res.confirm) {
wx.openSetting({
success: function (dataAu) {
if (dataAu.authSetting["scope.userLocation"] == true) {
wx.showToast({
title: '授权成功',
icon: 'success',
duration: 1000
})
that.getLocation();
} else {
wx.showToast({
title: '授权失败',
icon: 'none',
duration: 1000
})
}
}
})
}
}
})
} else if (res.authSetting['scope.userLocation'] == undefined) {
//调用wx.getLocation的API
that.getLocation();
} else {
//调用wx.getLocation的API
that.getLocation();
}
}
})
},
// 获取定位当前位置的经纬度
getLocation: function () {
let that = this;
wx.getLocation({
success: function (res) {
let latitude = res.latitude
let longitude = res.longitude
app.globalData.lat = res.latitude;
app.globalData.lng = res.longitude; //把onload定位时候的经纬度存到全局
that.getLocal(latitude, longitude)
},
})
},
// 获取当前地理位置
getLocal: function (latitude, longitude) {
let that = this;
qqmapsdk.reverseGeocoder({
location: {
latitude: latitude,
longitude: longitude
},
success: function (res) {
console.log(res) //返回信息
$.toast('定位成功')
wx.setStorageSync('city_name', res.result.ad_info.city) //城市
},
});
},
进度条
组件 progress
<progress percent="" border-radius="20" color="#FC5B0A" stroke-width="8"backgroundColor="#ffdece"/>
上传oss
(尚街小程序案例)
uploadImg文件夹
config.js文件
var fileHost = "https://***********";//你的oss地址
var config = {
//aliyun OSS config
uploadImageUrl: `${fileHost}`,
AccessKeySecret:'GaLGiAGvVh2wWb3UvQdxDNuu6biZ1E',//登录oss控制台查看
OSSAccessKeyId: 'LTAI4G3bJRTvg5yvg35sCCsn',//登录oss控制台查看
timeout:200
};
module.exports = config
使用
var uploadImage = require('../../uploadImg/uploadImg.js');
//上传头像
uploadImg() {
let _this = this
wx.chooseImage({
count: 1, // 默认最多一次选择3张图
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: (res) => {
// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
var tempFilePaths = res.tempFilePaths;
//支持多图上传
for (var i = 0; i < res.tempFilePaths.length; i++) {
//显示消息提示框
wx.showLoading({
title: '上传中' + (i + 1) + '/' + res.tempFilePaths.length,
mask: true
})
uploadImage(res.tempFilePaths[i], 'images/',
function (result) {
_this.setData({
head_pic: result
})
wx.hideLoading();
},
function (result) {
wx.hideLoading()
}
)
}
}
})
},
确认订单页选择优惠券
selectedNum==index
data:{
selectedNum :-1,
}
if (this.selectedNum === i) {
this.selectedNum = -1; //取消选中
} else {
this.selectedNum = i;
}
网页变灰
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%);
-o-filter: grayscale(100%);
filter: url("data:image/svg+xml;utf8,#grayscale");
filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
-webkit-filter: grayscale(1);
排序
function compare(property) {
return function (a, b) {
var value1 = a[property];
var value2 = b[property];
return value1 - value2; //升序,降序为value2 - value1
}
}
this.setData({
list:this.data.medal.sort(compare('type'))
})
(科艺小程序案例)
小程序点赞 不获取列表直接改变状态
点击图片放大
bindtap='previewImage' data-url="{{item.image_url}}"
previewImage(e) {
let currentImg = e.currentTarget.dataset.url //图片链接
let urls = []
let gallery = this.data.gallery //图片数组
for (let i = 0; i < gallery.length; i++) {
urls.push(gallery[i].image_url)
}
wx.previewImage({
current: currentImg,
urls: urls
})
},
苹果端底部黑线处理
**1**
app.js里
wx.getSystemInfo({
success: (res) => {
//将机型存入到本地缓存 以免后期其他业务逻辑需要使用
wx.setStorageSync('Modelmes', res.model)
if (res.model === 'iPhone X' || 'iPhone XR' || 'iPhone XS Max' || 'iPhone 11' || 'iPhone 11 Pro' || 'iPhone 11 Pro Max') {
this.globalData.Modelmes = true;
} else {
this.globalData.Modelmes = false;
}
}
})
使用:
let { Modelmes } = app.globalData;
this.setData({
Modelmes: Modelmes
});
样式:padding-bottom:{{Modelmes?'30rpx':'0'}}
**2**
page {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
商品倒计时显示
单个倒计时用vant
多个倒计时:
<view class="countdown">
<view class="item">
<view class="txt-time">{{item.time.hou}}</view>:
<view class="txt-time">{{item.time.min}}</view>:
<view class="txt-time">{{item.time.sec}}</view>
</view>
this.severalCountDown(); //多个定时器
timeFormat(param) {
return param < 10 ? '0' + param : param;
},
severalCountDown: function () {
var that = this;
var time = 0;
var obj = {};
var timeList = that.data.list; //时间的数组
//遍历数组,计算每个item的倒计时秒数
timeList.forEach(function (item) {
// var endTime = new Date(item.endTime.replace(/-/g, "/")).getTime(); //结束时间时间戳 (格式时yyy:zz:xx)
var endTime = parseInt(item.end_time) * 1000; (这个格式是时间戳,*1000是转换为毫秒)
var currentTime = new Date().getTime(); //当前时间时间戳
time = (endTime - currentTime) / 1000;
// 如果活动未结束
if (time > 0) {
var hou = parseInt(time / (60 * 60));
var min = parseInt(time % (60 * 60 * 24) % 3600 / 60);
var sec = parseInt(time % (60 * 60 * 24) % 3600 % 60);
obj = {
hou: that.timeFormat(hou),
min: that.timeFormat(min),
sec: that.timeFormat(sec)
}
} else { //活动已结束
obj = {
hou: "00",
min: "00",
sec: "00"
}
clearTimeout(that.data.timeIntervalSeveral); //清除定时器
}
item.time = obj;
})
var timeIntervalSeveral = setTimeout(that.severalCountDown, 1000);
that.setData({
timeIntervalSeveral,
list: timeList (赋值)
})
},
动画
wx.createAnimation
案例,选择框的显示和隐藏
data:{
chose_box: false,
animationData: {}
}
show() {
let animation = wx.createAnimation({
duration: 500,
timingFunction: 'ease',
})
wx.getSystemInfo({
success: (res) => {
const H = res.safeArea.height H屏幕高度
if (this.data.chose_box) {
animation.translateY(0).step()
this.setData({
animationData: animation.export(),
chose_box: false
})
} else {
console.log(11);
animation.translateY(50 - H).step()
this.setData({
animationData: animation.export(),
chose_box: true
})
}
}
})
},
页面
<view class="ln-center card" bindtap="show">购买检测卡</view> 点击触发
</view>
<view class=" black" bindtap="show" animation="{{animationData}}">
</view>