предисловие
Когда React Native был в огне, я ударил одного из нихместоКлиент , недавно нашел время написать свой собственный проект на Flutter, адрес проектакликните сюда, я хотел бы дать вам звезду🌟, когда вы будете проходить мимо, большое спасибо; Ниже приводится краткое изложение некоторых взглядов и опыта использования Flutter в качестве внешнего интерфейса;
Dart
Когда я начал писать Flutter, я сначала не изучал Dart. Я думал, что он немного похож на TypeScript. С Dart было легко начать работу. Я прочитал его только тогда, когда столкнулся с некоторыми незнакомыми проблемами.Дарт Документация, поговорим о некоторых разных понятиях:
-
объявление переменной
-
var
Как в JavaScript, так и в Dart он может принимать любой тип, но как только переменная var в Dart будет назначена, тип будет определен, и его тип нельзя будет изменить;
var a; a = 'hello'; // a 已经确定为String类型 a = 1; // 报错,类型不能更改
-
dynamic & Object
В javaScript нет объявления динамической переменной, в отличие от var, обе они поддерживают изменение типа переменной после объявления, но переменная, объявленная Object, может использовать только свойства и методы, принадлежащие Object, а dynamic поддерживает все свойства.
-
final & const
Буквально обе объявлены константами, но переменные const являются константами времени компиляции, а переменные final инициализируются при первом использовании;
-
-
Асинхронная поддержка
И async, и await одинаково используются в Javascript и Dart, но обещания нет, вместо этого есть Future, но нет разрешения и отказа.
-
Конструктор В Dart подклассы не наследуют именованный конструктор суперкласса. Если вы явно не предоставляете конструктор подкласса, система предоставляет конструктор по умолчанию. При этом способ написания стал более лаконичным;
class Point { num x; num y; Point(this.x, this.y);// 这句等同于 /* Point(num x, num y) { this.x = x; this.y = y; } */ }
-
стрелочная функция
В Javascript функция стрелки существует как область действия, которая влияет на это, но в Dart она существует как сокращенный синтаксис.Концепции этих двух различны и должны быть четко различаются;
Макет пользовательского интерфейса
Во-первых, давайте посмотрим на тот же макет, используя HTML + CSS и разницу в написании Flutter.
Во Flutter весь UI основан на виджете, на картинке выше Container — это виджет, который стилизован по стилю (можно также использовать Theme, о чем будет подробно рассказано позже), а подклассы вложены в дочерние.
class MainApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
По сути, этот способ написания немного похож на виртуальный Дом, который написан в древовидной вложенности, но такой способ написания лично мне кажется, что его очень сложно поддерживать.Если не будет хватать подразделенных компонентов, читабельность тоже станет очень плохо На самом деле, во Flutter также есть проблемы сОбсуждение JSX-подобного письма, Чтобы пожаловаться на такую манеру написания, я недавно видел очень подходящую картинку по температуре кипения наггетсов:
О виджете см.Каталог виджетов китайской сети Flutter, не буду писать подробности, вот несколько нетипичных моментов, требующих внимания:
-
Expanded
Нельзя использовать для виджетов неопределенной или бесконечной высоты (таких какSingleChildScrollView
) середина -
BuildContext
Концепция чего-либоBuildContext
По сути, это объект Element, созданный текущим виджетом.Чтобы получить размер компонента, нужно использоватьMediaQuery.of(context).size
, также используется при маршрутизации переходовNavigator.of(context)
, более подробные инструкции по расширению и пониманию можно найти вГлубокое понимание BuildContextЭта статья; -
Управление состоянием виджета
Здесь, чтобы представить
InheritedWidget
,InheritedWidget
— это специальный виджет, который можно поместить в дерево виджетов в качестве родителя другого поддерева. Все дочерние виджеты этого поддерева могут взаимодействовать с этимInheritedWidget
Раскрываемые данные взаимодействуют, тем самым реализуя связь между WIDGET; можно указать дополнительные способы управления состоянием.Глубокое погружение в управление состоянием во флаттере
стиль
Во Flutter стили не извлекаются, а используются в различных (хаотичных и даже странных) комбинациях.TextStyle
, установить фон границы и т. д. для использованияdecoration
, можете посмотреть, если интересноНекоторые сравнения использования стилей;
Здесь я хочу плюнуть на управление стилями, во Flutter можно использоватьTheme
для совместного использования стилей, но стили одного виджета являются дополнением кDefaultTextStyle
Нет никакого наследования кроме установки стиля текста по умолчанию.Все равно их надо писать по одному.Здесь мы продвигаем доработку компонентов(иначе будет лень писать повторно).Тема имеет следующие способы использования
-
глобальная тема
new MaterialApp( title: title, theme: new ThemeData( brightness: Brightness.dark, ), );
-
местная тема
new Theme( data: new ThemeData( accentColor: Colors.yellow, ), child: new Text('Hello World'), );
-
Развернуть тему
Если вы не хотите переопределять все стили, вы можете унаследовать тему приложения и переопределить только некоторые стили, используя метод copyWith.
new Theme( data: Theme.of(context).copyWith(accentColor: Colors.yellow), child: new Text('extend theme'), );
-
получить тему
Theme.of(context)
Будет искать дерево виджетов и возвращать ближайший объект Theme. Если на родительском уровне есть объект Тема, возвращается эта Тема, если нет, возвращается Тема Приложения. Чтобы создать тему, просто вызовите ее через метод Theme.of(context) в конструкторе виджета.new Container( color: Theme.of(context).accentColor, chile: new Text( 'Text with a background color', style: Theme.of(context).textTheme.title, ), );
государственная составляющая
С сохранением состояния и без состояния
Любой, кто использовал React, знает компоненты без состояния и компоненты с состоянием.StatelessWidget
Это компонент без состояния, который не зависит ни от каких других данных, кроме переданных данных, а это означает, что изменение параметров, переданных в его конструктор, — единственный способ изменить его отображение. иStatefulWidget
Это компонент с состоянием, но он немного отличается от React.render
и состояние вместе, и во Флаттере,StatefulWidget
нужно переписатьcreateStae()
, возвращает состояние иbuild
Метод нужно поместить в State, а почему бы и не в StatefulWidget? Есть две причины:
-
проблема с доступом к состоянию
так как
build
Метод вызывается каждый раз при изменении состояния, вStatefulWidget
Когда много состояний,build
Метод должен передавать параметр State.Тогда все состояния State могут быть доступны только за пределами класса State, но после того, как состояние будет раскрыто, состояние больше не будет частным, поэтому изменение состояния станет неуправляемый;Widget build(BuildContext context, State state){ //state.a etc... ... }
-
Проблема наследования StatefulWidget
Когда возникает первая ситуация, если есть дочерний виджет, который наследуется от абстрактного метода, который вводит
build(BuildContext context)
Родительский виджет, затем дочерний виджет реализует этоbuild
В это время родительский виджет должен передать свое состояние дочернему виджету, что очень неразумно, поскольку состояние родительского виджета связано только с его собственной логикой, и его нужно передать дочернему виджету. , следовательно, должно бытьbuild
Методы помещаются в состояние.class ChildWidgert extends ParentWidget{ @override Widget build(BuildContext context, State state){ super.build(context, _parentWidgetState) } }
жизненный цикл
Жизненный цикл Flutter выглядит следующим образом:
Скажите некоторые часто используемые:-
initState
Эта функция эквивалентна инициализации State в конструкторе в React, и на этом шаге можно выполнить загрузку запроса данных.
-
didUpdateWidget
когда звонят
setState
При изменении состояния виджета Flutter создаст новый виджет для привязки этого состояния и передаст старый виджет в этом методе, если вы хотите сравнить старый и новый виджет и внести некоторые коррективы в состояние, или некоторые виджеты включают изменения в состояние. controller , вы можете удалить старый контроллер и создать новый контроллер в этом методе обратного вызова;@override void didUpdateWidget(AVCycleLess oldWidget){ super.didUpdateWidget(oldWidget); }
-
dispose
Когда виджет освобождается (например, при переключении маршрута), в виджете есть некоторые отслеживаемые или постоянные переменные, и вам необходимо освободить его.
FutureBuilder
Когда мы заходим на страницу для выполнения некоторых трудоемких операций, таких как запрос данных, инициализация некоторых настроек и т. д., нам обычно нужно отобразить страницу загрузки.Общая практика заключается в оценке состояния данных для переключения отображаемых компонентов и во флаттере естьFutureBuilder
Это удобное решение будет здесь очень длинным, вы можете обратиться кКак использовать FutureBuilder и вопросы, требующие внимания
маршрутизация
Во Flutter маршрутизация делится на статическую маршрутизацию и динамическую маршрутизацию.Статическая маршрутизация не может передавать параметры, поэтому, когда необходимо передать параметры, можно использовать только динамическую маршрутизацию;
статическая маршрутизация
Статические маршруты определяются при создании нового приложения, используйтеNavigator.of(context).pushNamed('/router/a');
Для переключения pushNamed возвращает Future, который может получить возвращаемое значение со следующей страницы.
return new MaterialApp(
home: new Text('hello'),
routes: <String, WidgetBuilder> {
'/router/a': (_) => new APage(),
'/router/b': (_) => new BPage(),
},
);
// then 说明
// 当前页面
Navigator.of(context).pushNamed('/router/b').then((value) {
// value 为下一个页面的返回值
});
// b 页面
Navigator.of(context).pop('some data');
динамическая маршрутизация
Используйте динамическую маршрутизациюpush
метод, передать объект маршрута, создать новый объект страницы в конструкторе, если вам нужно настроить эффект анимации, просто используйтеPageRouteBuilder
заменятьMaterialPageRoute
,существуетtransitionsBuilder
Вы можете определить анимацию в .
Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
return new NewPage(data: 'some data');
}));
сетевой запрос
Dio
Во Flutter сетевые запросы выполняютсяHttpClient
Однако операция очень хлопотная, поэтомуDioТакая отличная библиотека запросов упрощает нашу работу, следует отметить, что когда приложение имеет только один источник данных, Dio должен использовать шаблон singleton.
Сериализация
Когда мы получаем данные, мы обычно получаем JSON, В JavaScript мы можем напрямую использовать оператор точки, чтобы получить поля в данных, но в Dart вам нужно импортироватьdart:convert
и использоватьJSON.decode(json)
, но возвращаетMap<String, dynamic>
, означает, что мы не знаем тип значения до времени выполнения, и мы теряем большинство функций статически типизированного языка: безопасность типов, автодополнение и, что наиболее важно, исключения времени компиляции.
Но тогда наш код может стать очень подверженным ошибкам. Обычно нам нужно писать классы моделей для сериализации JSON, что официально рекомендуется.json_serializable
(См. соответствующие операцииздесь), чтобы помочь нам сгенерировать сериализацию библиотеки JSON, таким образом, мы можем напрямую использовать оператор точки для управления данными.
Если это все еще проблематично, вы можете попробоватьJSONFormat4FlutterЭтот инструмент (я еще не использовал его, он выглядит очень хорошо.)
обработка событий
В Vue нам просто нужно использовать@click
Вы можете прослушивать события, используя такие методы, какonClick
например, но во Flutter нам нужно обернуть элементы, которые должны прослушивать события, вGestureDetector
в использованииonTap
и другие методы для обработки событий, а для поведения событий мы можем установитьbehavior
контролировать,
enum HitTestBehavior {
deferToChild, // 子widget会一个接一个的进行命中测试,如果子Widget中有测试通过的,则当前Widget通过,这就意味着,如果指针事件作用于子Widget上时,其父(祖先)Widget也肯定可以收到该事件。
opaque,// 在命中测试时,将当前Widget当成不透明处理(即使本身是透明的),最终的效果相当于当前Widget的整个区域都是点击区域
translucent,// 当点击Widget透明区域时,可以对自身边界内及底部可视区域都进行命中测试,这意味着点击顶部widget透明区域时,顶部widget和底部widget都可以接收到事件
}
Canvas
Во Flutter, если нам нужно использовать Canvas, нам нужно наследовать CustomPainter и переопределить метод рисования для рисования пользовательской графики. При использовании Canvas нам нужно знать три понятия:
-
canvas
Объект Canvas, включая различные методы рисования, используемые для рисования различной графики.
-
size
размер текущей области рисования
-
paint
Кисти, используемые для управления различными свойствами рисунка, такими как цвет, обводка и сглаживание;
Пример использования следующий:
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.drawRect(Offset.zero & size, Paint()
..isAntiAlias = true // 抗锯齿
..style = PaintingStyle.fill // 填充,stroke则为使用描边
..color = Color(0xFF000000) // yanse
);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => false; // 强制不重绘,提高性能
}
мультиплекс
Mixin
Когда дело доходит до миксинов, я полагаю, что пользователи Vue и React знакомы с ними.Хотя миксины были заменены функциями более высокого порядка или декораторами в React, во Flutter миксины все еще сохраняются.
оно используетwith
Чтобы ввести миксин, определение выглядит следующим образом:
class A {
int a = 1;
void b(){
print('c');
}
}
class B with A{
}
B b = new B();
print(b.a);
b.b();
Однако примеси имеют следующие условия для использования в Dart:
- классы миксинов могут наследоваться только от объекта
- классы миксинов не могут иметь конструкторов
- Класс может примешивать несколько классов примесей
- Может смешивать несколько классов, не нарушая единого наследования Flutter
Keep-alive
При использовании вкладки, после переключения вкладки, каждая вкладка будет уничтожена и перестроена, поэтому initState будет вызываться несколько раз.Есть ли что-то подобное в Vue?<keep-alive>
А как насчет тех же компонентов? Ответ да, то естьAutomaticKeepAliveClientMixin
. Просто унаследуйте этот миксин и реализуйтеwantKeepAlive
метод. Однако виджет не будет уничтожен после того, как он не будет отображаться, а все еще хранится в памяти, поэтому используйте этот метод с осторожностью.
class APageState extends State<APage> with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true;
// ...
}
позже
Вышеизложенное — это только то, что я узнал, когда делал первое грубое приложение Flutter с перерывами за последние 10 дней, Некоторые из них — это некоторые знания, которые я увидел в процессе проверки данных, которые не использовались в проекте, и там много подробных или неизведанных вещей. То, в чем я был, стоит обсудить, и я расскажу об этом позже, когда у меня будет возможность.
Ссылаться на
- официальный сайт флаттера(Настоятельно рекомендуется превалировать официальная документация, которую удобнее запрашивать)
- Флаттер в действии(настоятельно рекомендуется)
- Китайская сеть Flutter