指南介绍
-
如果你是前端开发人员,对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() {
// 程序内容
}
变量
- typescript中第一个文件通常叫做index.ts,而在dart中第一个文件名通常叫做main.dart
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();
import/export 导入导出
在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)
}
打印 logging
index.ts
console.log('howdy!');
main.dart
print('howdy!');
Map(键值对) 和 Object
在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;
List and Array 列表 和数组
- 在Js中,一个有序队列叫做 array(数组)。
- 在dart中,一个有序队列叫做List(列表)
index.ts
const things: number[] = [1, 2, 3]
main.dart
List<int> things = [1, 2, 3];
things.forEach()
things.reduce()
things.last;
Function 方法
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));
Class 类
在Dart中会频繁地使用Class,它们非常强大。该语言支持基于mixin(混合)的继承,该继承可通过composition提供出色的代码重用。在Js中,类只是功能和原型继承的语法糖。
index.ts
export const main = () => {
const myComponent = new Component()
}
class Component { }
main.dart
main() {
var myWidget = Widget();
}
class Widget { }
constructor 类构造器
- 在Js中使用class,通常会new一个对象。
- 在Dart中,你可以像调用函数一样通过调用其名称来构造一个类,。直接调用,不用new。另外,你可以使用命名构造函数以不同的逻辑实例化相同的对象。
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);
}
Async Programming 异步编程
异步内容,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();
Streams and Observables 流和观察者
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框架
Flutter受到JavaScript框架(例如React / Angular / Vue)的启发,该框架使小组件组件能够在数据更改时以响应式更新UI,也就是数据驱动UI。实际上,Flutter提供了setState一种与ReactJS中完全一样的方法。
包管理
- pubspec.yaml👉package.json
- Pub 👉 NPM
- Js中管理所有地库文件使用: package.json
- dart中管理所有地库文件使用: pubspec.yaml
widget | component
在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比较
从react native文档重新创建这个样式化的组件。注意,左侧的Flutter版本具有大约65%的代码占用空间,并保证了类型安全。另请参见本要点中的其他示例。
Flutter提供了几种管理组件状态的方法。你可以setState像React一样使用,但是还有一些其他内置技术。
我个人最喜欢的是将状态数据表示为a Stream或Rx Observable,然后使用StreamBuilder小部件有条件地绘制UI。如你所见,这不需要任何显式调用即可呈现UI,而是基于流中发出的最新值。代码占用空间略有改善,但是如果你发现自己频繁设置状态,则可以真正实现这一点。