[ReactJS] Калькулятор на телефон как способ знакомства с React-native
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Приветствую.
Так получилось, что последние несколько лет я занимался веб-разработкой, однако - в последнее время появилась возможность и желание попробовать себя в разработке на мобильные устройства. Причин на то было несколько, начиная от понимания того, что десктопам отводится все меньшая роль, и эта тенденция сохраняется, и заканчивая тривиальным желанием попробовать что либо новое. Кроме ого, была пара задумок для рet-проектов, которые предполагали использование возможностей мобильных платформ. Как это было и что из этого вышло - под катом <cut /> ВведениеВвиду того, что на момент планированного перехода в мобильную разработку основным инструментов разработки для меня являлся ReactJS, было принято решение начать именно с него. Кроме того, мною была использована платформа для сборки приложений Expo, которая решила существенную часть проблем с конфигурацией - сборка приложения осуществлялась буквально за несколько команд.
Первым относительно серьезным(по крайней мере, работающим, а не показывающим работоспособность QuickStart`a) приложением для меня стал калькулятор - примерно такой же, как есть в каждом из смартфонов. Калькулятор должен был содержать один экран, в котором есть 2 раздела - дисплей и клавиатура, дисплей - отображает информацию, а клавиатура позволяет ее вводить
Скриншоты получившегося приложения расположены под спойлером. Признаю, выглядит не как шедевр дизайна, но - не сильно хуже встроенного калькулятора. Интерес тут представляет не это
Spoiler
Горизонтальное отображение
Вертикальное отображениеДля запуска используется онлайн-версия эмулятора, но на нескольких домашних устройствах с андроидом, а так же - в браузерной версии Экспо оно выглядит приблизительно также.Анализ исходного кода Для того, что бы приложение было по минимуму "захардкодженным" я вынес все кнопки, которые должны быть на клавиатуре в отдельный двумерный массив. При этом, ввиду того, что надпись на каждой кнопке уникальна - она же используется и в качестве id, т.е. именно по ней привязывается функция-обработчик.
let labels=[
["1","2","3"],
["4","5","6"],
["7","8","9"],
["0", ".","+/-"],
["+","-","*","/"],
["ln","C", "=",]
]
Данный подход позволяет не только изменять расположение клавиш, но еще и - в случае необходимости - получать их с сервера, не меняя логику самого приложения.
Аналогичным образом сделана и привязка операций к кнопкам - при этом надпись на кнопке является ключом, а функция, в моем случае стрелочная - значением. Ввиду объемности следующего объекта - уберу его под спойлер. Для взаимосвязи использовались хуки состояний - об этом упомяну чуть позже.Spoiler
let functionMapping = {
"+":()=>{
setOperation(()=>(a,b)=>{return a+b})
setFirstOperand(display);
setDisplay("")
},
"-":()=>{
setOperation(()=>(a,b)=>{return a-b})
setFirstOperand(display);
setDisplay("")
},
"*":()=>{
setOperation(()=>(a,b)=>{return a*b});
setFirstOperand(display);
setDisplay("")
},
"/":()=>{
setOperation(()=>(a,b)=>{return a/b});
setFirstOperand(display);
setDisplay("");
},
"ln":()=>{
setOperation(()=>(a,b)=>{return Math.log(a)});
setFirstOperand(display);
},
"C":()=>{
setFirstOperand("");
setsecondOperand("");
setOperation(null);
setDisplay("");
},
"+/-":()=>{
setDisplay((+display)*(-1)+"");
},
".":()=>{
if (display.indexOf(".")===-1)
setDisplay(display+".")
},
"=":()=>{
setsecondOperand(display);
let rezult = operation(+firstOperand, +display);
setDisplay(rezult);
}
}
for (let i =0; i<10; i++) {
functionMapping[i+""]=()=>{setDisplay(display+i)};
}
Тут особого внимания заслуживают конструкции вида
setOperation(()=>(a,b)=>{return a * b})
Выглядит крайне нелогично, кроме того - ошибка, которая выбрасывается при использовании интуитивного
setOperation(()=>{return ab})
весьма посредственно гуглится.
Однако, в статье рассматривается данная проблема - не только ее решение, но и причины, почему это было сделано именно так.
Кроме того, для числовых значений кнопок функция-хэндлер однотипна, поэтому добавление ее обработчиков вынесено в отдельный цикл.В моем проекте используются функциональные компоненты, поэтому вместо громоздких выражений с конструкторами для хранения требуемой информации используются 4 переменных состояния, одна из которых к тому же не момент релиза не используется (однако умышленно оставлена, ввиду планов на дальнейшее развитие)
const [operation, setOperation] = useState(null);
const [firstOperand, setFirstOperand] = useState("");
const [secondOperand, setsecondOperand] = useState("");
const [display, setDisplay] = useState("");
Соответственно, firstOperand и secondOperand хранят значения переменных, display отвечает за информацию, выводимую на экран, а operation хранит ключ выбранной операции.
На этом вся логика приложения закончилась, все что происходит дальше - лишь отображение компонентов и прикрепление таблицы стилей
Прикреплю это под спойлер, кроме того, в конце статьи будет ссылка на репозиторий со всеми исходниками.SpoilerОтображение компонентов
<View style={styles.root}>
<View style = {styles.display}>
<Text style={{fontSize: 40}}>
{display}
</Text>
</View>
<View style={styles.keyboard}>
{labels.map((value, index, array)=>{
return <View style={styles.row}>
{value.map((item)=>{
return <TouchableOpacity style={styles.cell} onPress={()=>{functionMapping[item]()}}>
<Text style={{fontSize: 35}}>{item}</Text>
</TouchableOpacity>
})}
</View>
})}
</View>
</View>
Стили
const styles = StyleSheet.create({
root: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
fontSize:40
},
display:{
flex: 2,
backgroundColor: "lightblue",
width: "100%",
justifyContent: "space-around",
alignItems: "center"
},
keyboard:{
flex: 9,
width: "100%",
backgroundColor:"lightgrey",
justifyContent:"space-around",
alignItems:"center"
},
row:{
flex: 1,
flexDirection:"row",
justifyContent:"space-around",
alignItems:"center",
width:"100%",
},
cell:{
flex:1,
borderWidth:1,
width:"100%",
height:"100%",
justifyContent:"space-around",
alignItems:"center",
}
});
Процесс написания и отладки-ощущенияПриложение создавалось мною с помощью Expo quickstart. Она создает базовое приложение, имеющее все основные разделы и базовый файл App.js, который предполагается изменять для получения желаемого результата. Проблем с конфигурацией практически нет - в этом большой плюс, т.к. попытки разобраться с созданием мобильных приложений на Java разбивались в том числе и о сложности конфигурации (это была не единственная причина, но с конфигами Джавы у меня исторически сложились напряженные отношения). Любое изменение практически сразу же можно увидеть на web-сервере, запускаемым Expo, либо - в эмуляторе.
Однако тут есть несколько проблем. Большую часть времени я отлаживал приложение в браузере, запуская эмулятор андроида только перед тем как отправить на сборку релизной версии. И - возникла очень не очевидная проблема, когда один и тот же код корректно работал на веб-версии и напрочь вылетал на андроиде, не оставляя никаких логов. Методом последовательного исключения компонентов было выявлено, что проблема в компоненте Picker, который ожидал получить в качестве называния строку, а получал - число. (данный элемент не попал в релизную версию программы, но не отметить я это не мог). Кроме того, в веб-версии шрифты можно было изменять с помощью поля строкового типа, задавая ему габариты в условно любых единицах - процентах, пикселях или даже архаичных "сантиметрах", в то время как на андроиде программа требовала дать ей только число.
Очень не порадовало отсутствие по умолчанию наследования свойств - нельзя было задать шрифт и выравнивание для корневого элемента, полагая, что все его потомки будут его поддерживать.
С другой стороны - очень к месту приходится возможность flex разметки, которая в вебе появилась сравнительно недавно - именно с ее помощью получается получать довольно аккуратную верстку даже на довольно экстремальных соотношениях сторон. С помощью "классического" CSS, безусловно, можно сделать то же самое, но это потребует на порядок более кропотливой работы.
Ну и безусловно - размер сборки получается слишком весомый. Я понимаю, что это плата за простоту написания, и на чем-либо уровня С, размер приложения будет существенно меньше, но тем не менее...ВыводыВ целом, учитывая опыт верстки на чистом Реакте, освоение основных принципов React-native заняло очень небольшое количество времени. Инструмент содержит в себе основные преимущества Реакта, однако - не клонирует его полностью, внося ряд ограничений и добавляя новые возможности. В некотором роде можно сказать, что нативный Реакт более требователен к типам, чем обычный, но если сравнивать его с React over TypeScript - различий становится еще меньше. Как мне кажется, можно сказать, что react-native может стать неплохой точкой входа в индустрию разработки мобильных приложений для лиц, имеющих опыт в вебе. P.S. Cтатья не претендует на рассмотрение как авторитетное мнение о технологии, она лишь описывает - надеюсь, объективно - первое впечатление от инструмента от человека, имеющего опыт в смежной области
P.P.S Целевая аудитория статьи - не гуру веб разработки, а скорее смежники, подобные мне.
Исходники
===========
Источник:
habr.com
===========
Похожие новости:
- [Ненормальное программирование, Assembler, Старое железо] Архитектура и программирование микрокалькулятора HP-41
- [Программирование, Разработка мобильных приложений, Учебный процесс в IT, Карьера в IT-индустрии] 1 марта SimbirSoft приглашает на Весенний интенсив
- [Интерфейсы, ReactJS, TypeScript] Код на React и TypeScript, который работает быстро. Доклад Яндекса
- [Разработка мобильных приложений, Разработка под Android] Как безболезненно мигрировать с RxJava на Kotlin Coroutines+Flow
- [Разработка веб-сайтов, JavaScript, HTML, ReactJS] React.js — формошлепство или работа с формами при помощи пользовательских хуков
- [JavaScript, Разработка мобильных приложений, Разработка игр, ReactJS] Как я разработал мобильную игру на Android с использованием React.js и выложил её в Google Play Store
- [JavaScript, Программирование, Дизайн мобильных приложений, TypeScript] Автоматизируем локализацию макетов в Figma
- [JavaScript, ReactJS] React Server Components — что это?
- [Разработка веб-сайтов, Open source, JavaScript, ReactJS, TypeScript] Что выбрать в качестве библиотеки компонентов для React-проекта
- [Программирование, ReactJS] Создание React-компонентов с помощью Hygen (перевод)
Теги для поиска: #_reactjs, #_reactnative, #_mobilnaja_razrabotka (мобильная разработка), #_kalkuljator (калькулятор), #_petproject, #_reactjs
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:26
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Приветствую. Так получилось, что последние несколько лет я занимался веб-разработкой, однако - в последнее время появилась возможность и желание попробовать себя в разработке на мобильные устройства. Причин на то было несколько, начиная от понимания того, что десктопам отводится все меньшая роль, и эта тенденция сохраняется, и заканчивая тривиальным желанием попробовать что либо новое. Кроме ого, была пара задумок для рet-проектов, которые предполагали использование возможностей мобильных платформ. Как это было и что из этого вышло - под катом <cut /> ВведениеВвиду того, что на момент планированного перехода в мобильную разработку основным инструментов разработки для меня являлся ReactJS, было принято решение начать именно с него. Кроме того, мною была использована платформа для сборки приложений Expo, которая решила существенную часть проблем с конфигурацией - сборка приложения осуществлялась буквально за несколько команд. Первым относительно серьезным(по крайней мере, работающим, а не показывающим работоспособность QuickStart`a) приложением для меня стал калькулятор - примерно такой же, как есть в каждом из смартфонов. Калькулятор должен был содержать один экран, в котором есть 2 раздела - дисплей и клавиатура, дисплей - отображает информацию, а клавиатура позволяет ее вводить Скриншоты получившегося приложения расположены под спойлером. Признаю, выглядит не как шедевр дизайна, но - не сильно хуже встроенного калькулятора. Интерес тут представляет не это Spoiler Горизонтальное отображение Вертикальное отображениеДля запуска используется онлайн-версия эмулятора, но на нескольких домашних устройствах с андроидом, а так же - в браузерной версии Экспо оно выглядит приблизительно также.Анализ исходного кода Для того, что бы приложение было по минимуму "захардкодженным" я вынес все кнопки, которые должны быть на клавиатуре в отдельный двумерный массив. При этом, ввиду того, что надпись на каждой кнопке уникальна - она же используется и в качестве id, т.е. именно по ней привязывается функция-обработчик. let labels=[
["1","2","3"], ["4","5","6"], ["7","8","9"], ["0", ".","+/-"], ["+","-","*","/"], ["ln","C", "=",] ] Аналогичным образом сделана и привязка операций к кнопкам - при этом надпись на кнопке является ключом, а функция, в моем случае стрелочная - значением. Ввиду объемности следующего объекта - уберу его под спойлер. Для взаимосвязи использовались хуки состояний - об этом упомяну чуть позже.Spoiler let functionMapping = {
"+":()=>{ setOperation(()=>(a,b)=>{return a+b}) setFirstOperand(display); setDisplay("") }, "-":()=>{ setOperation(()=>(a,b)=>{return a-b}) setFirstOperand(display); setDisplay("") }, "*":()=>{ setOperation(()=>(a,b)=>{return a*b}); setFirstOperand(display); setDisplay("") }, "/":()=>{ setOperation(()=>(a,b)=>{return a/b}); setFirstOperand(display); setDisplay(""); }, "ln":()=>{ setOperation(()=>(a,b)=>{return Math.log(a)}); setFirstOperand(display); }, "C":()=>{ setFirstOperand(""); setsecondOperand(""); setOperation(null); setDisplay(""); }, "+/-":()=>{ setDisplay((+display)*(-1)+""); }, ".":()=>{ if (display.indexOf(".")===-1) setDisplay(display+".") }, "=":()=>{ setsecondOperand(display); let rezult = operation(+firstOperand, +display); setDisplay(rezult); } } for (let i =0; i<10; i++) { functionMapping[i+""]=()=>{setDisplay(display+i)}; } setOperation(()=>(a,b)=>{return a * b})
Выглядит крайне нелогично, кроме того - ошибка, которая выбрасывается при использовании интуитивного setOperation(()=>{return ab})
Однако, в статье рассматривается данная проблема - не только ее решение, но и причины, почему это было сделано именно так. Кроме того, для числовых значений кнопок функция-хэндлер однотипна, поэтому добавление ее обработчиков вынесено в отдельный цикл.В моем проекте используются функциональные компоненты, поэтому вместо громоздких выражений с конструкторами для хранения требуемой информации используются 4 переменных состояния, одна из которых к тому же не момент релиза не используется (однако умышленно оставлена, ввиду планов на дальнейшее развитие) const [operation, setOperation] = useState(null);
const [firstOperand, setFirstOperand] = useState(""); const [secondOperand, setsecondOperand] = useState(""); const [display, setDisplay] = useState(""); На этом вся логика приложения закончилась, все что происходит дальше - лишь отображение компонентов и прикрепление таблицы стилей Прикреплю это под спойлер, кроме того, в конце статьи будет ссылка на репозиторий со всеми исходниками.SpoilerОтображение компонентов <View style={styles.root}>
<View style = {styles.display}> <Text style={{fontSize: 40}}> {display} </Text> </View> <View style={styles.keyboard}> {labels.map((value, index, array)=>{ return <View style={styles.row}> {value.map((item)=>{ return <TouchableOpacity style={styles.cell} onPress={()=>{functionMapping[item]()}}> <Text style={{fontSize: 35}}>{item}</Text> </TouchableOpacity> })} </View> })} </View> </View> const styles = StyleSheet.create({
root: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', fontSize:40 }, display:{ flex: 2, backgroundColor: "lightblue", width: "100%", justifyContent: "space-around", alignItems: "center" }, keyboard:{ flex: 9, width: "100%", backgroundColor:"lightgrey", justifyContent:"space-around", alignItems:"center" }, row:{ flex: 1, flexDirection:"row", justifyContent:"space-around", alignItems:"center", width:"100%", }, cell:{ flex:1, borderWidth:1, width:"100%", height:"100%", justifyContent:"space-around", alignItems:"center", } }); Однако тут есть несколько проблем. Большую часть времени я отлаживал приложение в браузере, запуская эмулятор андроида только перед тем как отправить на сборку релизной версии. И - возникла очень не очевидная проблема, когда один и тот же код корректно работал на веб-версии и напрочь вылетал на андроиде, не оставляя никаких логов. Методом последовательного исключения компонентов было выявлено, что проблема в компоненте Picker, который ожидал получить в качестве называния строку, а получал - число. (данный элемент не попал в релизную версию программы, но не отметить я это не мог). Кроме того, в веб-версии шрифты можно было изменять с помощью поля строкового типа, задавая ему габариты в условно любых единицах - процентах, пикселях или даже архаичных "сантиметрах", в то время как на андроиде программа требовала дать ей только число. Очень не порадовало отсутствие по умолчанию наследования свойств - нельзя было задать шрифт и выравнивание для корневого элемента, полагая, что все его потомки будут его поддерживать. С другой стороны - очень к месту приходится возможность flex разметки, которая в вебе появилась сравнительно недавно - именно с ее помощью получается получать довольно аккуратную верстку даже на довольно экстремальных соотношениях сторон. С помощью "классического" CSS, безусловно, можно сделать то же самое, но это потребует на порядок более кропотливой работы. Ну и безусловно - размер сборки получается слишком весомый. Я понимаю, что это плата за простоту написания, и на чем-либо уровня С, размер приложения будет существенно меньше, но тем не менее...ВыводыВ целом, учитывая опыт верстки на чистом Реакте, освоение основных принципов React-native заняло очень небольшое количество времени. Инструмент содержит в себе основные преимущества Реакта, однако - не клонирует его полностью, внося ряд ограничений и добавляя новые возможности. В некотором роде можно сказать, что нативный Реакт более требователен к типам, чем обычный, но если сравнивать его с React over TypeScript - различий становится еще меньше. Как мне кажется, можно сказать, что react-native может стать неплохой точкой входа в индустрию разработки мобильных приложений для лиц, имеющих опыт в вебе. P.S. Cтатья не претендует на рассмотрение как авторитетное мнение о технологии, она лишь описывает - надеюсь, объективно - первое впечатление от инструмента от человека, имеющего опыт в смежной области P.P.S Целевая аудитория статьи - не гуру веб разработки, а скорее смежники, подобные мне. Исходники =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:26
Часовой пояс: UTC + 5