快应用介绍遇到的问题及解决方案一些开发实践和感悟快应用介绍网页:网页不需要安装,体验不够好;NativeApp:原生App体验流畅,但需要从app下载,直接从商店下载安装给用户使用,安装包消耗流量大;应用快捷:深度集成在手机操作系统中,用户无需下载安装直接在手机上运行,??即可流畅体验应用内容。与微信小程序类似,微信小程序嵌套在微信应用中,快应用嵌套在手机系统中。入口比较齐全,包括:URL链接、全局搜索、应用商店、浏览器、负一屏、系统桌面、PUSH、语音助手、安全中心、垃圾清理、信息助手、天气、短信模板、日历、个性化主题、文件管理...开发技术快应用采用前端技术栈,由基础标签、样式、js脚本等组成,类似于Vue的开发方式。快应用是使用MVVM设计模式开发的。开发者无需直接操作DOM节点的增删改查,采用数据驱动的方式完成节点更新。开发实时编译渲染,完成后打包生成rpk包上传平台。快速开始安装快应用开发工具:https://www.quickapp.cn/docCe...新建一个快应用项目代码结构,开发、调试、编译、打包、提交、测试上传到开发者中心上官网,提交审核发布遇到的问题和解决方案缺点真实开发体验感受的问题:开发工具属于VSCode简易版,容易卡顿,偶尔会出现奇怪的问题。API并不都是统一的。每个制造商都有一些私有的API和函数。官方文档不完整。细节不够更新迭代慢,基本功能可以用,更详细的功能不够用,整个社区不繁荣,更新维护应用少,开发人员少导致文档和相关资料少,很难找到解决方案遇到问题时参考遇到的问题及解决方法1、开发工具卡顿:快应用开发工具运行久了会卡死。解决方法:可以退出杀掉快应用开发工具,然后重新打开。2、开发工具运行报错现象:第一次安装报错,开发过程报错,偶尔编译报错。解决方法:查看右侧预览错误信息=>查看底部错误信息输出=>onError监控=>代码二分法排查=>重启开发工具=>重启电脑注意:右侧预览有规律的明显错误会提示整个组件报错组件会渲染失败,可以通过调试器的输出来检查问题onError全局监听,使用prompt.showDialog弹出全局报错异常页面使用二分法查找半隐藏代码中的错误,发现没有异常或者$app,$def,custom$config没有报错,清空缓存重新编译,不行就重启开发工具,不行就重启电脑3.生命周期函数执行问题页面执行顺序onInit=>onReady=>onShow自定义组件只有onInit=>onReady现象:加载一次当页面返回时重新执行nters,只会执行onShow,此时不会执行页面中的自定义组件生命周期函数。解决方法:在页面onShow中添加if修改为false,100ms后修改为true强制子组件刷新。4、定位不支持z-index控制层现象:z-index无效,当多个position定位元素相互重叠时,谁晚渲染就在上层。解决方法:换成栈组件。堆叠容器的子组件层叠排列,每个直接子组件依次堆叠,覆盖前面的子组件;使用代码逻辑来控制最顶层子组件的最终渲染。5、私有自动登录api导致预览无法使用:使用oppo的私有自动登录api,模块不存在报错,导致开发者工具右侧无法预览,并且无法实时开发和调试。解决方案:封装登录方法,调试阶段引入参数控制硬编码的登录token,不要走私登录api。6、页面栈数据过多被破坏:阅读页面和详情页面每次都会生成新的页面栈,因为id不一样。如果页栈数超过5,内存中缓存的最早的页数据就会被破坏。表现就是首页会变成空白,因为最高级的就是首页。解决方法:阅读页、详情页等有id的页面,将router.push替换为router.replace;如果监控页面栈数超过5则记录,返回首页时重新加载数据。7、定时器问题现象:定时器里面的函数报错找不到这个,页面A跳转到B,后台继续监听页面A的定时器,定时器执行到最后,页面A有此时被销毁,报错。解决方法:在Function中添加一个bindPage方法,只有当bindPage中存在该页面时才执行该函数。所有定时器都使用以下方法:constbindPageLC=()=>{Function.prototype.bindPage=function(vmInst){constfn=thisreturnfunction(){if(!vmInst){thrownewError('Useerror:please传递VM对象')}if(vmInst.$valid){returnfn.apply(vmInst,arguments)}else{console.error('页面销毁时不执行回调函数')}}}}bindPageLC()setTimeout(function(){}.bindPage(this),500)8.系统字体设置改变导致的内容错位:手动修改系统字体大小,不适配导致页面错位。目前还没有相关的API来监控系统字体大小的变化。解决方案:manifest.json关闭字体大小响应“textSizeAdjust”:“none”。9、系统显示设置改变导致内容错位:手动修改系统显示大小,使用富文本容器嵌入html元素,会变大错位。"textSizeAdjust":"none"只能关闭,不响应系统字体变化。解决方法:不要使用富文本容器嵌入html,而是使用div、text等组件代替。10、适配屏快应用和负一屏卡片默认尺寸为“designWidth”:750,750的设计图可以1:1写样式;if"designWidth":1080,375的绘图需要乘以3,可以在publicstyle中定义变量,@3:3px;;具体使用:高度:156*@3;填充:16*@316*@30;。11、夜间适配现象:监听夜间模式,然后改变最外层的样式来改变颜色,但是不起作用。您需要分别更改每个元素的样式才能生效。解决方案:快应用可以适配@media(prefers-color-scheme:dark){}夜间媒体查询。manifest.json中的"themeMode":-1,跟随主题颜色,"forceDark":true,开启逆像暗夜src替换:监听主题模式切换onConfigurationChanged,获取当前主题模式配置.getThemeMode()组件单独关闭反色:forcedark="false"自定义样式:使用mediaquery适配@media(prefers-color-scheme:dark){}12.阅读页面垂直翻转模式1.0广告问题现象:多广告componentsfor循环,绑定了appear来触发加载,每个组件都会触发多次appear事件;广告组件的onLoad回调会被多次触发。解决方案:添加索引缓存,过滤掉加载的组件;将广告对象提取到外部公共引用,将数据传输到广告组件以呈现数据,并进行数据缓存过滤。13.2.0原生广告加载注意事项:最外层重新渲染加载新广告成功:返回数据不再有广告id点击:广告曝光和点击只会触发一次,再点击不会触发广告点击举报,无利润;触发广告的跳转区域不能用if控制,否则点击没有反应,关闭由show控制:自定义关闭的广告元素使用show而不是if,这样就不会跳转到adlink14.安全审计问题loglevel需要设置为off;同意隐私协议前有联网行为:所有请求均在同意协议后发送;不允许http链接:所有发给接口的链接都转成https,接口链接支持http和https,有的发的还是http;代码中不允许硬编码IP:可以拼接;storage不允许敏感信息以明文形式存储,比如昵称、手机号等:可以用cipher.aes()加密存储。开发实践几点平台版本快速应用覆盖更新,平台版本可以升级到最新版本1100ErrorhandlingJSON.parse解析错误处理constparseJSON=()=>{constrawParse=JSON.parseJSON.parse=(str,defaults)=>{try{returnrawParse(str)}catch(err){console.error(`JSONparsingfailed:${str},${err.stack}`)returndefaults}}}判断页面状态通过$valid,解决回调函数中引用this数据的错误thrownewError('useerror:PleasepasstheVMobject')}if(vmInst.$valid){returnfn.apply(vmInst,arguments)}else{console.error('当页面被销毁时,回调函数未执行')}}}}错误页面监听onPageNotFound,页面跳转异常时,跳转到自定义错误页面,添加埋点,报全局错误reportingmonitor监听onError应用错误,应用捕获到异常时调用,增加埋点上报后端服务器接口请求报告性能优化1.全局挂载公共函数global.$config挂载公共静态配置数据:$config.bpImgglobal.$utils挂载纯函数和一些系统API的封装:$utils.formatDate()app.ux挂载封装的快捷应用方法函数:this.$app.$def.login2。合理嵌套的htmlhtml层级不要超过28层,否则会发出警告;标签必须关闭,否则不会报错,但是渲染的判断逻辑不起作用,会出现奇怪的bug3.合理使用css选择器。css样式嵌套层次越深,单次匹配耗时越长。避免使用组件(如文本)名称作为最后匹配规则,否则每个文本组件在渲染时都会遍历匹配一次。左匹配,最后一个样式名尽量唯一,减少匹配次数。4.简化ViewModel数据。快应用会递归定义分配的响应数据中的每一个属性。定义的属性数量越少越好。数组类型数据,赋值时可以过滤掉不需要的对象属性5。使用延迟加载在列表组件中,不在屏幕上的list-item可以在滑动时加载更多,并完成渲染在tabs组件中,当前未显示用户点击tab时可以渲染tab的内容(使用if指令控制tab-content组件的子节点)数据传递1.父子组件传递数据父组件:props<==>子组件:$emit()触发绑定自定义事件子组件:$dispatch()触发自定义事件<==>父组件:$on()监听自定义事件,向外传递父组件:$broadcast()触发自定义事件<==>子组件:$on()监听自定义事件并向内传递2.兄弟组件传递数据写一个JS提供发布订阅功能,然后每个ViewModel导入这个JS文件或者挂载到页面级ViewModel上,子组件通过$引用页面级ViewModel父组件root<脚本>导入{createOrRetrieveInst}from'./pubsub.js'exportdefault{onReady(){//1.实例化:并将其绑定到VM.pubsubModel=createOrRetrieveInst()//2.订阅:其他VM也可以调用this.pubsubModel。subscribe('count-add',function(vArg0,vArg1){...})//3.发布:其他VM也可以调用你可以调用this.pubsubModel.publish('count-add',['arg0','arg1'])}}subcomponent3.app.ux中的跨级数据传输:onCreate(){this.dataCache={}//初始化应用缓存数据},getAppData(key){//获取应用缓存数据returnthis.dataCache[key]},setAppData(key,val){//设置应用缓存数据this.dataCache[key]=val},使用://设置任何页面this.$app.setAppData('adbooks',JSON.parse(JSON.stringify(adBook)))//获取任何页面this.$app.getAppData('adbooks')快速生成多个快应用需求:以一个快应用为主,衍生出多个换肤、换图、换问题的快应用。项目文件manifest.json,variables.less,publicconfig.js负一屏卡片开发新版负一屏卡片整体空间完全自定义,包括logo,标题,刷新频率,每触发一次当你滑到负一屏的时候,onShow卡加载了系统加载,不需要添加加载,否则两种加载会冲突,需要使用骨架屏缓存来读取中间状态。独立构建包需要在快应用中嵌入卡片,然后在管理平台创建智能服务console查看电脑安装adbbrewcaskinstallandroid-platform-toolsadblogcat-c清除日志缓存信息adblogcat-vtime>./log.log写入日志,然后在日志文件中查找信息夜间适配必须适配夜间模式不支持媒体查询@media(prefers-color-scheme:dark){}根据获取到的当前问题模式值,动态修改各个组件的样式。小小感悟完成一个快速应用项目的周期,相对于静态页面,jq、vue、react、applets、uni-app、electron和各种衍生组件库的核心还是三个东西,html页面结构,css样式,和js逻辑:html页面结构的写法、优化、注意事项都差不多,css的写法也一样(除了react的cssinjs的写法),掌握一套完整的文笔基本可以应付一般的业务。js的核心逻辑也是一样的。然后你会发现各个项目的脚手架、项目结构、使用方法都大同小异。最后,业务逻辑永远是写得最多的。在这里你可以整理一下。然后不断复用自己的一整套项目开发方法:包括项目结构、文件命名、html结构、css命名编写、js常规方法、api调用方法、文档、eslint规则等配置项等。举一个点:经常使用的消息提示弹窗元素:this.$message({message:'Thisisamessageprompt',type:'info',duration:3000,...})vant:this.$notify({message:'这是一条消息提示',type:'danger',duration:3000...})antd:message.success({content:'这是一条消息提示',duration:3,...})message.loading({content:'这是一条消息提示',duration:3,...})微信小程序:wx.showToast({title:'成功',icon:'成功',duration:1500})uni-app:uni.showToast({title:'这是一条消息提示',icon:'success',duration:1500})快应用:prompt.showToast({message:'message',duration:0})这些框架和组件库的基本用法和原理都差不多。最大的不同在于api的命名和参数的不同。记住每一个都非常费力且耗费内存。这个api可以在这里重新封装,比如统一到$utils.showToast()中,这样就可以一直记住这个了。可以封装的功能包括:各种反馈弹窗、登录注销、支付、缓存存储、内嵌功能、各框架提供的系统调用方法等,将常用的重新封装起来复用,可以进一步消除差异并减轻记忆负担。我的分享到此结束,感谢阅读,谢谢~
