Я все еще в процессе обучения дартс/флаттеру. Я экспериментирую с ListView/ListTile и, в частности, с onTap() из ListTile.
Я немного знаком с JS/Jquery, и мне трудно понять различия в подходах между JS и флаттером.
Пожалуйста, постарайтесь игнорировать любые семантические или технические ошибки в приведенном ниже коде. Меня больше интересует теория/подход, чем если бы это был идеально отформатированный и синтаксически правильный пример.
В JS обычно делают что-то вроде вызова AJAX к API, чтобы получить список товаров для продажи из базы данных. Предположим, что API вернул 4 поля (идентификатор первичного ключа, isAvailable, название товара и цена товара). Затем вы обрабатываете список и создаете/вставляете элементы DOM для отображения.
<div id = "234" data-isavailable = "y" class = ".itemsForSale">TV: $800</div>
<div id = "345" data-isavailable = "y" class = ".itemsForSale">Microwave: $200</div>
<div id = "456" data-isavailable = "n" class = ".itemsForSale">Book: $30</div>
<div id = "567" data-isavailable = "y" class = ".itemsForSale">Sofa: $450</div>
Затем вы можете установить слушателей произвольно. Например, вы могли бы сделать...
$( ".itemsForSale" ).click(function() {
// do something
});
Обработчик кликов применяется в «реальном времени». Выполняемый код знает, что было нажато, и может анализировать/взаимодействовать с этим элементом в списке. Итак, вы можете сделать что-то вроде:
$( ".itemsForSale" ).click(function() {
var isAvailable = $(this).attr('data-isavailable');
if ( isAvailable == 'n' )
alert('sorry but that item is out of stock!');
else
addItemToCart( $(this).attr('id') );
});
Дело в том, что обработчик кликов не обязательно знает или заботится о базовых данных каждого элемента. Он становится «контекстным» во время выполнения, а затем извлекает соответствующие значения из пользовательского интерфейса и т. д.
С флаттером я хочу воссоздать аналогичную функциональность, используя ListView и ListTile. В частности, onTap() в ListTile. Я путаюсь, потому что кажется, что все закодировано «наперед».
Вот базовый пример (не обращайте внимания на то, что я не показываю цену/и т. д.)...
import 'package:flutter/material.dart';
class SecondScreen extends StatelessWidget {
var mapper = {
'234': 'TV',
'345': 'Microwave',
'456': 'Book',
'567': 'Sofa'
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body:
ListView.builder(
padding: const EdgeInsets.all(8.0),
itemCount: mapper.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
key: new Key(mapper.keys.elementAt(index).toString()),
title: Text('${mapper.values.elementAt(index)}'),
onTap: () {
print('you clicked: ' + mapper.keys.elementAt(index).toString() );
addToShoppingCart( mapper.keys.elementAt(index).toString() ); // this doesnt exist yet and is just an example
}
);
}
)
);
}
}
Прежде всего, я даже не уверен, что мне нужно назначать пользовательский ключ каждому элементу ListView (на основе первичного ключа базы данных), но сейчас это не имеет значения.
Я застрял на том, что обработчик onTap, похоже, не имеет эквивалента «$ (this)». Предоставляет ли флаттер каждому ViewTile свою «собственную» копию onTap() и что каждая соответствующая ключевая информация «жестко закодирована» в каждом из них (для каждого цикла itemBuilder текущее значение mapper.keys.elementAt(index).toString() равно заменен на onTap() )?
Я, вероятно, неправильно описываю свое замешательство, и я даже не уверен во всех проблемах, с которыми столкнусь. Я уверен, что мой способ сделать это очень «старый» и не соответствует реакции и другим новым подходам/фреймворкам (объединение данных в элементах пользовательского интерфейса).
Я просто не понимаю, как я смогу добавить более сложную логику (например, проверку доступности того, что было нажато).
Есть ли у кого-нибудь ссылки или объяснения, которые помогут мне преодолеть этот пробел? Я даже не знаю, как описать концепцию $(this) и как ее искать по сравнению с flutter/etc. Я просто знаю, что что-то чувствуется совсем по-другому.
Спасибо!





Я понимаю ваше замешательство, вероятно, потому, что у меня был похожий вопрос, когда я начал работать с Flutter всего несколько месяцев назад. И вот что я думаю -
На самом деле не имеет значения, есть ли у элемента ListTile собственная копия onTap() или нет. О. У него нет собственной копии. (Следующий фрагмент кода объяснит) и B. Каждый язык программирования/SDK/что угодно имеет свой собственный способ работы. Вы, вероятно, пытаетесь сказать, что у вас BMW. У него есть определенный тип перерывов. И вы пытаетесь сделать точный тип перерыва в Audi. Это может быть неправильно, так как другие системы, связанные с перерывами, могут работать неоптимальным образом.
Теперь взгляните на следующий фрагмент кода:
@override
Widget build(BuildContext context) {
return ListView.separated(
separatorBuilder: (context, index) => ListViewDivider(),
itemCount: faceRecTransactions.length,
itemBuilder: (BuildContext context, int index) {
return FacerecTransactionListItem(facerecTransaction: faceRecTransactions[index], onTap:()=> _onTap(faceRecTransactions[index],context),);
},
);
}
void _onTap(FacerecTransaction facerecTransaction, BuildContext context) {
print('Status : ${facerecTransaction.userId}');
Navigator.push(context, MaterialPageRoute(builder: (context) => FacerecDetailPage(
facerecTransaction: facerecTransaction,
criminalList: this.criminalList,)));
}
Нет копии onTap для каждого элемента списка. Он просто «ощущается» таким, какой он есть, потому что мы пишем onTap внутри ListView. Если вы посмотрите на приведенный выше пример, когда пользователь нажимает на определенный элемент, тогда onTap получает информацию. Мы не создаем массив onTap как таковой.
Поскольку копии onTaps нет, это не опережающий код. Это в значительной степени работает как в Ajax, где onTap на самом деле не заботится о полезной нагрузке. Он просто выполняет указанные действия.
Теперь, в приведенном выше примере, подробная страница может проверить доступность определенного элемента. И если элемент недоступен, может быть показано любое соответствующее сообщение. В зависимости от требований мы можем написать этот код либо в onTap, либо на следующей странице. Короче говоря, onTap может обрабатывать сложную логику так, как вам нужно.
большое спасибо за подробный ответ! полезно знать, что нет массива onTap, как вы сказали. это все еще кажется немного «опережением времени», но я думаю, что это просто потому, что это такой другой подход к кодированию.
Да, конечно.
дополнительная мысль: из-за $(this) вы можете делать такие вещи, как просмотр предыдущих/последующих братьев и сестер в DOM или даже перейти к родительскому узлу и проверить атрибуты родителя. подобные вещи просто помогают вам быть более осведомленным о том, что делает пользователь, в зависимости от того, как организован экран и т. д.