ساخت یک اپلیکیشن چند پلتفرمی موبایل با React Native (بخش اول) — به زبان ساده
در این مقاله قصد داریم به معرفی عملی مراحل ساخت یک اپلیکیشن در کمتر از 10 روز در فریمورک React Native بپردازیم. در این راهنما مراحل ساخت این اپلیکیشن برای iOS و همچنین اندروید توضیح داده خواهد شد. اگر میخواهید اپلیکیشن نهایی را ملاحظه میکنید، در مورد نسخه iOS میتوانید به این آدرس (+) و در مورد اندروید به این نشانی (+) مراجعه کنید. دقت کنید که اپلیکیشنی که اینک در اپ استورهای فوق مشاهده میکنید نسخه 10 روزه نیست و بهروزرسانیهای زیادی روی نسخه اولیه اپلیکیشن صورت گرفته است. اپلیکیشن زمانی که در روز دهم ارائه شد، به صورت زیر بوده است:
سرآغاز
روش منطقی برای آغاز هر پروژهای، انجام طراحی اولیه به صورت کامل است؛ اما در مورد این پروژه خاص ما همه چیز را از صحبتهای اولیه بسیار مبهم در طی یک شب آغاز کردیم. در واقع حتی قصد اتمام ده روزه آن تا زمانی که روز دهم اجرای پروژه نرسیده بود، در میان نبوده است. با این حال توصیه میشود که قبل از شروع به ساخت هر اپلیکیشن، طرح اولیه هر چند بسیار سادهای در دست داشته باشید، چون این مسئله موجب صرفهجویی زیادی در زمان میشود.
نصب React
قبل از هر چیز باید بخش «Get Started» مستندات ریاکت نیتیو بروید (+). در این جا برخی موارد که باید دانلود کنید مانند Node.js معرفی شدهاند.
اکنون نوبت ایجاد پروژه رسیده است. برای این منظور دو روش وجود دارد:
- استفاده از Create React Native App
- ساخت اپلیکیشن React Native از CLI. این کار با کمک دستور react-native init AwesomeProject صورت میگیرد.
تفاوت بین این دو مسیر در مستندات ریاکت نیتیو به خوبی توضیح داده نشده است. به طور خلاصه نکته اصلی در این است که آیا از Expo استفاده میکنید یا نه. Expo یک مجموعه ابزار است که در کتابخانه create-react-native-app جای گرفته و برخی موانع را از سر راه بر میدارد؛ اما برخی موانع را نیز در بکاند در برابر ما قرار میدهد.
برای مثال ممکن است شما از ابتدا پروژه خود را با استفاده از Expo ایجاد کنید؛ اما در ادامه متوجه شوید که باید برخی کتابخانههای خاص را پیادهسازی کنید که یا پشتیبانی نمیشوند و یا تنها پشتیبانی Alpha در Expo دارند. به علاوه انتخاب نصب نسخه جدید بسیار بهتر از این است که تا حدود زیادی در پروژه پیشرفت کنیم و بعد بخواهیم تغییرهای عمدهای ایجاد کنیم.
ساختار پوشه
پس از نصب React باید فایلهای زیر را در پروژه خود داشته باشید:
در آغاز باید مقداری تمیزکاری انجام دهید:
- یک پوشه در ریشه به نام «app» ایجاد کنید.
- فایل App.js را به ریشه app انتقال دهید.
- گزاره ایمپورت فایل index.js را به صورت import App from./app/App.js بهروزرسانی کنید.
- پوشهای درون app ایجاد کنید.
- assets - ما دو پوشه در این دایرکتوری به نامهای images و animations داریم.
- components - این همان جایی است که همه کامپوننتهای اشتراکی را در آن نگهداری میکنیم.
- config - طرحبندی رنگی اپلیکیشن در فایل colors.js نگهداری میشود تا همه چیز سازگار باقی بماند.
- screens - اینها ویوهای اصلی ما هستند.
Screens
ما در اپلیکیشن خود پنج screen اصلی داریم:
- Bookcase
- Explore
- Add Book
- Lists
- Profile
ما در آغاز این موارد را با جایگذاری یک placeholder متن طراحی میکنیم.
import React, { Component } from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default class Boookcase extends Component { render() { return ( <View style={styles.container}> <Text style={styles.title}> Bookcase </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, title: { fontSize: 20, textAlign: 'center', margin: 10, } });
ناوبری
زمانی که هر پنج صفحه راهاندازی شدند، میتوانیم بخش نخست ناوبری خود را ایجاد کنیم. ما از ناوبری برگهای در بخش پایین صفحه استفاده میکنیم. ما قصد داریم از کتابخانه React Navigation استفاده کنیم. ما یک فایل router.js به ریشه پوشه app خود اضافه میکنیم و سپس چند کتابخانه نصب میکنیم:
npm install react-navigation –save
عنصرهای React Native برای آیکونها و مواردی از این دست استفاده میشود. میتوانید از دستورالعملهای نصب react-native-elements که در این صفحه ارائه شده است (+) استفاده کنید.
import React, { Component } from 'react'; import { Dimensions, Platform } from 'react-native'; import { StackNavigator, TabNavigator } from 'react-navigation'; import { Icon } from 'react-native-elements'; import Bookcase from './screens/Bookcase'; import Explore from './screens/Explore'; import AddBook from './screens/AddBook'; import Lists from './screens/Lists'; import Profile from './screens/Profile'; let screen = Dimensions.get('window'); export const Tabs = TabNavigator({ 'Bookcase': { screen: Bookcase, navigationOptions: { tabBarLabel: 'Bookcase', tabBarIcon: ({ tintColor }) => <Icon name="open-book" type="entypo" size={28} color={tintColor} /> }, }, 'Explore': { screen: Explore, navigationOptions: { tabBarLabel: 'Explore', tabBarIcon: ({ tintColor }) => <Icon name="ios-map-outline" type="ionicon" size={28} color={tintColor} /> }, }, 'Add Book': { screen: AddBook, navigationOptions: { tabBarLabel: 'Add Book', tabBarIcon: ({ tintColor }) => <Icon name="ios-add-circle-outline" type="ionicon" size={28} color={tintColor} /> }, }, 'Lists': { screen: ReadingListStack, navigationOptions: { tabBarLabel: 'Lists', tabBarIcon: ({ tintColor }) => <Icon name="list" type="entypo" size={28} color={tintColor} /> }, }, 'My Profile': { screen: Profile, navigationOptions: { tabBarLabel: 'Profile', tabBarIcon: ({ tintColor }) => <Icon name="ios-person-outline" type="ionicon" size={28} color={tintColor} /> }, }, }); export const createRootNavigator = () => { return StackNavigator( { Tabs: { screen: Tabs, navigationOptions: { gesturesEnabled: false } } }, ); };
اینک باید به نتیجهای مانند تصویر زیر رسیده باشید:
افزودن کتابها
اینک که چارچوب اصلی اپلیکیشن آماده شده است، نوبت به بخشهای سرگرمکننده رسیده است. بخش دادههای دینامیک را به سریهای بعدی این مقاله واگذار میکنیم و در این بخش از دادههای استاتیک برای ساخت لیستی از کتابها استفاده میکنیم. برای نمایش قفسه کتاب اولیه تنها از چند نوع داده به صورت شناسه، عنوان، نویسنده و تصویر شاخص استفاده میکنیم.
۵
دقت کنید که شما میتوانید و باید همه چیز را به کامپوننتهای قابل اشتراک تقسیم کنید. ما به منظور سادگی کد در برخی موارد این واقعیت را نادیده میگیریم، اما باید توجه داشته باشید که در هر حال چنین کدی در مراحل آتی نیاز به بازسازی خواهد داشت.
ما قصد داریم از کامپوننت React به نام FlatList استفاده کنیم. این یک کامپوننت زیبا است که به صورت آماده برای تعریف حلقه روی دادهها و نمایششان استفاده میشود. دلیل زیبایی این کامپوننت آن است که کارکردهای داخلی زیادی مانند بارگذاری اسکرول، عملکرد کشیدن برای رفرش و غیره دارد.
در این مرحله فایل bookcase.js ما به صورت زیر در آمده است:
import React, { Component } from 'react'; import { StatusBar, StyleSheet, FlatList, Text, View } from 'react-native'; import BookcaseItem from './BookcaseItem'; export default class Boookcase extends Component { constructor(props) { super(props); this.state = { books: [ { id: 1, title: 'Harry Potter and the Goblet of Fire', author: 'J. K. Rowling', thumbnail: 'https://covers.openlibrary.org/w/id/7984916-M.jpg' }, { id: 2, title: 'The Hobbit', author: 'J. R. R. Tolkien', thumbnail: 'https://covers.openlibrary.org/w/id/6979861-M.jpg' }, { id: 3, title: '1984', author: 'George Orwell', thumbnail: 'https://covers.openlibrary.org/w/id/7222246-M.jpg' } ] } } _renderItem = ({item}) => ( <BookcaseItem id={item.id} title={item.title} author={item.author} thumbnail={item.thumbnail} /> ); _keyExtractor = (item, index) => item.id; render() { return ( <View style={styles.container}> <StatusBar barStyle="light-content" /> <FlatList data={this.state.books} keyExtractor={this._keyExtractor} renderItem={this._renderItem} /> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5FCFF', } });
اگر دقت کرده باشید، متوجه شدهاید که ما باید فایل دیگری را نیز به نام BookcaseItem.js اضافه کنیم این فایل همان چیزی است که تابع renderItem_ ما آن را رندر میکند. فایل در این مرحله به صورت زیر در آمده است:
import React, { Component } from 'react'; import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native'; import { Icon } from 'react-native-elements'; export default class BookcaseItem extends Component { render() { return( <View style={styles.rowContainer}> <Image source={{uri: this.props.thumbnail}} style={styles.thumbnail} resizeMode="contain" /> <View style={styles.rowText}> <Text style={styles.title} numberOfLines={2} ellipsizeMode ={'tail'}> {this.props.title} </Text> <Text style={styles.author} numberOfLines={1} ellipsizeMode ={'tail'}> {this.props.author} </Text> </View> </View> ); } } const styles = StyleSheet.create({ rowContainer: { flexDirection: 'row', backgroundColor: '#FFF', height: 100, padding: 10, marginRight: 10, marginLeft: 10, marginTop: 10, borderRadius: 4, shadowOffset:{ width: 1, height: 1, }, shadowColor: '#CCC', shadowOpacity: 1.0, shadowRadius: 1 }, title: { paddingLeft: 10, paddingTop: 5, fontSize: 16, fontWeight: 'bold', color: '#777' }, author: { paddingLeft: 10, marginTop: 5, fontSize: 14, color: '#777' }, thumbnail: { flex: 1, height: undefined, width: undefined }, rowText: { flex: 4, flexDirection: 'column' } });
اکنون ما میتوانیم کتابهای خود را مشاهده کنیم:
ویرایش کتابها
با این وجود، قصد ما از ساخت این اپلیکیشن، صرفاً لیست کردن کتابها نبوده است. ما میخواهیم توانایی ویرایش این کتابها، رتبهبندی آنها و نوشتن توضیح در مورد آنها را نیز داشته باشیم. به این منظور باید یک رویداد کلیک اضافه کنیم که وقتی کسی روی یک کتاب میزند، یک صفحه جدید برای ویرایش آن باز شود و یک مسیر جدید به روتر اضافه شود.
تابع TouchableOpacity و onPress را به فایل BookcaseItem.js به صورت زیر اضافه میکنیم:
import React, { Component } from 'react'; import { StyleSheet, TouchableOpacity, Text, Image, View } from 'react-native'; import { Icon } from 'react-native-elements'; export default class BookcaseItem extends Component { _onEditBook = () => { let id = this.props.id; this.props.navigation.navigate('EditBook', {id: id}) } render() { return( <TouchableOpacity onPress={this._onEditBook}> <View style={styles.rowContainer}> <Image source={{uri: this.props.thumbnail}} style={styles.thumbnail} resizeMode="contain" /> <View style={styles.rowText}> <Text style={styles.title} numberOfLines={2} ellipsizeMode ={'tail'}> {this.props.title} </Text> <Text style={styles.author} numberOfLines={1} ellipsizeMode ={'tail'}> {this.props.author} </Text> </View> </View> </TouchableOpacity> ); } } const styles = StyleSheet.create({ rowContainer: { flexDirection: 'row', backgroundColor: '#FFF', height: 100, padding: 10, marginRight: 10, marginLeft: 10, marginTop: 10, borderRadius: 4, shadowOffset:{ width: 1, height: 1, }, shadowColor: '#CCC', shadowOpacity: 1.0, shadowRadius: 1 }, title: { paddingLeft: 10, paddingTop: 5, fontSize: 16, fontWeight: 'bold', color: '#777' }, author: { paddingLeft: 10, marginTop: 5, fontSize: 14, color: '#777' }, thumbnail: { flex: 1, height: undefined, width: undefined }, rowText: { flex: 4, flexDirection: 'column' } });
در حال حاضر قصد داریم یک فایل به نام EditBook.js به دایرکتوری app/screens اضافه کنیم و چند مکان برای نگهداری متن و همچنین دکمه بازگشت به آن بیافزاییم. در این مرحله کارکرد درست آن را بررسی میکنیم:
import React, { Component } from 'react'; import { StyleSheet, Text, View } from 'react-native'; export default class EditBook extends Component { render() { return ( <View style={styles.container}> <Text style={styles.title}> EditBook </Text> </View> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, title: { fontSize: 20, textAlign: 'center', margin: 10, } });
در ادامه در فایل router.js یک StackNavigator اضافه میکنیم. در این مرحله TabNavigator را میتوان مانند پنج کارت بازی تصور کرد که روی یک مسیر به صورت افقی در کنار هم چیده شدهاند. زمانی که StackNavigator اضافه میشود در واقع این کارتها روی آن پنج کارت قبلی قرار میگیرند و عمق ایجاد میشود.
import React, { Component } from 'react'; import { Dimensions, Platform } from 'react-native'; import { StackNavigator, TabNavigator } from 'react-navigation'; import { Icon } from 'react-native-elements'; import Bookcase from './screens/Bookcase'; import Explore from './screens/Explore'; import AddBook from './screens/AddBook'; import Lists from './screens/Lists'; import Profile from './screens/Profile'; import EditBook from './screens/EditBook'; let screen = Dimensions.get('window'); export const Tabs = TabNavigator({ 'Bookcase': { screen: Bookcase, navigationOptions: { tabBarLabel: 'Bookcase', tabBarIcon: ({ tintColor }) => <Icon name="open-book" type="entypo" size={28} color={tintColor} /> }, }, 'Explore': { screen: Explore, navigationOptions: { tabBarLabel: 'Explore', tabBarIcon: ({ tintColor }) => <Icon name="ios-map-outline" type="ionicon" size={28} color={tintColor} /> }, }, 'Add Book': { screen: AddBook, navigationOptions: { tabBarLabel: 'Add Book', tabBarIcon: ({ tintColor }) => <Icon name="ios-add-circle-outline" type="ionicon" size={28} color={tintColor} /> }, }, 'Lists': { screen: Lists, navigationOptions: { tabBarLabel: 'Lists', tabBarIcon: ({ tintColor }) => <Icon name="list" type="entypo" size={28} color={tintColor} /> }, }, 'My Profile': { screen: Profile, navigationOptions: { tabBarLabel: 'Profile', tabBarIcon: ({ tintColor }) => <Icon name="ios-person-outline" type="ionicon" size={28} color={tintColor} /> }, }, }); export const BookcaseStack = StackNavigator({ Bookcase: { screen: Bookcase, navigationOptions: ({navigation}) => ({ header: null, }), }, EditBook: { screen: EditBook, navigationOptions: ({navigation}) => ({ header: null, tabBarVisible: false, gesturesEnabled: false }), }, }); export const createRootNavigator = () => { return StackNavigator( { BookcaseStack: { screen: BookcaseStack, navigationOptions: { gesturesEnabled: false } }, Tabs: { screen: Tabs, navigationOptions: { gesturesEnabled: false } } }, { headerMode: "none", mode: "modal" } ); };
اکنون ما لیست سادهای از کتابها داریم که میتوانیم روی هر کدام کلیک کنیم و بدین ترتیب صفحه ویرایش را میبینیم و از آنجا میتوانیم با زدن دکمه بازگشت به صفحه اصلی بازگردیم. درک این الگو بسیار مهم است زیرا این همان الگویی است که در بخشهای Explorer و لیستهای در حال مطالعه اپلیکیشنمان ایجاد خواهیم کرد.
در این نوشته صرفاً مراحل مقدماتی ایجاد اپلیکیشن را معرفی کردیم؛ اما با آمادهسازی این مقدمات اینک آماده هستیم که شروع به افزودن کارکردهای واقعی به اپلیکیشن خود بکنیم. در بخشهای بعدی این سری از مقالات آموزش عملی React Native به تکمیل اپلیکیشن خود خواهیم پرداخت.
برای مطالعه بخش دوم این مطلب میتوانید از این لینک استفاده کنید:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای طراحی و توسعه پروژه های وب
- چگونه با React Native اپلیکیشن اندرویدی بنویسیم؟ — به زبان ساده
- مجموعه آموزش های پروژه محور برنامه نویسی
- ۶ روش آسان برای سرعت بخشیدن به اپلیکیشن های React Native
- آموزش React Native: توسعه سوئیچ چند اسلایدری – به زبان ساده
==
با سلام و خسته نباشید
ضمن تشکر از مطالب گرانبهاتون ، بنده میخواستم با react ی اپ درست کنم میخواستم بدونم در ابتدا چه ملزومات و پیکربندی باید انجام بشه؟
اگه میشه لطفا مراحل رو از ابتدا توضیح دهید برای مثال اندروید استودیو باید نصب بشه یا نه
ممنون
سلام ممنونم بابت متن بسیار مفیدتوون .امیدوارم که ادامه داشته باشه .ولی متاسفانه من اجرا نتونستم بگیرم چون مبتدی هست بگم اولش ولی کاش اول هر صفحه کد یه کامنت میگذاشتین برای اینکه چه فایلی هست این کد (خوانا تر و قابل فهم تر میشد)
یا گیت هاب میکردین که فایل بندی ها فولدر بندی ها خیلی راحت نمیشه فهمید باز از اونجا میشد دید که منظورتون چی هست
باز هم تشکر میکنم از مطالب مفیدتتون