uniapp开发微信小程序项目总结

最近刚完成一个项目,项目不大,但是设计支付等功能,在这里进行记录一下,以便自己随时可以回顾

一、微信小程序

1、跳转到一个页面时想关闭之前的叠加的页面栈

最初我的做法是直接使用页面卸载,但是我发现用户体验度不是很好,会有很明显的闪动效果,而且因为我的项目登录方式有游客方式不是必登录,不登录的情况下也要能看到这个页面,所以就不能使用onShow这个方法了,但是从上一个页面跳回时还要能刷新更新一下数据。

onUnload(){
	uni.navigateTo({
		url:'要跳转的页面'
	})
}

后来百度了一下,找到了一种写法,感觉效果要好些,就是在跳转的时候调用一下跳转的页面 你想要刷新的方法

realodPage() {
	let pages = getCurrentPages();  //获取当前页面
	let beforePage = pages[pages.length - 2]  //获取上一个页面的实例
	  //1、调用上一个页面onLoad
	beforePage.onLoad() 
	//2、调用上一个页面方法
	// beforePage.fun()
	// uni.navigateBack({
	// 	delta: 0
	// })
},
onUnload(){
	this.realodPage()
}
2、开启订阅号
uni.getSetting({
	withSubscriptions: true,
	success(res) {
		if (!res.subscriptionsSetting.mainSwitch) {
			uni.openSetting({
				success(res) {
				}
			})
		} else {
			uni.requestSubscribeMessage({
				tmplIds: [‘模版Id’],
				success(res) {
					// console.log('requestSubscribeMessage 订阅信息', res);
					if (res[paymodelId] ==
						"accept") { // 用户点击确定后

					} else {
						// console.log('拒绝,不会再弹出弹框 只能去设置页膝盖');
						 uni.showModal({
							title: '您未开启消息订阅',
							content: '为了给您提供更好的服务,请您授权消息订阅',
							success: res2 => {
								if (res2.confirm) {
									uni.openSetting({
										success(res) {
											// console.log('打开设置页', res.authSetting);
										}
									})
								} else {
									// console.log('决绝')
								}
							}
						 })
	
					}
				},
				fail(errMessage) {
					// console.log("订阅消息 失败 ", errMessage);
				},
				complete(errMessage) {
					// console.log("成功 失败都执行 ", errMessage);
					that.buyClick()
				}
			})
		}
	},
})
3、百度地图经纬度转换

这个项目中用到地图导航,后管是用地图获取经纬度传到后端,后端再通过接口传到小程序端的,但是我使用的是百度地图,微信小程序用的腾讯地图,所以经纬度上会有差别导致地址不准所以需要转换一下,下面是我找到的转换方法
借鉴:https://blog.csdn.net/weixin_43311271/article/details/139468547

1.百度经纬度转换成腾讯/高德地图经纬度

function bMapTransQQMap(lng, lat) {
      let x_pi = 3.14159265358979324 * 3000.0 / 180.0;
      let x = lng - 0.0065;
      let y = lat - 0.006;
      let z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
      let theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
      let lngs = z * Math.cos(theta);
      let lats = z * Math.sin(theta);
      
      return {
          lng: lngs,
          lat: lats        
      }   
}

2、腾讯/高德地图经纬度转换成百度经纬度

function qqMapTransBMap(lng, lat) {
      let x_pi = 3.14159265358979324 * 3000.0 / 180.0;
      let x = lng;
      let y = lat;
      let z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi);
      let theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi);
      let lngs = z * Math.cos(theta) + 0.0065;
      let lats = z * Math.sin(theta) + 0.006;
     
      return {
          lng: lngs,
          lat: lats 
      } 
}

4、左滑删除功能

在这里插入图片描述

