我们以问答形式继续对
Flutter官方文档进行简洁的解释。 这是第三部分,它将对React Native开发人员更加有用。 通过这种解释,您可以找到常见问题的答案,并自己确定要从一个跨平台框架切换到另一个框架需要付出多少努力。

如果这些信息还不够,或者您有特定平台的本机开发经验,那么我建议您查看其他部分:
扑 第1部分。对于Android开发人员扑 第2部分。对于iOS开发人员扑 第3部分。对于React本机开发人员扑 第4部分。对于Web开发人员
扑 第5部分。对于Xamarin.Forms开发人员
内容:
- 关于Dart的一点
- 基础知识
- 项目结构与资源
- 观看次数
- 版面
- 程式化
- 国家管理
- 本地存储
- 导览
- 手势和触摸事件处理
- HTTP请求
- 输入形式
- 平台特定的代码
- 侦错
- 动画制作
- 等效组件
- Flutter插件
关于Dart的一点
问题:
入口在哪里?
答案是:
函数
main()
。
差异:
JavaScript没有预定义的入口点;它可以是开发人员定义的任何函数。 在Dart中,这仅是
main()
。
问题:
如何输出到控制台?
答案是:
使用
print()
函数。
差异:
在JavaScript中,使用
console.log()
完成控制台输出。
一个例子:
print('Hello world!');
问题:
如何创建和分配变量/字段?
答案是:
Dart支持动态键入和强类型键入。 因此,可以使用任何方便您键入的类型来创建变量/字段。 分配通过单个=进行。
差异:
JavaScript不支持强类型。
附加信息:
此处有更多详细信息。一个例子:
String name = 'dart';
问题:
变量/字段的默认值是多少?
答案是:
null
差异:
默认情况下
undefined
JavaScript。
附加信息:
此处有更多详细信息。问题:
如何检查
null
或0的值?
答案是:
使用显式验证
==
。
差异:
在JavaScript中,作为
if
检查的一部分,数字1或任何
non-null
对象将等同于
true
。 在Dart中,只有布尔值
true
等效于
true
。
一个例子:
var myNull = null; if (myNull == null) { print('use "== null" to check null'); } var zero = 0; if (zero == 0) { print('use "== 0" to check zero'); }
问题:
如何声明函数?
答案是:
在Dart中,函数(如字段)可以带有动态或强类型的返回值。 动态类型简单地由函数名称声明,也可以由参数声明,而强类型的开头仍然具有返回类型。
差异:
在JavaScript中,使用关键字
function
声明
function
,后跟名称和可选参数。
附加信息:
此处有更多详细信息。一个例子:
fn() { return true; }
问题:
什么是
Promise ?
答案是:
未来的附加信息:
Dart和JavaScript一样,都支持单线程执行。 Dart中的
Future与React Native中的
Promise具有相同的含义。
此处有更多详细信息。 。
一个例子:
import 'dart:convert'; import 'package:http/http.dart' as http; class Example { Future<String> _getIPAddress() { final url = 'https://httpbin.org/ip'; return http.get(url).then((response) { String ip = jsonDecode(response.body)['origin']; return ip; }); } } main() { final example = new Example(); example ._getIPAddress() .then((ip) => print(ip)) .catchError((error) => print(error)); }
问题:
async
和
await
什么?
答案是:
async
await
差异:
在JavaScript中,异步函数返回
Promise ,在Dart中,它们返回
Future 。 同步等待await调用异步函数的结果。
附加信息:
此处有更多详细信息。一个例子:
import 'dart:convert'; import 'package:http/http.dart' as http; class Example { Future<String> _getIPAddress() async { final url = 'https://httpbin.org/ip'; final response = await http.get(url); String ip = jsonDecode(response.body)['origin']; return ip; } } main() async { final example = new Example(); try { final ip = await example._getIPAddress(); print(ip); } catch (error) { print(error); } }
基础知识
问题:
如何在Flutter上创建应用程序项目?
答案是:
- 将IDE与已安装的Flutter和Dart插件一起使用。
- 使用
flutter create {projectname}
。
差异:
要在React Native中创建项目,请使用
create-react-native-app {projectname}
。
附加信息:
此处有更多详细信息。问题:
如何启动应用程序?
答案是:
- 在安装了Flutter和Dart插件的IDE中使用运行功能。
- 使用
flutter run
命令。
差异:
React Native使用
npm run
或
yarn run
命令启动应用程序。
问题:
如何导入小部件?
答案是:
在Flutter中,所有小部件都被分解为包,因此导入包就足以使用其小部件。
差异:
在React Native中,您需要导入每个小部件。
一个例子:
import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/my_widgets.dart';
问题:
如何使用小部件和嵌套来构建小部件树?
答案是:
在Flutter中,几乎所有东西都是小部件。 甚至应用程序对象也是小部件。 每个小部件都可以嵌套在父级中。 通过组合小部件,可以构建称为小部件树的层次结构。 后来她变成屏幕上的显示的是她。
一个例子:
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Welcome to Flutter', home: Scaffold( appBar: AppBar( title: Text('Welcome to Flutter'), ), body: Center( child: Text('Hello world'), ), ), ); } }
问题:
如何创建可重用组件?
答案是:
在Flutter中,您可以创建一个小部件类并重用它。 使用的参数是类字段。
差异:
在React Native中,要更改重用元素的参数,您需要将其标记为prop。
附加信息:
构造函数中的参数可以通过两种方式声明:通过常规枚举和可选(使用花括号
{}
。 使用参数调用构造函数时会发生差异。
在通常的枚举中,所有参数都是必需的,并且在调用构造函数时,您无法指定传递哪个特定参数,因为 他们是由于订单。
使用可选参数时,您可以按任何顺序传输参数,但是必须指定要传输或不传输特定参数。 要根据需要标记可选参数,请使用
@required
批注。
一个例子:
class CustomCard extends StatelessWidget { CustomCard({@required this.index, @required this.onPress}); final index; final Function onPress; @override Widget build(BuildContext context) { return Card( child: Column( children: <Widget>[ Text('Card $index'), FlatButton( child: const Text('Press'), onPressed: this.onPress, ), ], ) ); } } ...
项目结构与资源
问题:
从哪里开始编写代码?
答案是:
在
{projectname}/lib/main.dart
。
问题:
Flutter项目中的文件结构是什么?
答案是:
┬ └ projectname ┬ ├ android - Android . ├ build - iOS Android . ├ ios - iOS . ├ lib - Dart . ┬ └ src - Contains additional source files. └ main.dart - . ├ test - . └ pubspec.yaml - . package.json React Native.
问题:
在哪里存储资源和资产以及如何使用它们?
答案是:
资源和项目依赖项的链接存储在
pubspec.yaml
文件中。 实际上,您可以将它们放置在
lib
内的任何文件夹中,最重要的是,可以在
pubspec.yaml
指定它们的路径。 您可以在项目中使用专用的小部件(例如
AssetImage )或直接使用
AssetBundle来使用
它们 。
附加信息:
此处有更多详细信息。一个例子:
在
pubspec.yaml
声明资产
flutter: assets: - assets/my_icon.png - assets/background.png
在代码中使用
image: AssetImage('assets/background.png'),
问题:
如何从网络下载图像?
答案是:
使用
Image.network 。
一个例子:
body: Image.network( 'https://flutter.io/images/owl.jpg',
问题:
如何连接第三方软件包和插件?
答案是:
在
pubspec.yaml
使用
dependencies
pubspec.yaml
。
差异:
React Native使用
yarn add {package-name}
或
npm install --save {package-name}
命令添加依赖项。
附加信息:
使用包软件包和插件开发Flutter的流行插件一个例子:
dependencies: flutter: sdk: flutter google_sign_in: ^3.0.3
观看次数
问题:
什么相当于
View容器?
答案是:
用于布局的所有基本小部件,例如
Container ,
Column ,
Row和
Center 。
附加信息:
此处有更多详细信息。问题:
FlatList或
SelectionList的类似物是什么?
答案是:
列表视图一个例子:
var data = [ ... ]; ListView.builder( itemCount: data.length, itemBuilder: (context, int index) { return Text( data[index], ); }, )
问题:
如何使用画布?
答案是:
使用
CustomPaint和
CustomPainter类 。
差异:
在React Native中,无法直接使用Canvas进行绘制。 有第三方插件,例如
react-native-canvas
。
一个例子:
class MyCanvasPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { Paint paint = Paint(); paint.color = Colors.amber; canvas.drawCircle(Offset(100.0, 200.0), 40.0, paint); Paint paintRect = Paint(); paintRect.color = Colors.lightBlue; Rect rect = Rect.fromPoints(Offset(150.0, 300.0), Offset(300.0, 400.0)); canvas.drawRect(rect, paintRect); } bool shouldRepaint(MyCanvasPainter oldDelegate) => false; bool shouldRebuildSemantics(MyCanvasPainter oldDelegate) => false; } class _MyCanvasState extends State<MyCanvas> { @override Widget build(BuildContext context) { return Scaffold( body: CustomPaint( painter: MyCanvasPainter(), ), ); } }
版面
问题:
如何使用小部件描述布局属性?
答案是:
Flutter使用专用的小部件作为布局属性,例如:
列 ,
行 ,
填充 ,
对齐 ,
堆栈 。
差异:
在React Native中,最常见的布局属性可以使用
props
设置。
附加信息:
小部件的完整列表问题:
如何在布局中放置小部件?
答案是:
对于绝对定位,请使用
堆栈小部件。 对于相对各种小部件及其组合,可以在
此处找到。
一个例子:
Stack( alignment: const Alignment(0.6, 0.6), children: <Widget>[ CircleAvatar( backgroundImage: NetworkImage( 'https://avatars3.githubusercontent.com/u/14101776?v=4'), ), Container( decoration: BoxDecoration( color: Colors.black45, ), child: Text('Flutter'), ), ], )
程式化
问题:
如何为组件设置样式?
答案是:
通常,小部件具有
style
属性。
差异:
React Native使用
stylesheets.create
进行样式设置。
一个例子:
var textStyle = TextStyle(fontSize: 32.0, color: Colors.cyan, fontWeight: FontWeight.w600); ... Center( child: Column( children: <Widget>[ Text( 'Sample text', style: textStyle, ), Padding( padding: EdgeInsets.all(20.0), child: Icon(Icons.lightbulb_outline, size: 48.0, color: Colors.redAccent) ), ], ), )
问题:
如何使用图标和颜色?
答案是:
使用
图标和
颜色类。
差异:
React Native没有开箱即用的图标支持。
一个例子:
图示
Icon(Icons.lightbulb_outline, color: Colors.redAccent)
色彩
class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, textSelectionColor: Colors.red ), home: SampleAppPage(), ); } }
问题:
如何自定义应用程序的样式主题?
答案是:
使用
ThemeData类。
差异:
在React Native中,通用主题是通过
stylesheets
配置的。
一个例子:
@override Widget build(BuildContext context) { return Theme( data: ThemeData( primaryColor: Colors.cyan, brightness: brightness, ), child: Scaffold( backgroundColor: Theme.of(context).primaryColor, ... ... ), ); }
国家管理
问题:
如何更新小部件的显示?
答案是:
使用
StatefulWidget及其
状态 。 Flutter有2种小部件:
StatelessWidget和
StatefulWidget 。 它们以相同的方式工作,唯一的区别在于渲染状态。
差异:
StatelessWidget具有不可变状态。 适用于显示文本,徽标等。 即 如果屏幕上的元素在整个显示时间内均不应更改,则适合您。 它也可以用作有状态窗口小部件的容器。
StatefulWidget具有
状态状态,该状态存储有关当前状态的信息。 如果要在执行某些操作时更改屏幕上的元素(来自服务器的响应,用户单击按钮等),这是您的选择。
一个例子:
1)StatelessWidget-文字
Text( 'I like Flutter!', style: TextStyle(fontWeight: FontWeight.bold), );
2)StatefulWidget-当您单击(FloatingActionButton)按钮时,“文本”小部件中的文本从“
我喜欢颤动”变为“
颤动很棒”! import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget {
本地存储
问题:
如何在应用程序中存储
key-value
数据?
答案是:
使用
shared_preferences插件。
差异:
React Native使用
AsyncStorage 。
一个例子:
成瘾
dependencies: flutter: sdk: flutter shared_preferences: ^0.4.3
使用方法
SharedPreferences prefs = await SharedPreferences.getInstance(); _counter = prefs.getInt('counter'); prefs.setInt('counter', ++_counter); setState(() { _counter = _counter; });
问题:
如何存储复杂数据?
答案是:
使用数据库插件,例如
sqflite或
hive 。
导览
问题:
如何在屏幕之间导航?
答案是:
要在屏幕之间导航,请使用
Navigator和
Route类。
差异:
React Native使用
StackNavigator ,
TabNavigator和
DrawerNavigator 。
Flutter有两种导航方法:
- 用路线名称描述地图
- 直接导航到Route 。
Navigator可以
将()或
pop() 推送到您指定的路线。
一个例子:
void main() { runApp(CupertinoApp( home: MyAppHome(),
问题:
如何使用标签导航?
答案是:
使用类:
TabController ,
TabBar ,
Tab和
TabBarView 。
差异:
React Native使用
createBottomTabNavigator和TabNavigation 。
附加信息:
此处有更多详细信息。 。
一个例子:
class _NavigationHomePageState extends State<NavigationHomePage> with SingleTickerProviderStateMixin { TabController controller=TabController(length: 2, vsync: this); @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: Material ( child: TabBar( tabs: <Tab> [ Tab(icon: Icon(Icons.person),) Tab(icon: Icon(Icons.email),), ], controller: controller, ), color: Colors.blue, ), body: TabBarView( children: <Widget> [ home.homeScreen(), tabScreen.tabScreen() ], controller: controller, ) ); } }
问题:
如何使用抽屉式导航?
答案是:
使用
Drawer类。
差异:
React Native使用
createDrawerNavigator和DrawerNavigation 。
一个例子:
@override Widget build(BuildContext context) { return Scaffold( drawer: Drawer( child: ListTile( leading: Icon(Icons.change_history), title: Text('Screen2'), onTap: () { Navigator.of(context).pushNamed('/b'); }, ), elevation: 20.0, ), appBar: AppBar( title: Text('Home'), ), body: Container(), ); }
手势和触摸事件处理
问题:
如何处理点击?
答案是:
如果小部件支持点击,则在
onPressed()
。 如果不是,则使用
GestureDetector小部件。
差异:
React Native
为此使用
PanResponder或
Touchable 。
一个例子:
GestureDetector( child: Scaffold( appBar: AppBar( title: Text('Gestures'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Text('Tap, Long Press, Swipe Horizontally or Vertically '), ], ) ), ), onTap: () { print('Tapped'); }, onLongPress: () { print('Long Pressed'); }, onVerticalDragEnd: (DragEndDetails value) { print('Swiped Vertically'); }, onHorizontalDragEnd: (DragEndDetails value) { print('Swiped Horizontally'); }, );
HTTP请求
问题:
如何从API请求中获取数据?
答案是:
使用
http插件 。
差异:
React Native使用
fetch API
。
一个例子:
插件连接
dependencies: flutter: sdk: flutter http: <latest_version>
资料检索
final url = Uri.https('httpbin.org', 'ip'); final httpClient = HttpClient(); _getIPAddress() async { var request = await httpClient.getUrl(url); var response = await request.close(); var responseBody = await response.transform(utf8.decoder).join(); String ip = jsonDecode(responseBody)['origin']; setState(() { _ipAddress = ip; }); }
输入形式
问题:
哪些小部件可用于输入?
答案是:
TextField与
TextEditingController或
TextFormField结合使用。
差异:
React Native使用
TextInput 。
TextFormField与
TextField的不同之处在于其内置的验证功能和用于在字段中存储值的逻辑。
一个例子:
文字栏位
final TextEditingController _controller = TextEditingController(); ... TextField( controller: _controller, decoration: InputDecoration( hintText: 'Type something', labelText: 'Text Field ' ), ), RaisedButton( child: Text('Submit'), onPressed: () { showDialog( context: context, child: AlertDialog( title: Text('Alert'), content: Text('You typed ${_controller.text}'), ), ); }, ), )
TextFormField
final formKey = GlobalKey<FormState>(); ... Form( key:formKey, child: Column( children: <Widget>[ TextFormField( validator: (value) => !value.contains('@') ? 'Not a valid email.' : null, onSaved: (val) => _email = val, decoration: const InputDecoration( hintText: 'Enter your email', labelText: 'Email', ), ), RaisedButton( onPressed: _submit, child: Text('Login'), ), ], ), ) void _submit() { final form = formKey.currentState; if (form.validate()) { form.save(); showDialog( context: context, child: AlertDialog( title: Text('Alert'), content: Text('Email: $_email, password: $_password'), ) ); } }
平台特定的代码
问题:
如何确定代码在哪个平台上运行?
答案是:
使用
Theme或
Platform类中的
platform
字段类。
一个例子:
平台领域
if (Theme.of(context).platform == TargetPlatform.iOS) { return 'iOS'; } else if (Theme.of(context).platform == TargetPlatform.android) { return 'android'; } else if (Theme.of(context).platform == TargetPlatform.fuchsia) { return 'fuchsia'; } else { return 'not recognised '; }
平台类
if (Platform.isIOS) { return 'iOS'; } else if (Platform.isAndroid) { return 'android'; } else if (Platform.isFuchsia) { return 'fuchsia'; } else { return 'not recognised '; }
问题:
如何调用本机平台代码?
答案是:
通过
MethodChannel 。
附加信息:
此处有更多详细信息。 。
侦错
问题:
有哪些调试应用程序的工具?
答案是:
开发工具问题:
如何进行
hot reload
?
答案是:
如果该应用程序是从IntelliJ IDE或Android Studio启动的,则
⌘s/ctrl-s
或单击
hot reload
图标。 如果从终端启动,则输入字母
r
。
差异:
对于iOS模拟器,React Native使用
⌘R/Ctrl+R
,对于Android,则使用
⌘R/Ctrl+R
。
问题:
如何访问应用程序中的开发人员菜单?
答案是:
如果是从IDE启动的,则使用IDE工具。 如果从控制台,则使用h。
差异:
React Native在iOS模拟器上使用
⌘D/Ctrl+D
,在Android上使用
⌘M/Ctrl+M
。
附加信息:
完整的球队名单
动画制作
问题:
动画使用什么?
答案是:
Animation和
AnimationController 。
差异:
React Native使用
Animation API
。
附加信息:
此处有更多详细信息。问题:
如何添加简单的
fade-in
动画?
答案是:
使用
FadeTransition 。
一个例子:
import 'package:flutter/material.dart'; void main() { runApp(Center(child: LogoFade())); } class LogoFade extends StatefulWidget { _LogoFadeState createState() => _LogoFadeState(); } class _LogoFadeState extends State<LogoFade> with TickerProviderStateMixin { Animation animation; AnimationController controller; initState() { super.initState(); controller = AnimationController( duration: const Duration(milliseconds: 3000), vsync: this); final CurvedAnimation curve = CurvedAnimation(parent: controller, curve: Curves.easeIn); animation = Tween(begin: 0.0, end: 1.0).animate(curve); controller.forward(); } Widget build(BuildContext context) { return FadeTransition( opacity: animation, child: Container( height: 300.0, width: 300.0, child: FlutterLogo(), ), ); } dispose() { controller.dispose(); super.dispose(); } }
问题:
如何将滑动动画添加到列表项?
答案是:
使用
Dismissible 。
一个例子:
child: Dismissible( key: key, onDismissed: (DismissDirection dir) { cards.removeLast(); }, child: Container( ... ), ),
等效组件
问题:
与React Native相比,Flutter的等效功能是什么?
答案是:
Flutter插件
问题:
如何访问GPS?
答案是:
使用
geolocator插件。
问题:
如何使用相机?
答案是:
使用
image_picker插件。
问题:
如何通过Facebook登录?
答案是:
使用
flutter_facebook_login插件。
问题:
如何使用firebase?
答案是:
Firebase支持
Flutter第一方插件 :
这也许是基本问题的答案。 我希望我的解释对您有用,如果您还没有写Flutter,请至少考虑一下。 这意味着在Flutter开发人员的基础上可能会增加一些东西,并且我们将共同通过开发方便快捷的应用程序使世界变得更美好! 是的,React不会破坏您的本机!