uniappvideo避坑指南(H5小程序app)
Posted wang_前端Javascript
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniappvideo避坑指南(H5小程序app)相关的知识,希望对你有一定的参考价值。
今天写下这篇文章已是蓄谋已久了,背景是年初接到项目需求开发基于H5运行的视频学习平台,以及后来uniapp转小程序app开发。相信开发过uniapp的video应该或多或少都遇到过一些坑,开场就不多说了,直接上干货。
项目要求用户不得拖动进度条,由播放进度触发对应事件
首先说说uniappH5使用video
H5是基于浏览器运行,那么浏览器平台就是我们需要考虑的兼容问题,就像我们之前写pc端的时候对IE的多年奋战一样,给大家列举一下现在市上使用率比较高的浏览器平台
QQ浏览器=>360浏览器=>UC浏览器=>谷歌浏览器(这个如果不是开发者应该使用率不多)等等
就拿我们常见使用的浏览器举例把:
QQ、UC、360浏览器等常见平台都会在渲染video标签时劫持播放器,渲染内置可脱离网页进行播放,严重与项目需求不符,无论用何种方法都绕不开,
百度浏览器目前未发现劫持事件,但是运行百度时切入后台,过一段时间在切回浏览器项目是会白屏浏览器bug,无法绕开
开发H5如果需要背景和我一样的要注意及时和经理商量商量了
其次在说说app
各位开发者应该都知道video层级的问题,既然我们的需求是不然用户拖动进度条,那么就得考虑如何实现,我的思路是覆盖元素dom遮罩层,自己写播放控件,cover-view、cover-image是我们所需的救星,官方简介部分组件如map、video、textarea、canvas通过原生控件实现,原生组件层级高于前端组件(类似flash层级高于div)。为了能正常覆盖原生组件,设计了cover-view。
发现了光,但是开发一般发现video在全屏时cover-view不生效了,翻阅文档原理是app.vue页面video全屏不支持,得采用元素nvue页面写法
video全屏后,如何自行绘制界面?比如加个标题、加个分享按钮
app端 2.1.5 以上nvue页面的video也可以通过cover-view来绘制界面覆盖元素
继续我们的开发过程,完成在app端覆盖自定义播放组件,新的问题出现了,获取播放进度
@timeupdate="onTimeupdate"官方播放进度变化事件通过e.detail.currentTime获取进度赋值给initial-time达到保存进度,进入页面跳转到上传播放位置,但是发现nvue设置完毕后卡顿,timeupdate发现官方介绍说触发频率是250毫秒一次 ,且initial-time是实时推进的,打个比方timeupdate获取到的时间是4秒出发4次之后才是5秒,等于initial-time会被赋值4次,难,想办法,定义2个变量,一个进入页面赋值initial-time跳转到对应位置,一个通过timeupdate获取当前比方时间,ok了,
播放下一个视频时问题又来了,initial-time直接去上一个视频的e.detail.currentTime播放时间直接跳转了,需求无法完成,换思路,还是改用.vue页面的方式写吧,起码e.detail.currentTime是正常的,那我们全屏的时候怎么办呢,videoContext.seek()跳转到指定播放位置,采用timeupdate事件监听播放进度变化,超过3秒就不是正常播放,为用户手动拖拽进度条
this.videoTime = parseInt(e.detail.duration)
if((currenttime - this.curCourse.Progress > 3 || currenttime - this.curCourse.Progress <
-1) && this.plan.FinishedExam!== 1 && this.plan.FinishedCourses !== 1)
this.videoContext.seek(this.curCourse.Progress)
else
this.videoRealTime = currenttime
if(this.videoRealTime > this.curCourse.Progress)
this.curCourse.Progress = this.videoRealTime
这个大家应该能看懂把,变量在data中自行定义
实现效果达到预期,不足的是用户拖拽进度条,在使用seek()拖回来时video会触发@waiting事件加载,视频会卡顿一下。
打包交给测试,测试反馈播放视频会不定期闪退,我懵逼了。这怎么搞,没遇到过啊
开始因为是测试的手机太垃圾,死鸭子说你手机不行换手机测测,测试哄骗公司大大小小5,6个小姐姐的手机在测,现象一样,都是播放视频不定期会闪退。
怎么办,解决呀。代码没问题呀,初步闪退为内存消耗搞导致的,面向百度把
https://ask.dcloud.net.cn/question/117091
https://ask.dcloud.net.cn/question/66095
video高阶组件重新按照官方进行修改,发现怎么都不管用,
后来一直沿着这个思路百度优化,终于找到这篇文章,可以运行动态查看当前手机内存情况各位有时间组件研究一下把,问题找到了,但是解决方案?没有!!!
根本没有任何一篇文章说相似我的bug,只能自己摸索了。
距离测试反馈的闪退bug已经4天了,依然没有解决,emo了!!!
中间有想过是不是视频地址的编码问题或者是https等等,一一pas
就在刚刚突然想到nvue页面开发是基于原生渲染的性能更好,说干就干,开整
实际与预期一至,个人见解是nvue有更好的性能处理不vue页面更快,但是nvue缺点也是无奈,各位只能自己去摸索了,但是刚刚我们提到的e.detail.currentTime应该怎么办呢,个人解决方案 放弃initial-time调用保存的播放进度 在play事件里利用seek方法给拉过去
onplay(e)
//当开始/继续播放时触发play事件,这里的clStatus 是我自己定义的播放开始还是暂停的标识
console.log(this.clStatus,'onplay')
if(this.clStatus === 2)
this.videoContext.seek(this.curCourse.Progress)
this.clStatus = 1
this.videoContext.play()
到此bug优化完成,其实video里面还是有很多坑。这里我就不一样解释了 ,如果大家有一些见解欢迎和我一起探讨,后期个人一会去话一些时间去写一个可以自定义进度条的video播放器,我相信很多项目是有这样的需求的。但是uniapp插件目前还没有这方面的实例
创作不易,转载请注明出处谢谢
小程序表单校验uni-forms正确使用方式及避坑指南
小程序表单校验uni-forms正确使用方式及避坑指南
一、前言
小程序上使用表单理应是很常用,也很必须的功能,因为系统实用了uni-app,所以这时候会用到uni-forms,但使用过程中遇到不少问题。
这边的需求有3个:
- 即时校验(输入框失焦立即校验值)
- 需自定义校验规则
- 需要异步校验
满足这3个需求,就能实现绝大部分表单校验,然而直接使用官方的案例并不能满足,踩过不少坑,最后解决方案如下。
二、成果展示
以下展示均满足上述3个需求,下面示例代码可以直接看 第六点
三、uni-forms即时校验
实现即时校验,uni-forms需要加validate-trigger="bind"
,同时input添加@blur="binddata('字段名', $event.detail.value)"
示例:
<uni-forms ref="form" :modelValue="ruleForm" validate-trigger="bind">
<uni-forms-item label="账号" name="account">
<input v-model.trim="ruleForm.account"
@blur="binddata('account', $event.detail.value)"
placeholder="请输入您的登录账号" />
</uni-forms-item>
</uni-forms>
四、uni-forms自定义校验规则
需要自定义校验规则时,去掉uni-forms的:rules,同时onReady里加this.$refs.form.setRules(this.rules)
,其中validateFunction: this.checkEmail为自定义校验方法
示例:
<template>
<uni-forms ref="form" :modelValue="ruleForm" validate-trigger="bind">
......
</uni-forms>
</template>
<script>
export default
data()
return
// 校验规则
rules:
email:
rules: [
validateFunction: this.checkEmail,
,
],
,
,
;
,
onReady()
// 需要在onReady中设置规则
this.$refs.form.setRules(this.rules);
,
methods:
/**
* 表单验证邮箱
*/
checkEmail(rule, value, allData, callback)
if (value !== "" && !verifyEmail(value))
return callback("邮箱不正确");
callback();
,
,
;
</script>
五、uni-forms异步校验
通常使用异步方法来校验账号是否重复等,步骤:
- 首先需要自定义校验方法
validateFunction: this.checkAccount
- 然后进行常规的规则校验
- 再进行异步方法校验账号唯一性
需要使用Promise,校验通过使用return resolve()
校验失败使用return reject(new Error('错误提示信息'))
示例(核心代码部分):
export default
data()
return
// 校验规则
rules:
account:
rules: [
required: true,
errorMessage: '请输入您的账号',
,
validateFunction: this.checkAccount,
,
],
,
,
;
,
methods:
// 表单验证账号
checkAccount(rule, value)
return new Promise((resolve, reject) =>
// 先进行规则校验
if (value === '' || !verifyAccount(value))
return reject(new Error('只能输入4-30位英文、数字、下划线'))
// 再进行异步校验,checkUser为本系统api异步方法,结合你系统使用你自己的方法
apiCheckAccount( account: value )
.then((data) =>
if (data.exist)
return reject(new Error('账号已存在'))
resolve()
)
.catch((err) =>
return reject(new Error(err.message))
)
)
,
,
六、完整示例源码
<template>
<view class="register">
<view class="title">最实用表单校验</view>
<uni-forms ref="form" :modelValue="ruleForm" validate-trigger="bind" label-width="40">
<uni-forms-item label="账号" name="account">
<input v-model.trim="ruleForm.account" @blur="binddata('account', $event.detail.value)" placeholder="请输入您的登录账号" />
</uni-forms-item>
<uni-forms-item label="姓名" name="name">
<input v-model.trim="ruleForm.name" @blur="binddata('name', $event.detail.value)" placeholder="请输入您的姓名" />
</uni-forms-item>
<uni-forms-item class="form-item-center">
<button type="primary" @click="submit()">注册</button>
</uni-forms-item>
</uni-forms>
</view>
</template>
<script>
import apiCheckAccount from '@/api'
import verifyAccount, verifyName from '@/utils'
export default
data()
return
// 表单数据
ruleForm:
account: '', // 账号
name: '', // 姓名
,
rules: ,
,
onReady()
this.setRules()
// 需要在onReady中设置规则
this.$refs.form.setRules(this.rules)
,
methods:
// 提交表单
submit()
this.$refs.form
.validate()
.then(() =>
uni.showToast(
title: '注册成功!',
duration: 2000,
icon: 'success',
)
)
.catch((err) =>
console.log('表单校验失败:', err)
)
,
// 设置校验规则
setRules()
this.rules =
account:
rules: [
required: true,
errorMessage: '请输入您的账号',
,
validateFunction: this.checkAccount,
,
],
,
name:
rules: [
required: true,
errorMessage: '请输入您的姓名',
,
validateFunction: this.checkName,
,
],
,
,
// 验证账号
checkAccount(rule, value)
return new Promise((resolve, reject) =>
// 先进行规则校验
if (value === '' || !verifyAccount(value))
return reject(new Error('只能输入4-30位英文、数字、下划线'))
// 再进行异步校验,checkUser为本系统api异步方法,结合你系统使用你自己的方法
apiCheckAccount( account: value )
.then((data) =>
if (data.exist)
return reject(new Error('账号已存在'))
resolve()
)
.catch((err) =>
return reject(new Error(err.message))
)
)
,
// 验证姓名
checkName(rule, value, allData, callback)
if (!verifyName(value))
return callback('只能输入1-30位中英文和数字')
callback()
,
,
</script>
七、最后,点个赞
如果帮到你,点个赞再走嘛 :)
以上是关于uniappvideo避坑指南(H5小程序app)的主要内容,如果未能解决你的问题,请参考以下文章
小程序webview使用避坑(因为开发者配置域名错误导致打开失败)
Java避坑指南:finally块的陷阱及正确的关闭资源方式小