<view class="list">
			<view v-for="(item, index) in collectList" :key="index">
				<movable-area class="movable-area" v-if="show">
				  <movable-view class="movable-view" direction="horizontal" out-of-bounds="true" damping="50" friction="4" inertia="true" 
				  :x="movableX"
				   
				  >
					<view class="p-tb-30" style="position: relative;width: calc(100% - 80px);" @click="detailClick(item)">
						<view class="row collect m-lr-30" >
							<view class="collect-left">
								<image :src="item.ticketImage" mode="aspectFill" style="width:225rpx;height:180rpx;"></image>
							</view>
							<view class="collect-right">
								<view class="f30 text-two">{{item.ticketName}}</view>
								<view class="label m-t-30">活动</view>
							</view>
						</view>
						<!-- <image src="../../static/delete.png" mode="aspectFit" class="delete-img" v-if="item.type == 1"></image> -->
						<image src="../../static/yishixiao.png" mode="aspectFit" class="delete-img" v-if="item.type == 1"></image>
					</view>
					<view class="delete-btn" @click="delData(item)">删除</view>
				  </movable-view>
				</movable-area>
			</view>
		</view>

js

data(){
	return{
		// 设置开始的位置
		movableX:0,
		startX: 0,
		startY: 0,
		show:true,
	}
},
delData(item){
	this.movableX = -80
	let params = {
		favoriteId:item.favoriteId,
		userId:uni.getStorageSync('userId'),
	}
	getCollectCancel(params).then(res => {
		if(res.data.code === 200){
			this.movableX = 0
			this.show = false
			this.getData()
			uni.showToast({
				title: '删除成功',
				icon: 'success',
			})
		}
	})
},

css

.movable-area {
		width: 93%;
		height: 90px;
		overflow: hidden;
		padding: 30rpx 0;
		border-bottom: 1px solid #f1f1f1;
		border-radius: 15rpx;
		margin:auto;
	    margin-top: 30rpx;
		box-shadow: 5rpx 5rpx 20rpx #cdcdcd;
	}
	
	.movable-view {
		width: calc(100% + 80px); /* 增加额外的宽度用于显示删除按钮 */
		height: 90px;
		padding: 30rpx 0;
		display: flex;
		align-items: center;
		justify-content: space-between;
		background-color: #fff;
		position: relative;
		left: 0px; /* 默认隐藏删除按钮 */
	}
	
	.item-content {
	  width: 100%;
	  padding-left: 20px;
	  background-color: #fff;
	}
	
	.delete-btn {
	  width: 70px;
	  height: 90px;
	  line-height: 90px;
	  color: white;
	  background-color: red;
	  text-align: center;
	  padding: 30rpx 0;
	}
5、传参参数过长导致丢失问题

方式一:
A页面

uni.navigateTo({
	url: `/pages/index/infom/detail?url=${encodeURIComponent(JSON.stringify(item.location))}`,
})

B页面

onLoad(item) {
			
    // 传入需要跳转的链接 使用web-view标签进行跳转
    // this.url = decodeURIComponent(item.url)
	if (item.url) {
		this.urlLink = JSON.parse(decodeURIComponent(item.url))
	}
}

方式二:(其实这种方式我没用明白,地址我已经获取到了,但是一拿出渲染到页面就不行了,目前还不知什么原因,所以亲测第一种方式可)

A页面

uni.navigateTo({
  url: `/pages/index/infom/detail?url=${encodeURIComponent(JSON.stringify(item.location))}`,
  success: function(res) {
  	 // 通过eventChannel向被打开页面传送数据
  	 res.eventChannel.emit('todetailData', { data: item.location })
  }
})

B页面

const eventChannel = this.getOpenerEventChannel();
// 监听todetailData事件,获取上一页面通过eventChannel传送到当前页面的数据
eventChannel.on('todetailData',function(data){
	console.log('详情数据',data)
	this.urlLink = decodeURIComponent(data.data)
	console.log('this.urlLink',this.urlLink)
})
6、项目前端js代码混淆加密

写这个项目的时候,领导提了一个要求,为了代码安全,让给项目做一下代码加密。
之后我就开始百度了,刚开始研究的时候一头雾水,百度找实现方法也是看的迷迷糊糊的,今天才算是研究明白,研究明白之后才发现其实挺简单的,我用的是 javascript-obfuscator 插件实现的,还有一种 terser-webpack-plugin,但是我没用明白,有看会的朋友可以留言替我解惑一下

首先是安装 javascript-obfuscator

