小程序页面配置
单位尺寸设置问题
- 绝大多数情况都可以用rpx
- 绝大多数的border可以用rpx
- 针对字体大小 当不需要根据分辨率的大小更改字体大小时可以选择使用px
- 使用vscode > 首选项 > 设置 > 搜索rpx 进行插件配置
css选择器相关
也有部分选择形式的选择器文档没有说明但也可以使用——实际开发中尝试。。。
字体设置
text {
font-family: "PingFangSC-Thin";
}
全局字体设置
在全局的样式文件中—— 原生项目是app.wxss
page {
font-family: "PingFangSC-Thin";
}
自定义组件相关——样式、通信、生命周期等
hover-class配合hover-stop-propagation使用阻止冒泡
hover-start-time & hover-stay-time
button主要属性
- size 大小
- type 颜色
- plain 镂空
- disabled 禁用启用
- loading 正在加载图标
下拉刷新onPullDownRefresh
- 触发下拉刷新的方式:
-
全局配置文件pages.json中配置(具有全局性):
"globalStyle": { "enablePullDownRefresh": true }
-
特定页面配置,pages.json文件中:
"pages": [ { "path": 'pages/list/index', "style": { "enablePullDownRefresh": true } } ]
-
页面中监听方法并做逻辑处理
<script> export default { data() { return {} } onPullDownRefresh() { // 相关逻辑 // uni.stopPullDownRefresh() // 关闭下拉刷新状态 // uni.startPullDownRefresh() // 用于手动开启下拉刷新 } } </script>
上拉加载onReachBottom
可配合onReachBottomDistance使用
<script>
export default {
data() {
return {}
}
onReachBottom() {
// 相关逻辑
}
}
</script>
uni.request 发送请求
uni.setStorage 做数据缓存( uni.setStorageSync同步设置)
图片的上传和预览
- uni.chooseImage 上传图片
- uni.previewImage 预览图片
条件编译
条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。
视图层面 和 js逻辑层面 以及 css样式层面 都可以使用条件编译
导航跳转和传参
有编程式导航(js API)和 声明式导航(组件形式)
通过onLoad(options){}的options接收路由参数
uni-app中组件的创建使用和生命周期
- 创建:同vue
- 使用:同vue
- 组件的生命周期同vue
组件之间的通信方式
- 父传子:同vue props
- 子传父:自定义事件 this.$emit('eventName')——@eventName=""; 同vue
- 相邻的兄弟组件:uni.on()
hidden 和 wx:if
原生小程序组件的hidden属性和wx:if属性都可以用来控制组件的显示和隐藏。如果频繁切换用hidden否则用wx:if。hidden不会触发组件的detached,但wx:if会。
小程序实现动画效果的两种方式
- 小程序提供的动画API
- css3、canvas
input标签有placeholder-style、placeholder-class、auto-focus等属性
小程序历史搜索记录与热门搜索功能
- 编写标签组件 用于展示
- 历史搜索 可以存到缓存中从缓存获取 限制历史搜索记录的数组长度 优化界面(添加新的历史记录时 删除历史记录数组的末尾元素)
- 热门搜索 来自于服务端需要请求接口
- 对搜索结果进行下拉加载更多数据的两种方式:1: 用scroll-view组件 2: 用onReachBottom
- 如果下拉请求返回的没有更多数据了 就不需要继续请求加载接口了,这个需要优化:(判断已加载数据和总数据量是否相等来判断是否已经加载完,或者判断接口请求回来的数据是否是空数组但是不够严谨,优选第一种方式)
- 下拉操作过快,请求发送过快导致出现重复数据:(通过锁的概念,设置一个loading属性,发送请求时判断loading状态,请求时和请求结束更新loading状态)
跳h5
- 微信小程序开发配置后台>开发管理>开发设置>业务域名: 下载校验文件上传到h5域名下的服务器上的根目录里,业务域名中添加h5链接的域名
- 用web-view组件 web-view文档
实现录音功能
- Uni-app提供了uni.getRecorderManager()等方法
- 微信原生也提供了相应的API 录音管理器文档
下面是以uni.getRecorderManager()为例的大概实现
<view class="record">
<view @touchend="handleTouchend" @longpress="hanldeLongPress">
<text v-if="!recordUrl">{{recordText}}</text>
<view class="play-btn" v-if="recordUrl" @click="handleClickPlay">
<iconfont class="bf-icon" name="bf" color="#fff" size="50"/>
<text >{{recordText}}</text>
</view>
</view>
<text @click="handleResetRecord">重录</text>
</view>
methods: {
computeSignature(accessKeySecret, canonicalString) {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
},
// 长按开始录音
hanldeLongPress() {
this.recorderManager = uni.getRecorderManager();
this.recorderManager.start();
this.recordText = '录音中...';
},
// 结束长按,结束录音并将录音上传
handleTouchend() {
this.recorderManager.stop();
this.recorderManager.onStop( (res) => {
this.pressRecord = false;
const { host, file_name, credentials } = this.ossData; // 调oss接口取到的验证信息等
const { AccessKeySecret, AccessKeyId, SecurityToken, Expiration } = credentials;
const policyText = {
expiration: Expiration,
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
]
}
const policy = Base64.encode(JSON.stringify(policyText));
const signature = this.computeSignature(credentials.AccessKeySecret, policy)
uni.uploadFile({
url: `https://${host}`,
filePath: res.tempFilePath,
name: 'file',
header: { Authorization: `Bearer ${uni.getStorageSync('token')}` },
formData: {
key: this.ossData.file_name,
policy: policy,
OSSAccessKeyId: AccessKeyId,
signature: signature,
'x-oss-security-token': SecurityToken // 使用STS签名时必传。
},
success: (uploadFileRes) => {
this.recordUrl = this.ossData.file_uri;
this.recordText = '点击播放'
},
fail: (error) => {
this.recordText = '长按录音(选填)'
uni.showToast({
title: '录音上传失败',
icon: 'none',
duration: 2000
});
}
});
});
},
// 播放
handleClickPlay() {
const innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.src = this.recordUrl;
if(!this.recordUrl) {
innerAudioContext.stop();
}else {
innerAudioContext.play();
}
},
// 重录
handleResetRecord() {
this.recordUrl = ''
this.recordText = '长按录音(选填)';
},
}
实现签字版签字功能
打开签字版 (由canvas渲染)手写签名并提交
<view class="sign-canvas">
<view class="sign-close">
<view class="close-icon" @click="handleCloseSign">
<iconfont name="qx" size="52"></iconfont>
</view>
</view>
<view class="reset-box">
<view class="reset-sign" @click="clearClick">
<iconfont name="sx1" size="72"></iconfont>
</view>
</view>
<canvas class="sign-box" canvas-id="sign" @touchmove="move" @touchstart="start" @touchend="end" @touchcancel="cancel" @longpress="tap" disable-scroll="true" @error="error"></canvas>
</view>
// 页面加载完成后获取并设置canvas上下文及其基础配置
//获得Canvas的上下文
this.content = wx.createCanvasContext('sign');
//设置线的颜色
this.content.setStrokeStyle("#000");
//设置线的宽度
this.content.setLineWidth(3);
//设置线两端端点样式更加圆润
this.content.setLineCap('round');
//设置两条线连接处更加圆润
this.content.setLineJoin('round');
// 画布的触摸移动开始手势响应
start(event) {
//获取触摸开始的 x,y
let point = { x: event.changedTouches[0].x, y: event.changedTouches[0].y }
this.touchs.push(point);
},
// 画布的触摸移动手势响应
move(e) {
let point = { x: e.touches[0].x, y: e.touches[0].y }
this.touchs.push(point);
if (this.touchs.length >= 2) {
this.draw(this.touchs);
}
},
// 画布的触摸移动结束手势响应
end(e) {
console.log("触摸结束" + e);
//清空轨迹数组
for (let i = 0; i < this.touchs.length; i++) {
this.touchs.pop();
}
},
// 画布的触摸取消响应
cancel(e) {
console.log("触摸取消" + e);
},
// 画布的长按手势响应
tap(e) {
console.log("长按手势" + e);
},
error(e) {
console.log("画布触摸错误" + e);
},
//绘制
draw(touchs) {
let point1 = touchs[0];
let point2 = touchs[1];
touchs.shift();
this.content.moveTo(point1.x, point1.y);
this.content.lineTo(point2.x, point2.y);
this.content.stroke();
this.content.draw(true);
}
//清除操作
clearClick() {
//清除画布
this.content.clearRect(0, 0, 750, 700);
this.content.draw(true);
},
//保存canvas绘图
saveClick() {
const { host, file_name, credentials } = this.signOssData;
const { AccessKeySecret, AccessKeyId, SecurityToken, Expiration } = credentials;
const policyText = {
expiration: Expiration,
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
]
}
const policy = Base64.encode(JSON.stringify(policyText));
const signature = this.computeSignature(credentials.AccessKeySecret, policy);
uni.canvasToTempFilePath({
canvasId: 'sign',
success: res => {
// 在H5平台下,tempFilePath 为 base64
this.canvasUrl = res.tempFilePath;
uni.uploadFile({
url: `https://${host}`,
filePath: this.canvasUrl,
name: 'file',
header: { Authorization: `Bearer ${uni.getStorageSync('token')}` },
formData: {
key: this.signOssData.file_name,
policy: policy,
OSSAccessKeyId: AccessKeyId,
signature: signature,
'x-oss-security-token': SecurityToken // 使用STS签名时必传。
},
success: (uploadFileRes) => {
// ...
},
fail: (error) => {
// ...
}
});
},
fail: err => {
// ...
}
})
}