Compose跨平台第二弹:体验Compose for Web
Posted datian1234
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Compose跨平台第二弹:体验Compose for Web相关的知识,希望对你有一定的参考价值。
前言
在Compose跨平台第一弹:体验Compose for Desktop 中,我们已经了解了Compose-jb以及如何使用Compose-jb开发简单的桌面端应用,第二弹,我们就来了解下如何使用Compose-jb开发Web应用。相信看完这一弹之后你会对Compose-jb有新的了解。
环境要求
与Compose For Desktop的环境要求一致。
开发流程
创建项目
同样的,我们打开IDEA创建Compose Multiplatform项目,选择Single plaform,不过这里我们选择Platform为Web平台,如下图所示。
创建好项目后,来看项目目录结构,如下图所示。
可以看到同样的在配置文件中指定了平台配置,这一点是比较重要的,便于以后我们在原有项目基础上添加配置。并且以后我们会发现,这个配置也不一定在根目录中的build文件中,所以我们需要知道配置的含义,这一点目前规划在后续的弹中会单独分享。
项目结构
在jsMain文件夹下Main文件通过renderComposable的rootElementId属性与index.html中的div标签绑定,从而将页面在web中显示。index.html代码截图如下所示。
Main.kt代码截图如下所示。
当我看到这段代码之后,我心里是慌的,Div?style?attrs?这都是什么玩意啊,学了Compose的我都不知道,这也能叫跨平台?
这是Compose for Web专门提供的一套DOM API,Div组件也是为Web实现的对应Composeable组件,通过attrs方法设置标签属性。所以这些代码,都是无法直接在android或Desktop平台上复用的。所以,从这一点来讲使用Compose实现跨平台,目前存在严重的割裂问题,和Flutter相比还是有一定的差距。
运行程序(./gradlew jsBrowserRun),页面如下图所示。
这是项目默认实现的一个加减计数器的功能。接下来我们来添加自己的组件。
添加输入框
和开发Desktop一样,我们先来添加一个输入框,在Compose for Web中输入框采用Input组件
,代码如下所示:
renderComposable(rootElementId = "root")
Div
P
Input(type = InputType.Text)
P
Input(type = InputType.Password)
P
Button(attrs =
onClick
)
Text("Login")
通过type属性指定输入框的类别分别为文字和密码,运行程序,结果如下图所示。
接着我们通过添加Text标签为输入框添加属性说明,修改部分的代码如下所示:
P
Text("用户名")
Input(type = InputType.Text)
P
Text("密码")
Input(type = InputType.Password)
再次运行程序,结果如下图所示。
嗯,挺丑的。上述代码我们在最外层使用Div包裹是为了便于为这块区域设置一些属性,比如我们设置背景色为蓝色,代码如下所示。
Div(style
backgroundColor(Color.blue)
)
...
运行程序,结果如下所示。
好吧,更丑了… , Compose for Web 允许开发者基于 DSL 定义 Style 样式,但是到目前为止我的感觉是写的很累,感觉如果不会Web就无法写好Compose for Web,这叫哪门子的跨平台?
添加超链接
超链接直接使用A标签即可,比如这里我们添加一个用户隐私协议,代码如下所示。
P
A("https://www.baidu.com/")
Text("用户协议")
运行程序,结果如下图所示。
如果想用Compose写好Web,我觉得最主要的是Style DSL,但是在这里我们没办法一一展示。需要我们在项目中去实战。接下来,我们来实现与Desktop一样的查询数据功能。
实现查询数据功能
本来打算仍然借用「wanandroid」中「每日一问」接口的,但是这个接口存在跨域问题,导致无法请求,所以我们这里将接口返回的json数据,定义为Api文件中的data变量,Ktor的使用方式是一样的,所以并不影响实际结果。
定义HttpUtil类并实现getData方法,代码如下所示。
class HttpUtil
/**
* 获取数据
*/
suspend fun getData(): DemoReqData
val rockets = Json.decodeFromString<DemoReqData>(string = Api.data)
return rockets
在Desktop中我们可以直接在Main 文件中直接调用取数据的方法,但是这里不行,因为renderComposable下无法启动协程。所以这里我们定义一个DataSource类继承自CoroutineScope,同样定义一个loadData方法,代码如下所示。
class DataSource : CoroutineScope
private var job = Job()
override val coroutineContext: CoroutineContext
get() = job
private val _stateFlow = MutableStateFlow(DemoReqData())
var stateFlow = _stateFlow.asStateFlow()
fun loadData()
launch
_stateFlow.value = HttpUtil().getData()
这样我们可以在loadData方法中启动协程并调用HttpUtil中的getData方法,然后赋值给stateFlow,这一点得益于Flow 是 kotlinx 包下的组件,与平台无关。
最后,我们在Main中定义一个按钮,点击“请求数据”,然后将数据显示出来,代码如下所示。
renderComposable(rootElementId = "root")
val dataSource = DataSource()
val data = dataSource.stateFlow.collectAsState()
Button(attrs =
onClick
dataSource.loadData()
)
Text("请求数据")
Div
repeat(data.value.data?.datas?.size ?: 0)
Div
P
Text("作者:" + data.value.data?.datas?.get(it)?.author)
P
Text("标题:" + data.value.data?.datas?.get(it)?.title)
P(
style
height(1.px)
backgroundColor(Color.red)
)
这里将作者信息与标题显示出来,为了效果明显添加了一个红色的横线,运行程序,点击“请求数据”,结果如下图所示。
这样我们就使用Compose实现了一个Web端简单的查询数据功能。
写在最后
Compose For Web 中提供了更贴近 HTML 风格的 Composable API,所以UI代码无法与Android或Desktop的UI代码直接复用。但是逻辑层的代码都是可以共用的,目前Google也在推进解决这样的“割裂”问题,从目前来看,Compose跨平台还有一定的路要走,我们将在后续的第N弹中持续探索…
作者:黄林晴
链接:https://juejin.cn/post/7187306464875118651
文末福利
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。
全套视频资料:
一、面试合集
二、源码解析合集
三、开源框架合集
欢迎大家一键三连支持,若需要文中资料,直接点击文末CSDN官方认证微信卡片免费领取↓↓↓
以上是关于Compose跨平台第二弹:体验Compose for Web的主要内容,如果未能解决你的问题,请参考以下文章
小白学数据神经网络第二弹:Google可视化体验平台Tensorflow Playground
使用 Jetpack Compose 提升 Play 商店的用户体验
欢迎体验 | Wear OS 版 Compose 开发者预览版