Преди няколко години един мой колега ми разказа за React Native. Бях много скептичен. Аргументирах, че това е просто поредната междуплатформена рамка, която никога няма да работи в реалния живот - малко знаех колко грешах.
един уникален аспект на управлението на спорта е, че косвените приходи често надвишават преките приходи
Минаха години и React Native уменията станаха много търсени. Тъй като от известно време научих нещо ново, помислих си защо не го пробвам? Днес съм огромен защитник на React Native.
Минуси:
Професионалисти:
Мога да продължавам и продължавам, но нека спрем до тук и да преминем към темата на тази публикация в блога. В тази публикация ще създам четири приложения за Android с React Native:
Както споменах по-горе, няма начин да използваме Android Studio за React Native разработка. Имаме нужда от заместител. React Native може да бъде разработен вероятно във всеки съвременен текстов редактор, наличен там (Atom, VS Code, Sublime Text, Brackets и т.н.), но тъй като идваме с Android Studio опит, любимият ми е WebStorm, създаден от същата компания. Въпреки че WebStorm е платено приложение (129 $ на година), можете да инсталирате версията му за ранен достъп. Изграждането на EAP на WebStorm е безплатно и доста стабилно. Ако предпочитате редактор, който е напълно безплатен, отидете на VS Code. Microsoft дори разработи невероятен плъгин React Native за него и работи много добре.
Предпоставки: Android SDK, Node и React Native, инсталирани на вашия компютър.
Има два начина за създаване на нов проект React Native.
react-native init AwesomeApeeScapeProject
create-react-native-app AwesomeApeeScapeProject
Ако използвате create-react-native-app
, създаденият проект ще бъде стартиран с експо. Няма да навлизам в подробности, но по същество това означава, че няма нужда да имате инсталиран Xcode, за да стартирате приложението на iOS. Също така е по-лесно клиентът да бъде винаги актуален чрез функционалността на expo.io и някои други функции. Но не можете да добавите собствен код. По този начин, ако разработвате специфична функция, може да се наложи да извадите приложение от експо и вместо това да използвате обикновен проект React Native.
Ще използвам първия метод.
Нека да стартираме проекта. Първо отворете емулатор или свържете устройството. Ако сте създали проекта с GUI на WebStorm, всичко, което трябва да направите, е да изберете конфигурация. В горния десен ъгъл на WebStorm щракнете върху падащото меню отляво на бутона Run, изберете Android и щракнете върху Run или Debug. Ако сте създали проекта с Terminal, можете или да добавите нова React Native конфигурация, или да го стартирате с помощта на Terminal:
cd AwesomeApeeScapeProject react-native run-android
Ако всичко е минало добре, ще бъдете посрещнати със следния екран:
Забележителни елементи в проекта са:
Нека създадем папка „src“ вътре в корена на проекта и преместим App.js там. Ще трябва да актуализирате index.js импортирането, за да съответства на новото местоположение на App.js.
import App from './src/App';
Изтрийте всичко в App.js и поставете този код:
import React from 'react'; import {Text} from 'react-native'; export default class App extends React.Component { render() { return ( Hello TopTal ); } }
Кодът, който поставихме, е доста ясен. Създадохме клас App
(дъщеря на React.Component
), което отменя render()
метод и връща Text
съставна част. React.Component
е основният клас за изграждане на потребителски интерфейс с помощта на JSX. export default
модификатор прави класа public
.
Вече сме готови да започнем да проектираме нашето оформление.
Flexbox
е подобно на LinearLayout
, но Flexbox
надхвърля възможностите на LinearLayout
Този фрагмент от JSX:
flex: 1
Оказва това оформление:
Докато този XML:
android:layout_width='match_parent' android:layout_height='match_parent'
Оказва това:
JSX кодът изглежда познат, а ?! Нека създадем „речник“ (или таблица за измама) за оформления, използвайки подобни на JSX и Android XML подобни.
Моля, обърнете внимание, че функционалностите не са непременно равни. Опитвам се да помогна на начинаещите React Native да разберат идеята за системата за оформление в React Native. Моля вижте официално ръководство за подробна информация.
Помислете за това свойство JSX:
flexDirection
Това е еквивалентно на това:
alignItems
Този фрагмент от JSX:
justifyContent
И този XML:
flexDirection: row',
И двете генерират този изход:
По същия начин този JSX:
works on Y axis and
И този XML:
works on X axis. Everything is mirrored for
Генерирайте това:
За да постигнем правилната позиция в контейнера, най-често ще използваме комбинация от justifyContent
, alignItems
и justifyContent
Имоти.
Този JSX:
space-around
И този XML:
space-between
Ще създаде това оформление:
Този JSX:
space-evenly
И този XML
state
Ще създаде това оформление:
Този JSX:
state
И този XML:
render()
Ще създаде това оформление:
Този JSX:
import React from 'react'; import {Button, Text, View} from 'react-native'; export default class App extends React.Component { /* Initialize state object with variable 'number' set to 0 and variable name with value of empty string */ state = {number: 0}; render() { return ( this.decrement()}/> {/* Text will be automatically updated whenever state.number has changed value */} Value = {this.state.number} this.increment()}/> ); } //Declaration of decrement function decrement() { //To update the state we need invoke this.setState //with new value for variable 'number' this.setState({number: this.state.number - 1}); } increment() { this.setState({number: this.state.number + 1}); } }
и този XML:
textView.setText('Value ' + number)
Ще създаде това оформление:
Урок, който трябва да се научи: ако имаме yarn
alignItems yarn add axios
justifyContent npm
flexDirection: колона ’- npm install axios
засяга оста Y и import React from 'react'; import { TextInput, View, Text, Image, ActivityIndicator, Platform, StyleSheet } from 'react-native'; import axios from 'axios'; TextInput = EditText, ActivityIndicator = ProgressBar Platform - Platform detecting module StyleSheet - Module for creating stylesheets and moving them away from JSX
засягат оста Y.
justifyContent: 'flex-start' | гравитация = 'старт | ляво' |
alignItems: 'flex-start' | гравитация = 'старт | ляво' |
justifyContent: 'flex-end' | гравитация = 'край | вдясно' |
alignItems: 'flex-end' | гравитация = 'край | вдясно' |
Опитайте сами. Задайте export default class App extends React.Component { }
стойност до state = {text: '', loading: false, error: null, imgUrl: null};
, TextInput
и Image
.
За актуализиране на състоянието на приложението ще използвате React’s render() { return ( //Predefined style. See below {/* returnKeyType ~ imeOptions onSubmitEditing ~ et.OnEditorActionListener */} this.setState({text})} onSubmitEditing={() => this.searchPicture()}/> {/* Render error Image component if this.state.imgUrl is not equal to null */} { this.state.imgUrl && } ); }
променлива. Всеки път, когато onChangeText={(text) => this.setState({text})} onSubmitEditing={() => this.searchPicture()} { this.state.imgUrl && }
се актуализира, EditText
се извиква.
Копирайте кода по-долу в приложението си:
TextWatcher
Ако щракнете върху бутоните DECREMENT и INCREMENT, ще видите, че текстът се актуализира автоматично за вас. Няма нужда изрично да се използва et.OnEditorActionListener
.
Функционалността на държавата е полезна по множество причини:
Сега, когато се справихме с основните положения, нека създадем нещо малко по-сложно: приложение за търсене на / r / pics. Reddit предоставя ясна крайна точка на JSON API, така че няма да се налага да ходим на странични куестове, за да получим удостоверяване, за да работи правилно.
React Native предоставя вграден API за извличане. Тъй като повечето от нас вероятно са свикнали Преоборудване и неговата лекота на използване, ние ще използваме аксиос . Можете да инсталирате аксиос чрез терминална команда
използвайки searchPicture()
(Моят предпочитан метод):
imgUrl
или използвайки this.state.imgUrl
:
0
Внос:
false
Създайте класа:
null
За инициализиране на състояние. Ще ни трябва:
undefined
Добавете JSX кода. Имаме вертикално оформление с searchPicture() { //Default state this.setState({loading: true, error: null, imgUrl: null}); axios.get('https://www.reddit.com/r/pics/search.json', { params: { //the get param map restrict_sr: 'on', //search only /r/pics limit: 1, //limit to one search item sort: 'new', //sort by creation date q: this.state.text //our search query } }).then(response => { //promise is resolved and 'then' block is triggered //set state with new values this.setState({ imgUrl: response.data.data.children[0] .data.preview.images[0].source.url, error: null, loading: false }) }).catch(error => {//Some error occurred //set error this.setState({error: error.message, loading: false, imgUrl: null}) }) }
и ActivityIndicator
компоненти.
Image
Нови неща:
{ //Separate method this.renderProgress() } {/* Render error Text component if this.state.error is not equal to null */} { this.state.error && {this.state.error} }
Първият метод работи подобно на render()
с renderProgress() { //If this.state.loading is true //return View containing a progressbar //View takes style array if (this.state.loading === true) { return ( ); } }
съставна част. Нека бъдем честни, в React Native е много по-хубаво.
Вторият метод се извиква при натискане на клавиша за връщане на клавиатурата (App
), след като задейства const styles = StyleSheet.create({ containerStyle: { flexDirection: 'column', flex: 1, //Since React Native is cross platform //let's handle both platforms. //Add top margin to fix status bar overlap marginTop: Platform.OS === 'ios' ? 20 : 0, }, textInputStyle: { marginLeft: 16, marginRight: 16, height: Platform.OS === 'ios' ? 30 : undefined } });
.
Изображението се изобразява, когато TextInput
не е null или undefined, тъй като операторът ‘&&’ не проверява за втори аргумент, ако първият вече е false.
Може би се чудите защо autoFocus={true} prop
е невярно. Е, когато се използват логически оператори в JavaScript, всичко освен ‘’ (празен низ), TextInput
, ref={ref => this.searchInput = ref}
, componentDidMount()
или componentDidMount(){ this.searchInput.focus(); }
са верни. Няма нужда от конкретна проверка.
constructor()
Ето ни. Приложението трябва да работи както се очаква сега. Въведете низ за търсене и натиснете връщане.
Тъй като нашето приложение също е готово да изобрази static _getDerivedStateFromProps_(props, state)
и грешки, трябва да добавим още малко код след render()
съставна част:
componentDidMount()
Можете да премествате компоненти за рендиране извън главния shouldComponentUpdate(nextProps, nextState)
метод също:
render()
Остават само стилове. Поставете ги извън getSnapshotBeforeUpdate(prevProps, prevState)
клас.
componentDidUpdate(prevProps, prevState, snapshot)
Вече можем да добавим още някои ощипвания като автоматично отваряне на меката клавиатура при стартиране на приложението.
Моля, обърнете внимание, че има по-лесен начин да направите render()
автоматично фокусира (componentWillUnmount()
), но в името на този пример няма да го използваме.
Добавете препратка към React.Component
с опора:
./src
И замени CardView.js
метод на жизнения цикъл по следния начин:
import React from 'react'; import {View} from 'react-native'; export default CardView = (props) => { return ( //Style will be merged from default containerStyle //and props.style. props.style attributes will override //values if parameters are same. {/* props.children contain subviews add this line if the component is container */} {props.children} ); }; const styles = { containerStyle: { borderRadius: 4, margin: 5, padding: 5, elevation: 5, shadowColor: 'black', shadowRadius: 5, shadowOpacity: 0.5, shadowOffset: {width: 0, height: 3}, backgroundColor: 'white' } };
Презаредете приложението и клавиатурата автоматично се отваря за нас.
Вече сме създали компонент, но нека да преминем през живота на компонент.
Ето потока на жизнения цикъл на React:
LoginForm
- Конструкторът винаги се извиква при стартиране на приложениетоCardView
- Обажда се преди изобразяване и след актуализация. Връща обект за актуализиране на състоянието. Върнете null, за да не актуализирате нищо.import React from 'react'; import {TextInput, Platform, Button, StyleSheet} from 'react-native'; import CardView from '../common/components/CardView'; export default class LoginForm extends React._Component _{ render() { return ( //Override default style console.log('onLoginPress')} buttonStyle={styles.buttonStyle}/> ); } } const styles = StyleSheet.create({ buttonStyle: { elevation: 5, height: 40 }, textInputStyle: { padding: 10, //Additional params to make //iOS inputs prettier ...Platform.select({ ios: { borderRadius: 2, marginTop: 5, backgroundColor: '#eeeeee' } }) } });
- Render се изисква за всеки клас на React Component. Използва се за визуализиране на View.LoginForm
- Извиква се, след като компонентът е изобразен и монтиран към дървото на изгледа.App
- Обажда се след смяна на състоянието или реквизита. Връщането по подразбиране е true след всяка актуализация на състоянието. Извиква View
ако връща true.react-navigation
- Обажда се непосредствено преди да се извърши рендиран изход.yarn
- Извиква се след представяне на нова актуализация. Не се извиква след първия npm
.axios
- Извикан точно преди компонентът да бъде демонтиран и унищожен.
Често трябва да създаваме компоненти за многократна употреба, когато работим по проекта. Има два начина за създаване на компонент:
yarn
. Този метод трябва да се използва, ако се нуждаем от методи на жизнения цикъл.Тъй като вече сме създали класове Component, нека създадем функция за този екземпляр.
Да предположим, че се нуждаем от аналог на. Създайте „обща“ папка под npm
директория.
Създаване PictureList.js:
.
import React from 'react'; import { ActivityIndicator, FlatList, Image, Text, TouchableHighlight, View } from 'react-native'; import axios from 'axios'; import CardView from '../common/CardView'; export default class PictureList extends React.Component { state = {loading: true, error: null, posts: null}; componentDidMount() { axios.get('https://www.reddit.com/r/pics.json') .then(response => { this.setState({ posts: response.data.data.children, loading: false }) }).catch(error => { this.setState({ error: error.message, loading: false }) }) } render() { return ( // FlatList ~ ListView // data - DataSource for the List // renderItem - function returns View item // keyExtractor - Unique id for items {this.state.posts && (item.data.id + '')}/>} {this.state.loading && } ); } navigateToPicture(title, url) { this.props.navigation.navigate('PicturePreview', { 'title': title, 'url': url }) } renderItem(item) { //Destructuring values from item //Read more 'ES6 destructuring' const {data} = item.item; const {title} = data; const {url} = data.preview.images[0].source; return ( //Clickable view this.navigateToPicture(title, url)}> {/Reusing our CardView/} {title} ) } }
PicturePreview.js
използвайки нашия нов import React from 'react'; import {Image} from 'react-native'; export default class PicturePreview extends React.Component { //Destructure navigation //Set title to header static _navigationOptions = ({navigation}) => ({ title: navigation.state.params.title }); render() { const {url} = this.props.navigation.state.params; return () } }
оформление:
navigationOptions
Импортирайте StackNavigation
клас в import React from 'react'; import {createStackNavigator} from 'react-navigation'; import PictureList from './components/PictureList'; import PicturePreview from './components/PicturePreview'; export default class App extends React.Component { render() { return ( ); } } //Customize the header_ const NavigationOptions = { headerTintColor: '#fff', headerStyle: { backgroundColor: '#f4511e', } }; //Create the router. const Router = createStackNavigator({ //Name the screen 'PictureList': { //Link the Component screen: PictureList, //Additional navigation options navigationOptions: { title: '/r/pics Browser', ...NavigationOptions } }, 'PicturePreview': { screen: PicturePreview, navigationOptions: NavigationOptions } }, { //Root initialRouterName: 'PictureList' } );
клас и го увийте с
|_+_|
|_+_|
Ако промените параметрите в стиловете, можете да получите нещо, което изглежда много по-хубаво.
Навигацията до различни сцени е съществена част за повечето приложения. Ще създадем приложение за браузър Reddit / r / pics.
Създаването на навигация в React Native е доста лесно.
Предпоставки
|_+_|с или
|_+_|с
|_+_|или
Нека започнем със създаването на два различни компонента.
Забележка: Повечето от кода по-долу вече трябва да са ви познати. Ще залепя целия клас.
: ще бъде автоматично извикано от React-Navigation.Сега да преминем към App.js
Забележка: В React-Navigation има много видове навигация. Днес ще се съсредоточим върху Моля, обърнете се към официалния уебсайт за подробна информация.
Както можете да видите, всичко, което трябва да направим, е да създадем навигационен рутер и да направим ап рендирайте го. Ако всичко е минало добре, ще имаме функционално приложение за браузър Reddit / r / pics.
Android:
iOS:
Откакто започнах да програмирам, имам чисто мобилен опит в разработката. Но сега мога да кодирам почти всичко с React: мобилни, настолни и уеб.
Ако решите да започнете да разработвате следващото си невероятно приложение, използвайки React Native , ще откриете, че тук и там има своите странности и някои грешки, но React Native е много функционален и идеален за повечето проекти.
Свързани: Изградете QR скенер: Урок за реагираща родна камераИнтегрирана среда за разработка или редактор на код.
Много популярни приложения използват React Native, включително Facebook, Tesla, Skype, Instagram, Uber и др.
JavaScript
Flexbox е начинът за създаване на оформления в React Native.
Накратко, нито едното, нито другото. Програмирането на код за React Native, което е JavaScript, всъщност не е компилирано в Java или Swift / Objective C. Така че все още се нуждае от JavaScript механизъм за стартиране. Потребителският интерфейс обаче използва естествени компоненти, така че е роден за потребителския интерфейс.
Да. React Native е рамка за изграждане на приложения, които имат Native UI.