【作者:芝兮】
背景Rax是什么Rax 是阿里巴巴应用最广泛的跨端解决方案,支持开发者通过类 React DSL 编写 Web、小程序、Flutter 等不同容器的跨端应用。
官方网站:rax.js.org/
Rax使用背景实际业务中为了跨端,采用了Rax框架来进行开发,从而适配小程序和H5,过程中遇到了各种各样的业务场景和技术问题。以下内容是经验总结和趟坑指导指南,欢迎交流。
一、语法篇1.如果使用 x-if、x-elseif 不生效记得检查下,不要在x-elseif前面添加注释,不然指令会被忽略。
// 错误事例<View x-if></View>{/** 第二个 **/}<View x-elseif></View>//正确用法<View x-if></View><View x-elseif></View>2.文件中不能export多个对象比如以下用法无法成功执行,如果使用了支付宝小程序IDE,则会直接白屏:
export { Component1, Component2, Component3 }import { Component1 } from '../..'3. jsx文件错误在小程序开发者工具中有些不会打印经常有同学会反馈类似的问题:为啥我写完后页面老是白屏,是哪里不对? 举个栗子:组件忘记import,小程序开发者工具的控制台不会报错,只会直接白屏。 解决方案:H5调试的时候控制台有错误日志,但是小程序开发者工具中并没有。所以如果写的是跨端的代码,倾向使用H5来进行调试或者靠火眼金睛来找bug。
二、组件篇1.Text组件不能包子组件以下写法不支持,因为Text组件不能再包子组件。
<Text>aaaa<Text>bbbb</Text>cccc</Text>2.Calendar组件不展示默认时间目前的Calendar组件有value(设置的值)但是打开日历的时候,没有默认展示当前value日期。
解决方案:已经给Calendar组件那边提了MR,并且已经上线。
三、生命周期篇1.usePageShow无法获取当前state中的最新数据usePageShow回调函数中无法获取当前state中的最新数据。根本原因是因为闭包。
具体可以查看以下文章来了解闭包的问题:《使用 JS 及 React Hook 时需要注意过时闭包的坑》
解决方案建议:usePageShow的回调函数中确实要获取最新的数据,就建议不要把数据存在state中,可以考虑存在全局或者有自己的store设计也可以。如果需要在usePageShow的回调函数中修改数据触发页面更新,则除了全局还需要维持一份数据到state来触发render。
2.原生中setData的回调函数如何处理(如何保证页面已经渲染完成)原生支付宝小程序中有一些写法是在setData的回调函数中处理了一些逻辑,此时说明这些逻辑是需要在页面渲染更新完成之后执行的。
this.setData( { hasLoadPlugin: true, }, () => { this.showSubscribe(subscribeMessage) },)支付宝小程序setData文档
在Rax中使用useState来更新数据,这样的话无法保证页面渲染完成,此时需要使用setDataFinished的事件来处理。举个例子:
import { createElement, useEffect } from 'rax';import View from 'rax-view';import { getBoundingClientRect } from '@uni/element';function logBoundingClientRect() { console.log('=============') getBoundingClientRect('#container').then((ret) => { const { width, height, top, left, right, bottom } = ret[0]; console.log(width, height, top, left, right, bottom); });}export default () => { useEffect(() => { window.addEventListener('setDataFinished', logBoundingClientRect); return () => { window.removeEventListener('setDataFinished', logBoundingClientRect); } }, []); return ( <View id="container"> <View>1</View> <View>2</View> </View> )}使用这种方式要注意如果页面中触发渲染次数很多或者存在轮询/轮播的内容,则setDataFinished监听后的处理方法也会不断的被调用: 例如某个页面加了倒计时功能,加上上面的组件会发现,因为时间是轮询变化的,那也就意味着每一次变化都会触发setDataFinished事件,所以通过log发现一直会执行logBoundingClientRect方法。
建议:
要进行removeEventListener方法内通过变量判断,如果已经执行过了,不要再次执行。参考《在页面渲染后获取小程序原生节点信息或 context 失败,应该怎么处理?》
3.支付宝小程序声明周期和全局变量支付宝小程序声明周期和全局变量,在不分包的情况下,可以直接写在根目录src下的 app.js 里,但是很多项目中是分包的,直接写在根目录的app.js里不生效,需要写在主包目录下的app.js里,全局变量声明要加一下环境判断,如下代码所示:
import { runApp } from 'rax-app'import staticConfig from './app.json'import { isMiniApp } from '@uni/env';const appConfig = { app: { // 小程序应用生命周期 onLaunch(options) { if (isMiniApp) { this.test = false } }, onShow() { console.log('app onShow') }, onHide() { console.log('app onHide') }, },}runApp(appConfig, staticConfig)四、框架API相关1. getSearchParams获取路由参数(特殊字符)不对根据官方文档说的,getSearchParams
仅支持 SPA 和小程序,不支持 MPA 应用
用于解析 url 参数。假设当前 URL 为example.com?foo=bar解析查询参数如下:
// src/components/Exampleimport { getSearchParams } from 'rax-app';function Example() { const searchParams = getSearchParams() // console.log(searchParams); => { foo: 'bar' }}当参数foo的值包含特殊字符时(例如foo=bar&test),很容易想到要做encodeURIComponent处理,但是实践中发现,encodeURIComponent一次,getSearchParams得到的结果还是错误的(即foo=bar),只有encodeURIComponent2次getSearchParams得到的才是正确的结果(foo=bar&test)。
五、功能篇1. 宽高获取在原生支付宝小程序中经常可以看到通过createSelectorQuery查询DOM来获取宽高。
// 获取高度,回传自适应图区域async getDemoHeight() { return new Promise((resolve) => { my.createSelectorQuery() .select('.component-demo') .boundingClientRect() .exec((res) => { resolve(res[0] && res[0].height) }) })},在Rax中可以使用getBoundingClientRectAPI获取
import { createElement, useEffect } from 'rax';import View from 'rax-view';import { getBoundingClientRect } from '@uni/element';function logBoundingClientRect() { getBoundingClientRect('#container').then((ret) => { const { width, height, top, left, right, bottom } = ret[0]; console.log(width, height, top, left, right, bottom); });}export default () => { useEffect(() => { window.addEventListener('setDataFinished', logBoundingClientRect); return () => { window.removeEventListener('setDataFinished', logBoundingClientRect); } }, []); return ( <View id="container"> <View>1</View> <View>2</View> </View> )}使用getBoundingClientRect时要注意,前面提到过,需要通过监听setDataFinished才能保证页面渲染完成后获取到DOM。
六、插件使用1. 静态插件使用根据文档可以调用静态插件
插件配置
在src/app.json配置plugins参数,和支付宝、微信原生的插件配置保持一致,例如
"plugins": { "subscribeMsg": { "version": "*", "provider": "XXXXX" } },插件组件使用
使用插件的组件时,直接使用import语法,例如
import SubscribeMsgPlugin from 'plugin://subscribeMsg/subscribe-msg'然后在 JSX 中正常使用SubscribeMsgPlugin标签即可
<SubscribeMsgPlugin />插件 JS API 使用
使用插件 js 接口,无限制,使用requirePlugin然后调用即可,和阿里、微信小程序官方使用方式保持一致
if (requirePlugin) { const subscribeMsg = requirePlugin('subscribeMsg') || {} requestSubscribeMessage = subscribeMsg.requestSubscribeMessage }多端开发注意
当开发多端时 import SubscribeMsgPlugin from 'plugin://subscribeMsg/subscribe-msg' 只能在支付宝小程序正常运行,而在微信端或者Web端都会出错,这个时候可以通过文件后缀来区分不同端的加载。参考: 《不同小程序端代码如何处理?》
2. Rax不支持动态加载插件找了Rax相应的同学了解到目前Rax不支持动态加载插件,但是因为Rax可以支持使用原生,所有有了另外一种可能。在公共util中封装loadPlugin API,只有在支付宝小程序中才能使用。这种方案只能保证JS API loadPlugin是可以调用的,但是<component is=XXX />不支持,所以动态加载插件如果涉及到页面使用component渲染插件的话,是无法使用RAX的。 解决方案:如果动态加载的插件是一整个页面,不涉及<component is=XXX />可以直接用loadPlugin。如果涉及了,不能使用rax来实现(例如SubscribeMsg)
《支付宝小程序插件说明》
七、功能无法跨端场景下,Rax中使用原生类似于之前的动态加载插件功能,都只在原生支付宝小程序上生效,所以经常能够想到的解决方案就是在Rax中调用原生的组件。
1.使用原生方式配置安装 Rax 项目中的原生小程序自定义组件及原生页面所用到的 npm 依赖(nativePackage)原生自定义组件搬运直接将小程序原生组件代码拷贝至src/miniapp-native目录下,并按具体路径引用组件即可使用:
import SubscribeMsg from '../../miniapp-native/subscribe-msg/index'(注:请勿使用 alias 路径)
使用的地方加上环境判断:
{env.isMiniApp && <SubscribeMsg entityIds={entityIds} />}通过以上的方式,可以发现在支付宝小程序中,确实成功使用了原生小程序组件(动态引入了插件)
但是因为使用Rax是为了多端,此时会发现H5端编译报错(component is not defined),页面白屏,经过排查发现Rax编译H5时不是根据env.isMiniApp判断是否显示组件来动态加载的。所以在使用原生时要考虑解决多端差异化问题。 因为import 组件的操作必须在文件开头执行,无法加入逻辑判断动态引入,可按照后缀名加载对应端的文件来进行分端构建。在之前《多端开发注意》章节提到过。
八、样式篇1. flex 布局Rax View有自己的内置样式,默认flex布局,但是会发现这个默认flex-direction: column;这跟之前小程序中默认的row是不一样的,所以需要手动复写样式,需要的地方改成row。
尾言以上是Rax开发的经验总结文档,希望对使用Rax框架开发的同学能带来一些收获,与君共勉之。
本文发布于:2022-09-11 01:02:28,感谢您对本站的认可!
本文链接:https://www.bsyshop.com/ask/xinxi/82/354887.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |