React Native 使用报告
最近邀请我参加一个七牛云的校园编程竞赛,我觉得自己能学到些什么,所以就半同意下来了。
昨天晚上三个人简要谈了谈之后,说是要决定一下选什么框架好,目前就两个方向——React Native
和 Flutter
,前者是我只听说过但没实际了解的东西,后者则是自去年 11
月份就在学的东西。
于是昨天配置好 RN
的基础环境后,今天就看教程去了,但是嘛,越看就越觉得 RN
不好用,我来具体分析一下。
语言不行
首先,RN
使用 JS/TS
语言来编写程序,而前者 JS
是我认为最令人难受的语言(PHP
好像也挺垃圾的),它的变量类型可以说是一塌糊涂,动态类型 Python
也有,但 Python
我就用来写点小东西,要我用它开发程序……我也不是没写过,WordCloud
就是用 Python
写的,体验也是非常糟糕。除此之外我还非常讨厌它有 ==
和 ===
的区别,隐式转换是坏文明。
后者 TS
我就直白的说,我看不懂!Python
里加入类型检查的方法是在变量后面冒号然后一个类型,而且重要的是,即便没给全部的变量都加上类型,程序仍然能跑起来,相当于只是给个 lint
提示一下,但 TS
要写类型就得全部写完,类型还不直观,之前学 React
的时候想转 TS
都转不了,后面对 React
就没多大兴趣了。
再来聊聊 Flutter
使用的语言 Dart
,这是我用的最喜欢的一门语言。
首先,他非常像 Java
,而我曾经写过一段时间的 Java
程序,所以很快就上手了。而且相比 Java
,它有空安全检查,也就是一个变量只有在其类型后面接上个问号时才能赋值为 null
。相比之下,Java
就没有这样的要求,就容易抛出空指针错误。它的语法比 Java
简约,new
关键字不再是必要的。它还有动态类型,所以动态类型的好处 Dart
也有。
其次,我非常喜欢它的 extension
方法,可以在已有的一个类(如 DateTime
)里,注入自己需要的一些便捷方法,这是非常好的,pub.dev
上还有一个包专门收录了许多的 extension
,极大方便了开发。
框架不行
包管理
React
和 React Native
都会搞出一个极大的 node_modules
文件夹,这是非常屎的一个设计,我就不多吐槽了,npm
、yarn
、pnpm
都是为了解决这个烂玩意的,见 此博客 。
而 RN
一个令我难受的点是,其 core
核心组件太少了,像是 Navigation
导航都要引入一个包,听说之前它是在 core
里的,之后被分离出去了……嗯……
再来聊聊 Flutter
的包管理,它没有什么外置的包管理器,要么一句 flutter pub add <包名>
解决,要么自己在 pubspec.yaml
文件里添加一行 <包名>: <版本号>
就行,甚至版本号都不填,留个冒号在那里,Flutter
自己会获取最新且兼容的包,一手包办的感觉太爽了。
那 Flutter
的包是放在哪的呢?在 %LOCALAPPDATA%\Pub\Cache\hosted
下,它按源的不同,分多个文件夹,一般来说是 pub.dev
文件夹和 pub.flutter-io.cn
文件夹,进 pub.dev
文件夹能看到很多包的不同版本的文件夹,就统计下来连 2 GB
都没有。
高下立判。
组件设计
React
和 RN
的类组件和 Flutter
的组件非常相似,但没有明显区分自己管理状态和无状态的组件,换言之,都是继承自 Component
,都有一个 state
,只是看你用不用就是了。
相似的点在于,前者的 constructor
相当于后者的 initState
,前者的 render
相当于后者的 build
,生命周期非常相似。
Flutter
是分了 StatelessWidget
和 StatefulWidget
的,前者只会要重写一个 build
方法,后者则是可重写整个生命周期。
组件的修改
这是我很不喜欢的一点,所有的,对于一个组件的修改,都要在一个远离组件的一个键值对里配置,这非常割裂。
其实我在学 HTML
和 CSS
的时候就有这样的感觉,样式为什么要放到另一个文件里?紧靠着不是更方便吗?没办法,网页这样搞是历史原因,React
也是搞网页的所以能理解,但 RN
的话……当我知道它不是在各平台的 WebView
里跑 React
时我就不理解了。
而且写的配置,对 key
是没有 lint
提示的,我鼠标移到上面,它不会提示我这个组件有哪些可以修改的属性,加重了记忆负担。value
更是离谱,绝大多数都是字符串,都是同一个类型,要是打错了怎么办,要是没有代码补全怎么办?
相比之下,Flutter
的组件的配置要更加舒服,在其构造函数里填入配置的属性即可,而且 lint
会显示构造函数的参数和参数类型,还有 dartDoc
显示示例。除此之外,全局的主题配置也是可以的,像是 MaterialApp
就有 theme
属性,给其子组件树应用上。
组件在多平台下的表现
RN
说是一套代码跑多个平台,但我觉得它的表现不尽人意,多平台的表现差距太大。就拿圆形加载器组件举例,大小属性值怎么可以只在安卓有效?
这是受到原生组件的限制导致的,iOS
没有大小属性值……
而 Flutter
,实际上也有多平台适配,部分已多平台适配的组件如 AlertDialog
是有个 adaptive
方法的,而且不会有“受原生组件限制”这一说法。
Navigation 导航
我人都麻了,不知道是不是我会错意了,所有进入路由的组件都要受改造,还要在 Navigation
根组件里登记命名路由?
Flutter
哪来那么多事,在 MaterialApp
的 home
属性填初始路由(也就是 "/"
的命名路由),再用 Navigator.push
方法压入未命名的路由,或者和 RN
类似地在 MaterialApp
填命名路由,然后用 Navigator.pushNamed
方法压入命名路由。
灵活性比 RN
强太多了。
我了解不够
这里是我自己的一些问题,以上都是刚接触一天所体验到的,可能了解上面的一些问题也早都有了解决方案。