1、打开小程序项目的终端,执行 mpn init
,初始化package.json 文件;
2、执行 npm i @vant/weapp -S
,安装 vant-weapp 组件库,成功之后会生成一个 node_module 依赖包;
3、在微信开发者工具上,左上角“工具” 点击 “构建npm” ,成功之后会生成 miniprogram_npm文件;
4、将 app.json 文件的 “style”:"V2"
去掉,因为小程序新版基础组件强行加了许多样式,难以 覆盖;
5、修改 project.config.json 文件:setting 对象下面
6、使用:
全局引入:在 app.json 中配置
"usingComponents": {
"van-button":"@vant/weapp/button/index"
},
局部引入:在页面对应的 json 文件中配置(同上)
在 app.json 中配置
"tabBar": {
"color": "#999999",
"selectedColor": "#0071D0",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "",
"selectedIconPath": ""
},
{
"pagePath": "pages/me/index",
"text": "我的",
"iconPath": "",
"selectedIconPath": ""
}
]
},
1、判断是否存在 token,存在则校验 token 有效性,有效则继续,无效则清空 token;
2、token 失效或者不存在则走登录流程,首先调用wx:openSetting
(打开设置页面授权)判断用户是否已授权,未授权则让用户授权;
3、已授权则调用wx.login
获取登录凭证 code,将 code 发送给服务器,获取 openid、session_key 等信息,存储在本地;
4、用户点击按钮(根据需要设置open-type)触发事件,获取 iv、encryptedData,可以校验一下 code 的时效性;
5、调取服务器接口,拿到 token 缓存起来;
// 定义 login.js 文件
//获取到openid, session_key等信息
const login = () => {
return new Promise((resolve, reject) => {
// 调用微信登录接口获取用户临时登录凭证 code
wx.login({
success: (res) => {
if (res.code) {
// 登录成功,将 code 发送到开发者服务器
wx.request({
url: 'https://example.com/login',
data: {
code: res.code
},
success: (res) => {
// 获取用户唯一标识 OpenID 和会话密钥 session_key
const { openid, session_key } = res.data;
// 将用户信息存储到缓存中,生成自定义登录态
wx.setStorageSync('openid', openid);
wx.setStorageSync('session_key', session_key);
resolve();
},
fail: (err) => {
reject(err);
}
});
} else {
reject(res.errMsg);
}
},
fail: (err) => {
reject(err);
}
});
});
};
// 判断用户是否已授权
const checkAuth = () => {
return new Promise((resolve, reject) => {
// 获取用户当前设置状态
wx.getSetting({
success: (res) => {
// 判断用户是否已授权
if (res.authSetting['scope.userInfo']) {
resolve();
} else {
// 用户未授权,引导用户打开设置页面进行授权
wx.showModal({
title: '提示',
content: '检测到您未授权登录,请先进行授权。',
showCancel: false,
success: (res) => {
if (res.confirm) {
wx.openSetting({
success: (res) => {
if (res.authSetting['scope.userInfo']) {
// 用户已授权,可进行相关操作
resolve();
}
}
});
}
}
});
}
},
fail: (err) => {
reject(err);
}
});
});
};
// 在需要登录的页面调用 login() 方法进行登录授权和判断用户是否已授权
onLoad(){
login();
}
//下面是用户手动触发的getPhoneNumber方法
getPhoneNumber(e){
//这里可以使用 wx.checkSession 校验一下code 的有效性
//e 里面可以拿到iv、encryptedData;发送给服务器获取到登录token
}
我这里上服务器获取用户的信息之后用过接口返回;也可以用个wx.getUserInfo
来获取用户信息;
注意:在调用 wx.openSetting() 方法时,需要在小程序的 app.json 文件中添加相应的权限设置。例如,如果要使用用户信息组件,需要在 app.json 中添加如下代码:
"permission": {
"scope.userLocation": {
"desc": "获取你的地理位置信息"
},
"scope.userInfo": {
"desc": "获取你的个人信息"
}
}
资质:
1、小程序已完成实名认证:需要提交个人或企业相关资料进行审核,并通过后才能开通支付功能;
2、小程序已开通微信支付:小程序管理后台中,需要先开通微信支付功能,配置相关参数和密钥;
3、绑定微信商户号:必须关联商户号才能开通支付功能;
流程:
1、需要在微信支付商户平台中注册商户账号,并进行相关的资质认证和审核。通过审核后,可以获得微信支付的商户号、API密钥和证书等信息;
2、在小程序中申请微信支付功能,绑定商户号;
3、使用 wx.request 方法调用统一下单
接口,获取预付单信息,将获取到的信息传递给wx.requestPayment
方法发起支付请求;
wx.requestPayment({
timeStamp: payParams.timeStamp,
nonceStr: payParams.nonceStr,
package: payParams.package,
signType: payParams.signType,
paySign: payParams.paySign,
success(res) {
console.log('支付成功', res);
},
fail(err) {
console.log('支付失败', err);
}
});
微信小程序提供了 wx.showShareMenu API,可用于开启小程序页面的分享功能。开启分享功能后,用户可以将小程序页面分享给其他用户或群聊。
1、在小程序页面中调用 wx.showShareMenu
方法,开启分享功能。可以在 onReady 生命周期函数中调用该方法。
onReady: function() {
wx.showShareMenu({
withShareTicket: true,
success: (res) => {
// 分享功能开启成功
}
});
},
2、在小程序页面中定义一个自定义按钮,用于触发分享操作。在该按钮的 bindtap 属性中绑定 onShare 方法。
3、在小程序页面中添加分享统计代码。可以在 onShareAppMessage 生命周期函数中调用后台接口,记录分享事件并上传数据。
onShareAppMessage: function(res) {
const { from, target, webViewUrl } = res;
// 调用后台接口记录分享事件
// ...
return {
title: '分享标题',
path: '/pages/index/index',
imageUrl: '/images/share.png'
};
},
第1和第4都可以开启右上角的分享,
uni.openLocation({
latitude: 31.230416, // 上海的纬度
longitude: 121.473701, // 上海的经度
name: '上海市', // 地点名称
address: '中国上海市黄浦区人民广场', // 地址的详细说明
scale: 18, // 缩放比例
success: function(res) {
console.log('打开地图成功');
},
fail: function(err) {
console.log('打开地图失败', err);
}
});
在地图上显示指定位置的标记点,并且支持调用内置地图进行导航;打开地图后点击右下角导航图标会弹出选项弹窗,让用户选择使用哪一个地图应用程序进行导航;
根据官方说明不能由小程序跳转至任意app,只能跳回app,也就是只能从app跳至小程序,再由小程序跳回app;小程序返回 app 需要用户主动触发,所以不由 API 来调用,需要用 open-type 的值设置为 launchApp 的 button 组件的点击来触发;
如果需要在打开 APP 时向 APP 传递参数,可以设置 app-parameter 为要传递的参数。通过 binderror 可以监听打开 APP 的错误事件。
Page({
launchAppError (e) {
console.log(e.detail.errMsg)
}
})
参考:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/launchApp.html
注意:
1、小程序也不能打开手机默认浏览器;
需要用户点击、需要确认跳转才可以打开另一个已发布的小程序,写文章时小程序之间跳转没有任何限制,可以随意跳转;
wx.navigateToMiniProgram({
appId: 'wx1234567890', // 要打开的小程序的appId
path: '/pages/index', // 打开的页面路径,如果为空则打开首页
extraData: {
foo: 'bar' // 需要传递给目标小程序的数据,格式为键值对
},
success(res) {
console.log('打开小程序成功', res);
},
fail(err) {
console.log('打开小程序失败', err);
}
});
需要保证用户已经授权并登录了目标小程序,否则会导致跳转失败;路径传参可以在打开的页面中 onLoad 生命周期通过 options 获取;extraData 通过小程序的 app.js 通过 onLaunch、onShow 参数 e.referrerInfo
获取;
如果想返回之前小程序可以使用:wx.navigateBackMiniProgram 只有在当前小程序被其他小程序打开的时候才可以调用成功;
首先需要在 app.json 里面配置获取位置权限;(uni-app 需要在manifest.json 里面的 mp-weixin 里面设置)
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序内的定位服务"
}
}
请求授权和获取位置信息都是异步操作,需要在回调函数中处理结果。另外,如果用户拒绝授权或未授权时,会导致 wx.getLocation 方法失败;
// 请求授权
wx.authorize({
scope: 'scope.userLocation',
success: function() {
// 授权成功,获取位置信息
wx.getLocation({
type: 'wgs84', // 坐标类型,默认为wgs84,可选gcj02
success: function(res) {
const latitude = res.latitude; // 纬度
const longitude = res.longitude; // 经度
const speed = res.speed; // 速度,单位m/s
const accuracy = res.accuracy; // 位置精度
console.log('获取位置信息成功', res);
},
fail: function(err) {
console.log('获取位置信息失败', err);
}
});
},
fail: function() {
// 授权失败,提示用户开启权限
wx.showModal({
title: '未授权地理位置信息',
content: '请在设置中打开地理位置权限',
showCancel: false,
confirmText: '确定'
});
}
});
在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限;
wx.chooseAddress({
success(res){
console.log(res)
},
fail(err){
console.log(err)
}
})
可以调起用户编辑收货地址原生界面;可以选择已有地址,也可以添加新地址;
在 app.js 中
App({
onLaunch() {
this.autoUpdate();
},
globalData: {
userInfo: null
},
//检测版本更新
autoUpdate(){
//检测当前设备是否可用getUpdateManager api
if(wx.canIUse('getUpdateManager')){
const updateManasger = wx.getUpdateManager();
//检测是否有版本更新
updateManasger.onCheckForUpdate(function(res){
if(res.hasUpdate){
wx.showModal({
title: '更新提示',
content: '需要重启小程序完成更新',
success: (res) => {
if (res.confirm) {
//更新成功,强制重启小程序并使用新版本
updateManasger.onUpdateReady(function(){
updateManasger.applyUpdate();
})
//更新失败,提示用户删除小程序重新进入
updateManasger.onUpdateFailed(function(){
wx.showModal({
title: '更新提示',
content: '小程序更新失败,请您删除当前小程序,重新搜索打开!'
})
})
}
}
})
}
})
}
}
})
1、登录企业微信后台:应用与小程序-小程序-关联小程序;或者登陆小程序后台:设置-关联设置-关联的企业微信;
2、关联过程中需要小程序管理员授权;
3、对小程序进行可见范围设置;这样企业微信成员就可以在工作台看到小程序了;
要在小程序中实现扫码、拍照和相册功能,可以使用微信提供的 API 接口。以下是具体实现方法:
1、扫码
需要获取摄像头权限。可以通过 wx.authorize 接口请求用户授权,或者在 app.json 文件中设置 "permission": {"scope.camera": {"desc": "用于扫码"}}
scanCode: function() {
wx.scanCode({
onlyFromCamera: true,
success(res) {
console.log('扫码成功', res.result)
},
fail(res) {
console.log('扫码失败', res)
}
})
}
2、拍照
同样需要获取摄像头权限;
wx.chooseMedia({
count: 1,
sizeType: ['original'],
sourceType: ['camera'],
success(res) {
console.log('选择照片成功', res.tempFilePaths)
},
fail(res) {
console.log('选择照片失败', res)
}
})
3、相册
需要获取相册访问权限。可以通过 wx.authorize 接口请求用户授权,或者在 app.json 文件中设置 "permission": {"scope.writePhotosAlbum": {"desc": "用于保存图片到相册"}}
wx.chooseMedia({
count: 1,
sizeType: ['original'],
sourceType: ['album'],
success(res) {
console.log('选择照片成功', res.tempFilePaths)
},
fail(res) {
console.log('选择照片失败', res)
}
})
移步到:微信小程序接入客服功能
跟目录下新建文件夹 api ;
1、新建 http.js :定义 baseUrl 方便后期维护;
2、新建 request.js :
import { baseUrl } from "./http"
import storage from "../utils/storage";
module.exports={
request:function(url, method, data){
let fullUrl = `${baseUrl}${url}`;
let token = storage.get('token');
wx.showLoading({ title: '数据请求中' });
return new Promise((resolve,reject)=>{
wx.request({
url: fullUrl,
method,
data,
header:{
'content-type': 'application/json',
'Authorization': 'Bearer' + token
},
success(res){
wx.hideLoading();
if(res.data.status == 200){
resolve(res.data);
}else if(res.data.status == 401){
wx.showToast({
title: '登录失效',
icon: "none"
})
wx.reLaunch({
url: '/pages/login/index',
})
}else{
wx.showToast({
title: res.data.message,
icon: "none"
})
reject(res.data.message);
}
},
fail(err){
wx.reLaunch({
url: '/pages/login/index',
})
wx.hideLoading();
wx.showToast({
title: err.errMsg,
icon: "none"
})
reject(err);
}
})
})
}
}
3、新建模块 api 文件 (user_api)
import { request } from "./request"
module.exports = {
user: (data) => request("user","get",data)
}
4、页面调用
const user_api = require("../../api/user_api");
user_api.user(data).then(res=>{
console.log(res)
})
在 utils 文件夹下新建 storage.js 文件
/**
- 同步新增:get(key)
- 同步修改、删除:set(key,value);只传递 key 就可以删除对应的key:value
- 同步清空:clear()
*/
export default class storage {
//同步获取
static get(key){
if(!key) return null;
return wx.getStorageSync(key);
}
//同步存储、删除
static set(key, value){
if(!key) return;
if(value == null || value == 'undefined'){
return wx.removeStorageSync(key);
}else{
return wx.setStorageSync(key, value);
}
}
//同步清空
static clear(){
return wx.clearStorageSync();
}
}
封装一个全局组件 safe,借助 env(safe-area-inset-botton)
封装校验工具类
// 表单校验工具
export class validator {
constructor(rules){
this.rules = rules
this.error= []
}
validate(form){
this.error = [];
Object.keys(form).forEach(key=>{
let rule = this.rules[key];
let required = this.rules[key].required;
let message = this.rules[key].message;
let maxLength = this.rules[key].maxLength;
let fn = this.rules[key].fn;
if(rule){
if(required && !this.checkValue(form[key]) && !Array.isArray(form[key])){
return this.error.push(message || ('请填写'+key));
}
//校验key是数组
if(required && this.checkValueArr(form[key]).isNull && Array.isArray(form[key])){
return this.error.push(message || (`请完善${this.checkValueArr(form[key]).key}信息`));
}
if(maxLength && this.max(form[key], maxLength)){
return this.error.push(`最多可输入${maxLength}个字!`);
}
}
})
return this.error;
}
checkValueArr(arr){
let isNull = false;
let key = null;
for(let i in arr){
if(!arr[i].value){
isNull = true;
key = arr[i].name;
break;
}
}
return {isNull,key}
}
checkValue(value){
return value.toString().length > 0;
}
max(value, maxLength){
return value && value.length > maxLength;
}
}
页面使用
let rules = {
test:{
required:true,
message:"请输入用户名"
}
}
let fromVal = new validator(rules);
利用 class 类,在new时将规则传入,在提交校验时执行下面操作,将form数据传入进行校验;
let err = fromVal.validate(this.data.form);
上面是我根据前人的思路根据自己的项目封装的一个方法,
editor 是小程序提供的一个组件,搭配 EditorContext api 来实现工具栏的操作;
加粗
斜体
下划线
撤回
恢复
插入图片
删除
提交
Component({
properties: {
},
data: {
editorCtx:''
},
methods: {
// 初始化,获取到编辑器节点,缓存在data中,方便下面操作
onEditorReady(){
let that = this;
let query = wx.createSelectorQuery();
query.in(that).select("#myEditor").context();
query.exec(res=>{
that.editorCtx = res[0].context;
})
},
undo(){
console.log(1)
this.editorCtx.undo();
},
redo(){
this.editorCtx.redo()
},
insertImg(){
let that = this;
wx.chooseMedia({
count:1,
mediaType:["image"],
sourceType:["album"],
success(res){
that.editorCtx.insertImage({
src:res.tempFiles[0].tempFilePath
})
}
})
},
clear(){
this.editorCtx.clear()
},
submit(){
this.editorCtx.getContents({
success(res){
console.log(res)
}
})
},
format(e){
let type = e.currentTarget.dataset.type;
this.editorCtx.format(`${type}`)
}
}
})
back(){
const pages = getCurrentPages();
const prePage = pages[pages.length-2];
console.log(prePage)
prePage.setData({
msg:'sssss'
})
wx.navigateBack();
}
想让上一页监听到,可以在后面调用一下前一页的方法;
1rpx 在IOS部分机型渲染像素点比较低,出现偶尔不显示的情况。可以设置为 1px 然后对边框进行缩放;
尽量避免多行整体布局使用 flex:1;因为这个1是针对剩余空间进行分配,而不是父元素的宽度;
let c = `arr[${i}].name`
this.setData({
"obj.a":b,
[c]:d
})
用 catchtap 来绑定事件;
应用:onLaunch onShow
页面:onLoad onShow onReady
组件:attached() -> ready() -> moved() -> detached()
class="name {{isOk?'a':'b'}}"
style="height:{{nav}}rpx"
页面:
var query = wx.createSelectorQuery();
query.select('.header').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec((res) => {
var listHeight = res[0].height; // 获取list高度
this.setData({
height:listHeight
})
})
组件:
var query = wx.createSelectorQuery().in(this);
query.select('.header').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec((res) => {
var listHeight = res[0].height; // 获取list高度
this.setData({
height:listHeight
})
})
方法放到 ready 周期里面,如果还获取不到,在用定时器包裹;
组件json中添加 “component”: true
只需要在小程序后台,将服务端域名配置成合法域名
1、使用uni-app提供的 cover-view、cover-image等标签;
2、给canvas标签一个判断控制显示隐藏;
在配置里面设置 navigationStyle:custom ,原生和uni-app 有区别;获取设备头部信息:uni.getSystemInfo({}),获取状态栏高度,导航栏高度;
1、跳转方式区别
navigateTo:跳转到下一页,保留当前页;
navigateBack:关闭当前页面,跳转到前一页;
redirectTo:关闭当前页面,跳转到其他页面;
reLaunch:关闭所有页面,跳转到某个页面;
switchTab:关闭所有非 tabBar 页面,跳转到 tabBar 页面;路径不可携带参数;
js 中使用方法 getCurrentPages() 可以获取当前页面战;
2、生命周期
onLaunch:小程序初始化完成触发,只触发一次;(获取用户信息)
onShow:小程序启动、后台进入前台触发;
onHide:小程序从前台进入后台触发;
onError:收集错误信息;
onPageNotFound:入口页面找不到时,通过它抱错,处理;
onLoad:页面初始化触发,一个页面只调用一次;(发送请求,初始化数据)
onShow:页面显示、后台进入前台触发;
onReady:页面初始化完成触发,只调用一次;
onHide:切入后台触发;
onUnload:页面卸载触发;
onPullDownRefresh:页面下拉刷新触发
onReachButton:
3、二者关系
navigateTo:onHide - onLoad - onShow - onReady
navigateBack:onUnload - onShow
redirectTo:onUnload - onLoad - onShow - onReady
小程序后台,右上角-工具;输入扫码之后进入的页面路径;
下载企业微信插件(设置-扩展设置-模拟器插件-企业微信模拟器),然后将小程序模式调整为企业微信小程序模式;
使用的是 van-field 组件,可以检查组件的配置参数是否正确,例如 auto-focus 或 focus 参数是否设置为 true
页面跳转,ios偶尔会跳转失败,navigateTo成功和完成的回调都能打印出来;具体原因不明,在网络请求拿到结果后跳转时延迟1秒就可以降低失败概率,但是依然会出现跳转失败的情况;
猜测可能是焦点异步有关系;
http://shop.jisuapp.cn/pecial/a79256.html
安装插件 “微信小程序插件” ,用微信开发者工具创建小程序项目,然后用 vscode 打开;就可以开发代码了;