[在码头旁]颤抖。 第3部分。对于React本机开发人员

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



如果这些信息还不够,或者您有特定平台的本机开发经验,那么我建议您查看其他部分:

第1部分。对于Android开发人员
第2部分。对于iOS开发人员
第3部分。对于React本机开发人员
扑 第4部分。对于Web开发人员
扑 第5部分。对于Xamarin.Forms开发人员

内容:


  1. 关于Dart的一点

  2. 基础知识

  3. 项目结构与资源

  4. 观看次数

  5. 版面

  6. 程式化

  7. 国家管理

  8. 本地存储

  9. 导览

  10. 手势和触摸事件处理

  11. HTTP请求

  12. 输入形式

  13. 平台特定的代码

  14. 侦错

  15. 动画制作

  16. 等效组件

  17. Flutter插件



关于Dart的一点


问题:


入口在哪里?

答案是:


函数main()

差异:


JavaScript没有预定义的入口点;它可以是开发人员定义的任何函数。 在Dart中,这仅是main()

问题:


如何输出到控制台?

答案是:


使用print()函数。

差异:


在JavaScript中,使用console.log()完成控制台输出。

一个例子:


 print('Hello world!'); 

问题:


如何创建和分配变量/字段?

答案是:


Dart支持动态键入和强类型键入。 因此,可以使用任何方便您键入的类型来创建变量/字段。 分配通过单个=进行。

差异:


JavaScript不支持强类型。

附加信息:


此处有更多详细信息。

一个例子:


 String name = 'dart'; // Explicitly typed as a string. var otherName = 'Dart'; // Inferred string. // Both are acceptable in 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; } // can also be written as bool 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)); } 

问题:


asyncawait什么?

答案是:


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上创建应用程序项目?

答案是:


  1. 将IDE与已安装的Flutter和Dart插件一起使用。
  2. 使用flutter create {projectname}

差异:


要在React Native中创建项目,请使用create-react-native-app {projectname}

附加信息:


此处有更多详细信息。

问题:


如何启动应用程序?

答案是:


  1. 在安装了Flutter和Dart插件的IDE中使用运行功能。
  2. 使用flutter run命令。

差异:


React Native使用npm runyarn 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, ), ], ) ); } } ... // Usage CustomCard( index: index, onPress: () { print('Card $index'); }, ) ... 

项目结构与资源


问题:


从哪里开始编写代码?

答案是:


{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容器?

答案是:


用于布局的所有基本小部件,例如ContainerColumnRowCenter

附加信息:


此处有更多详细信息。

问题:


FlatListSelectionList的类似物是什么?

答案是:


列表视图

一个例子:


 var data = [ ... ]; ListView.builder( itemCount: data.length, itemBuilder: (context, int index) { return Text( data[index], ); }, ) 

问题:


如何使用画布?

答案是:


使用CustomPaintCustomPainter类

差异:


在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种小部件: StatelessWidgetStatefulWidget 。 它们以相同的方式工作,唯一的区别在于渲染状态。

差异:


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 { //     . @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { //   String textToShow = "  Flutter"; void _updateText() { setState(() { //   textToShow = "Flutter !"; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: Center(child: Text(textToShow)), floatingActionButton: FloatingActionButton( onPressed: _updateText, tooltip: ' ', child: Icon(Icons.update), ), ); } } 

本地存储


问题:


如何在应用程序中存储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; }); 

问题:


如何存储复杂数据?

答案是:


使用数据库插件,例如sqflitehive

导览


问题:


如何在屏幕之间导航?

答案是:


要在屏幕之间导航,请使用NavigatorRoute类。

差异:


React Native使用StackNavigatorTabNavigatorDrawerNavigator

Flutter有两种导航方法:

  1. 路线名称描述地图
  2. 直接导航到Route

Navigator可以将()pop() 送到您指定的路线。

一个例子:


 void main() { runApp(CupertinoApp( home: MyAppHome(), // becomes the route named '/' routes: <String, WidgetBuilder> { '/a': (BuildContext context) => MyPage(title: 'page A'), '/b': (BuildContext context) => MyPage(title: 'page B'), '/c': (BuildContext context) => MyPage(title: 'page C'), }, )); } Navigator.of(context).pushNamed('/b'); 

问题:


如何使用标签导航?

答案是:


使用类: TabControllerTabBarTabTabBarView

差异:


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 为此使用PanResponderTouchable

一个例子:


 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; }); } 

输入形式


问题:


哪些小部件可用于输入?

答案是:


TextFieldTextEditingControllerTextFormField结合使用。

差异:


React Native使用TextInput
TextFormFieldTextField的不同之处在于其内置的验证功能和用于在字段中存储值的逻辑。

一个例子:


文字栏位

 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'), ) ); } } 

平台特定的代码


问题:


如何确定代码在哪个平台上运行?

答案是:


使用ThemePlatform类中的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

附加信息:


完整的球队名单

动作片终端团队功能和领域
小部件层次wdebugDumpApp()
渲染树ŤdebugDumpRenderTree()
层数大号debugDumpLayerTree()
辅助功能S(遍历顺序)或U(逆向命中测试顺序)debugDumpSemantics()
小部件检查器WidgetsApp.showWidgetInspectorOverride
显示施工线pdebugPaintSizeEnabled
模拟不同的操作系统ØdefaultTargetPlatform
性能表现PWidgetsApp。 showPerformanceOverlay
截图flutter.pngs
申请关闭q

动画制作


问题:


动画使用什么?

答案是:


AnimationAnimationController

差异:


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第一方插件

  • 用于Firebase AdMob的firebase_admob;
  • firebase_analytics for Firebase Analytics;
  • firebase_auth用于Firebase身份验证;
  • 用于Firebase RTDB的firebase_database;
  • firebase_storage用于Firebase云存储;
  • 用于Firebase消息传递(FCM)的firebase_messaging;
  • flutter_firebase_ui用于快速集成Firebase Auth(Facebook,Google,Twitter和电子邮件);
  • 用于Firebase Cloud Firestore的cloud_firestore

这也许是基本问题的答案。 我希望我的解释对您有用,如果您还没有写Flutter,请至少考虑一下。 这意味着在Flutter开发人员的基础上可能会增加一些东西,并且我们将共同通过开发方便快捷的应用程序使世界变得更美好! 是的,React不会破坏您的本机!

Source: https://habr.com/ru/post/zh-CN484284/


All Articles