当前项目安装(这里我用pnpm安装一直报错安装不下来,不知道为啥,后来换了npm就安装下来了,yarn没有试)

yarn add javascript-obfuscator
#
npm install javascript-obfuscator

全局安装

npm install javascript-obfuscator -g

当前项目安装使用方法

npx javascript-obfuscator ./path_to_input_dir --output ./path_to_output_dir
// 混淆示例
先编译成小程序源码,比如uniapp编译后的dev代码位于/yourproject/dist/dev/mp-weixin
进入项目根目录 cd /yourproject/dist/dev/
执行混淆如下
npx javascript-obfuscator ./mp-weixin --output ./mp-weixin

全局使用方法

javascript-obfuscator ./path_to_input_dir --output ./path_to_output_dir

注意:
我使用 npx javascript-obfuscator ./mp-weixin --output ./mp-weixin 对整个项目进行混淆加密之后,项目就起不起来了,所以小程序包内的文件common文件,app.js不能进行混淆加密,然后就可能麻烦点一个一个文件进行混淆加密了
下面介绍一种相对方面的方式,但是对于我的项目而言稍微有点缺陷,就是有的文件混淆不到
借鉴:https://blog.csdn.net/qq_40358970/article/details/112952264
我是在跟unpackage同等级的建了一个code-obfuscation文件夹
在这里插入图片描述
index.js

// 检索的相对文件夹
const relativePath = '../unpackage/dist/dev/mp-weixin'
// 不需要混淆的js或文件夹
const exitFile = ['uni_modules', 'index.js', 'app.js', 'common']


var fs = require('fs')
var process = require('child_process');
var readDir = fs.readdirSync(relativePath);


// 需要存在的js
const czFile = []

var filePath = relativePath
var arr = new Array()
readFile(readDir, filePath)
// 读取相对路径下的所有文件
function readFile(readDir, filePath) {
	if (readDir.length > 0) {
		for (var i = 0; i < readDir.length; i++) {
			scannerFile(readDir[i], filePath)
		}
	}
}
// 扫描文件进行检索出js文件进行混淆
function scannerFile(file, filePath) {
	console.log("file-----" + file);
	var readdirpath = ""
	if (filePath == './') {
		readdirpath = filePath + file
	} else {
		readdirpath = filePath + "/" + file
	}
	if (exitFile.indexOf(file) < 0) {
		console.log('-->Start entering FS');
		fs.stat(readdirpath, (err, data) => {
			if (err) {
				console.log(err);
			} else {
				if (data.isDirectory()) {
					console.log('-->isDirectory:' + file);
					var readChildDir = fs.readdirSync(readdirpath);
					console.log(readChildDir);
					readFile(readChildDir, readdirpath)
				} else {
					console.log('-->isNotDirectory:' + file);
					if (file.indexOf('.js') >= 0 && file.indexOf('.json') < 0) {
						// 开始混淆代码
						console.log('-->Start confusing code:' + file);
						var cmd = 'npx javascript-obfuscator ' + readdirpath + ' --config index.json --output ' + readdirpath;
						process.exec(cmd, function(error, stdout, stderr) {
							console.log("error:" + error);
							console.log("stdout:" + stdout);
							console.log("stderr:" + stderr);
						});
						arr.push(readdirpath)
					} else {
						console.log('Non-folder - Non-js code :' + file);
					}
				}
			}
		})

	} else {
		console.log('-->skip------------');
	}
}

index.json

{
	"compact": false,
	"controlFlowFlattening": true,
	"controlFlowFlatteningThreshold": 1,
	"numbersToExpressions": true,
	"simplify": true,
	"shuffleStringArray": true,
	"splitStrings": true,
	"stringArrayThreshold": 1
}

然后进入code-obfuscation文件夹执行命令行

node .\index.js

在这里插入图片描述
不过像这种在同一个文件夹下的两个页面只会执行一个js混淆加密
在这里插入图片描述

7、前端封装的方法

借鉴地址:https://blog.csdn.net/weixin_55176296/article/details/131309370

1、将一个对象里面的键值对转换成url地址

