如果你是前端开发人员,对Flutter感到好奇,想了解一下?
如果使用过React Native, 那么同为跨平台框架,flutter上手究竟有多难?
然后我尝试了一下……令我惊讶的是,我能够立即编写出高效的代码。以下内容将比较 Dart / Flutter 和 JS / ReactNative。
前端使用 Ts , flutter 使用 dart 语言。
对于Js开发人员,程序并没有特定的一个入口。
dart则指定了**方法main()**作为程序启始入口
index.ts
export const app = () => { // init app }; app();main.dart
main() { // 程序内容 }index.ts
// Reassignable variables let person: string; person = 'jeff'; person = 'bob'; // Single assignment variables const lucky: number = 23; // Implicit const implicit = { name: 'Jeff' }; // Any const whoKnows: any = getSomethingDynamic();main.dart
// Reassignable variables String person; person = 'Jeff'; person = 'Bob'; // Single Assignment final int lucky = 23; // Single Assignment & Immutable const Map person = 'Jeff'; // Implicit var implicit = { 'name': 'Jeff' }; // Map<String, String> // Any type dynamic whoKnows = getSomethingDynamic();在Js中,有几种导入/导出值的方法,所以让我们看一下现代的ES6方法。
global.ts
export default const = 'JS'; // or export const lang = 'JS';index.ts
import lang from 'globals'; // or import { lang } from 'globals';在dart中, 一旦引入文件,那么有权访问声明该文件的所有内容。这个避免了Js中大量的import xxx😠 global.dart
final String lang = 'Dart!';main.dart
import 'globals.dart'; main() { print(lang) }index.ts
console.log('howdy!');main.dart
print('howdy!');在Js中一个键值对就是map,而在dart中专门定义了Map这个类型指代键值对。
index.ts
const state = { lucky: 23 } state['unlucky'] = 11; const state = new Map([['lucky', 23]]); state.set('unlucky', 11);main.dart
Map state = { 'lucky': 23 }; state['unlucky'] = 11;index.ts
const things: number[] = [1, 2, 3]main.dart
List<int> things = [1, 2, 3]; things.forEach() things.reduce() things.last;Js开发人员应该对Dart中的函数感到非常熟悉:它支持命名,匿名,箭头和高阶函数。 主要区别在于dart不需要function关键字。
index.ts
function addOne(val: number) { return val + 1; } // Higher Order function callme(cb: Function) { return cb('Hello?'); } callme((v) => console.log(v));main.dart
addOne(int val) { return val + 1; } // Higher Order callme(Function cb) { return cb('Hello?'); } callme((v) => print(v));在Dart中会频繁地使用Class,它们非常强大。该语言支持基于mixin(混合)的继承,该继承可通过composition提供出色的代码重用。在Js中,类只是功能和原型继承的语法糖。
index.ts
export const main = () => { const myComponent = new Component() } class Component { }main.dart
main() { var myWidget = Widget(); } class Widget { }index.ts
export const main = () => { const bar = new Component(1,2); } class Component { constructor(private a, public b) { // non-ts version // this.a = a // this.b = b } }main.dart
main() { Widget foo = Widget.withStrings('1', '2'); } class Widget { // Default Constructor Widget(_a, b); // Named Constructor Widget.withStrings(_a, b); }异步内容,Dart Future 与 Js Promise几乎一模一样,非常好理解。其中dart中地关键字 async位置不一样。
index.ts
async function howdy() { return 'partner 🤠'; } async function greet() { await howdy(); } greet().then(console.log).catch()main.dart
Future howdy() async { return 'partner 🤠'; } greet() async { await howdy(); } greet().then(print).catchError();JavaScript中还没有流式数据结构,但它们通过第三方库,比如RxJS,Mobx,和其他库共同提供。
流类似于Promise(Future),区别在于A Stream就像一个Future事件发射中心,随着时间的推移会发出多个值,我们甚至可以将其与async / await use一起使用。
main.dart
main() async { var items = Stream.fromIterable([1,2,3]); await for (int i in items) { // do something } // Or setup a listener items.listen(print); }Flutter受到JavaScript框架(例如React / Angular / Vue)的启发,该框架使小组件组件能够在数据更改时以响应式更新UI,也就是数据驱动UI。实际上,Flutter提供了setState一种与ReactJS中完全一样的方法。
在flutter中,任何模块都称之为部件 widget 在Js中,任何模块都称之为组件 compoent
index.ts
import React from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default class MyApp extends React.Component { render() { return ( <View> <Text>Hello world!</Text> </View> ); } }main.dart
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override build(context) { return Center( child: Text('Hello World'), ); } }从react native文档重新创建这个样式化的组件。注意,左侧的Flutter版本具有大约65%的代码占用空间,并保证了类型安全。另请参见本要点中的其他示例。
Flutter提供了几种管理组件状态的方法。你可以setState像React一样使用,但是还有一些其他内置技术。
我个人最喜欢的是将状态数据表示为a Stream或Rx Observable,然后使用StreamBuilder小部件有条件地绘制UI。如你所见,这不需要任何显式调用即可呈现UI,而是基于流中发出的最新值。代码占用空间略有改善,但是如果你发现自己频繁设置状态,则可以真正实现这一点。