export function tansParams(params) {
  let result = ''
  for (const propName of Object.keys(params)) {
    const value = params[propName];
    var part = encodeURIComponent(propName) + "=";
    if (value !== null && value !== "" && typeof (value) !== "undefined") {
      if (typeof value === 'object') {
        for (const key of Object.keys(value)) {
          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
            let params = propName + '[' + key + ']';
            var subPart = encodeURIComponent(params) + "=";
            result += subPart + encodeURIComponent(value[key]) + "&";
          }
        }
      } else {
        result += part + encodeURIComponent(value) + "&";
      }
    }
  }
  return result
}

该函数作为一个工具函数,用于将一个 JavaScript 对象转换为 URL 查询参数格式的字符串。在前端开发中,我们常常需要通过 AJAX 或者跳转链接的方式将数据传递到服务器端,此时将数据转换成 URL 查询参数格式是一种常见的做法。

下面是一个小栗子方便理解的

const params = {
  name: "Jack",
  age: 25,
  hobbies: ["swimming", "jogging"],
  address: {
    city: "Beijing",
    street: "Haidian",
  },
};
const str = tansParams(params);
console.log(str);
// 输出: name=Jack&age=25&hobbies[0]=swimming&hobbies[1]=jogging&address[city]=Beijing&address[street]=Haidian&

通过调用该函数,我们能够将 JavaScript 对象转换为经过序列化的 URL 查询参数格式的字符串,并且这个过程是通用的,适用于从前端到后端的服务端开发。

2、将两个对象数据覆盖,如果检测有就合并没有就不合并

export function objAssign(target, provide) {
  //注意这里遍历 target 的key
  Object.keys(target).forEach((key) => {
  // Object.prototype.hasOwnProperty.call 用于检查一个对象是否具有指定的自身属性(也就是不继承自原型链的属性)
    if(Object.prototype.hasOwnProperty.call(provide, key)){
      target[key] = provide[key]; 								
    }                                                                                                                   
  });
}

Object.prototype.hasOwnProperty.call 用于检查一个对象是否具有指定的自身属性(也就是不继承自原型链的属性)

const object = {
  name: 'John',
  age: 30
};
 
console.log(Object.prototype.hasOwnProperty.call(object, 'name')); // true
console.log(Object.prototype.hasOwnProperty.call(object, 'toString')); // false

例如:

const target = { a: 1, b: 2 };
const provide = { b: 3, c: 4, d: 5 };
objAssign(target, provide);
console.log(target); //{a: 1, b: 3}

跟obj.assign还是有一定的区别的

const target = { a: 1, b: 2 };
const provide = { b: 3, c: 4, d: 5 };
console.log('123',Object.assign(target,provide))
// {a: 1, b: 3, c: 4, d: 5}
  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
uniapp是一款跨平台的开发框架,支持同时开发微信小程序App、H5等多个平台的应用程序。在uniapp开发微信小程序的定位功能非常简单,可以通过调用uniapp提供的API实现。 首先,在uniapp项目中,我们可以使用uni.getLocation方法来获取用户的位置信息。这个方法会弹出微信小程序的位置授权提示框,用户可以选择是否授权获取位置信息。我们可以在页面的生命周期钩子函数中调用这个方法,例如在mounted钩子函数中。 在调用uni.getLocation方法之前,我们需要先引入uniapp提供的API,可以通过在页面的script标签中添加import语句来实现。引入之后,就可以在页面的方法中调用uni.getLocation方法了。 调用uni.getLocation方法后,会返回一个Promise对象,我们可以通过.then方法来处理获取位置信息成功的情况,并进行相应的处理操作,例如展示地理位置的信息。如果获取位置信息失败,可以使用.catch方法来处理。 通过以上的步骤,我们就可以在uniapp微信小程序中实现定位功能的demo了。当然,在实际开发中,我们还可以通过uni.showLoading等方法来优化用户体验,例如在获取位置信息期间显示一个加载动画。 总结一下,uniapp微信小程序定位demo的实现步骤如下:引入uniapp提供的API,调用uni.getLocation方法获取位置信息,处理获取位置信息成功或失败的情况,并进行相应的操作。希望以上的回答对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张张Z7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值