翻譯 | 《JavaScript Everywhere》第22章 移動應用程序shell

翻譯 | 《JavaScript Everywhere》第22章 移動應用程序shell前端

寫在最前面

你們好呀,我是毛小悠,是一位前端開發工程師。正在翻譯一本英文技術書籍。react

爲了提升你們的閱讀體驗,對語句的結構和內容略有調整。若是發現本文中有存在瑕疵的地方,或者你有任何意見或者建議,能夠在評論區留言,或者加個人微信:code_maomao,歡迎相互溝通交流學習。git

(σ゚∀゚)σ..:*☆哎喲不錯哦github

第22章 移動應用程序shell

我妻子是一位攝影師,這意味着她的大部分生活都是基於在矩形框中構圖。在攝影中,有不少變量-物體,光線,角度,可是圖像的比例保持一致。在這種限制下,難以想象的事情發生了,塑造了咱們看待和記住周圍世界的方式。移動應用程序開發提供了相似的機會。在小巧的矩形屏幕的約束下,咱們能夠構建具備沉浸式用戶體驗的功能強大的應用程序。算法

在本章中,咱們將開始爲應用程序構建shell。爲此,咱們首先將仔細研究React Native組件的一些關鍵構建塊。而後,咱們將經過React Native的內置樣式支持以及咱們選擇的CSS-in-JS庫樣式組件,研究如何將樣式應用於咱們的應用程序。在介紹瞭如何應用樣式以後,咱們將看看如何將路由集成到咱們的應用程序中。最後,咱們將探索如何使用圖標輕鬆加強咱們的應用程序界面。shell

React Native構建塊

讓咱們先來看一下React Native應用程序的基本構建塊。你可能已經猜到React Native應用程序包含用JSX編寫的React組件。可是,若是沒有HTML頁面的DOM(文檔對象模塊),這些組件到底有什麼用?咱們可用於從src/Main.js的「 Hello World」組件開始。如今,我已經刪除了樣式:npm

import React from 'react';
import { Text, View } from 'react-native';

const Main = () => {
  return (
   <View>
    <Text>Hello world!</Text>
   </View>
  );
};

export default Main;

在此標記中,有兩個著名的JSX標籤. 。若是你有網頁開發經驗,就知道標籤與標籤的用途大體相同。它是咱們應用程序內容的容器。靠它們本身並不能作不少事,可是它們包含了咱們應用程序的全部內容,能夠相互嵌套,並能夠應用樣式。咱們的每一個組件都將包含在中。react-native

React Native中,你能夠在Web任何地方使用標籤。毫無疑問,該標籤用於包含咱們應用中的任何文本。bash

可是,與網頁不一樣,該標籤用於全部文本。咱們還能夠經過使用JSX元素來添加圖片到咱們的應用中。微信

讓咱們更新咱們的* src/Main.js *文件以包含圖像。要作到這一點,咱們從React Native導入了Image組件並使用一個有src屬性的標記(見圖22-1):

import React from 'react';
import { Text, View, Image } from 'react-native';

const Main = () => {
  return (
   <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text>Hello world!</Text>
    <Image source={require('../assets/images/hello-world.jpg')} />
   </View>
  );
};

export default Main;

前面的代碼在視圖中渲染了一些文本和圖像。你可能會注意到,咱們的標記和JSX標記是傳遞的屬性,這些屬性使咱們可以控制特定的行爲(在這種狀況下,是視圖的樣式和圖像的來源)。

將屬性傳遞給元素可使咱們擴展元素的各類附加功能。React NativeAPI文檔對每一個元素可用的屬性進行了分類。

在這裏插入圖片描述

22-1。使用<Image>標籤,咱們能夠將圖像添加到咱們的應用程序中(Windell Oskay攝)

咱們的應用程序並無作不少事情,可是在下一節中,咱們將探討如何使用React Native的內置樣式支持和樣式化組件來改善外觀。

樣式和樣式組件

做爲應用程序開發人員和設計師,咱們但願可以對應用程序進行樣式設置,能夠具備良好的外觀、感受和用戶體驗。有許多UI組件庫,例如NativeBaseReact Native Elements,一般提供了許多預約義且可自定義的組件。

這些都是值得一看的,但出於咱們的目的,讓咱們探索如何組合本身應用程序的樣式和佈局。

正如咱們已經看到的,React Native提供了一個style屬性,該屬性容許咱們將自定義樣式應用於應用程序中的任何JSX元素。樣式名稱和值與CSS的樣式名稱和值匹配,除了名稱使用camelCase編寫外,例如lineHeightbackgroundColor。讓咱們更新/src/Main.js文件,使其包含元素的某些樣式(參見圖22-2):

const Main = () => {
  return (
   <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text style={{ color: '#0077cc', fontSize: 48, fontWeight: 'bold' }}>
     Hello world!
    </Text>
    <Image source={require('../assets/images/hello-world.jpg')} />
   </View>
  );
};

22-2使用樣式咱們能夠調整<Text>元素的外觀

你可能會認爲,在元素級別應用樣式會很快變得難以維護。咱們可使用React NativeStyleSheet庫來幫助組織和重用咱們的樣式。

首先,咱們須要將StyleSheet添加到導入列表中(圖22-3):

import { Text, View, Image, StyleSheet } from 'react-native';

如今咱們能夠抽象出樣式:

const Main = () => {
  return (
   <View style={styles.container}>
    <Text style={styles.h1}>Hello world!</Text>
    <Text style={styles.paragraph}>This is my app</Text>
    <Image source={require('../assets/images/hello-world.jpg')} />
   </View>
  );
};

const styles = StyleSheet.create({
  container: {
   flex: 1,
   justifyContent: 'center'
  },
  h1: {
   fontSize: 48,
   fontWeight: 'bold'
  },
  paragraph: {
   marginTop: 24,
   marginBottom: 24,
   fontSize: 18
  }
});

彈性盒Flexbox

React Native使用CSS flexbox算法定義佈局樣式。咱們不會深刻介紹flexbox,可是React Native提供的文檔清楚地說明了flexbox及其如何在屏幕上排列元素的案例。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-z9Ipy9fi-1606433567748)(http://vipkshttp0.wiz.cn/ks/share/resources/c46f74f8-50d4-4015-8658-189fa6382bb9/3605e53d-a36d-4996-be90-cd98a055256a/index_files/3d8da063-0966-4016-892e-47d00d20fd54.jpg)]

22-3經過使用樣式表,咱們能夠縮放應用程序的樣式

樣式化的組件

儘管React Native的內置樣式屬性和StyleSheets能夠提供咱們開箱即用的全部功能,但它們遠不是咱們設計應用程序樣式的惟一選擇。

咱們還能夠利用流行的Web CSS-in-JS解決方案,例如Styled ComponentsEmotion。我認爲這些提供了更簡潔的語法,與CSS更加緊密地結合在一塊兒,並限制了Web和移動應用程序代碼庫之間所需的轉換的代碼量。使用這些啓用了Web CSS-in-JS庫也爲跨平臺共享樣式或組件創造了機會。爲了實現咱們的目的,讓咱們看一下如何使上一個示例適應使用Styled Components庫。首先,在src/Main.js中,咱們將導入庫的本機版本:

import styled from 'styled-components/native'

從這裏咱們能夠將樣式遷移到樣式化組件語法。若是已經按照了第13章的說明進行操做,則此語法應該很是熟悉。咱們的src/Main.js文件的最終代碼變爲:

import React from 'react';
import { Text, View, Image } from 'react-native';
import styled from 'styled-components/native';

const StyledView = styled.View`
  flex: 1;
  justify-content: center;
`;

const H1 = styled.Text`
  font-size: 48px;
  font-weight: bold;
`;

const P = styled.Text`
  margin: 24px 0;
  font-size: 18px;
`;

const Main = () => {
  return (
   <StyledView>
    <H1>Hello world!</H1>
    <P>This is my app.</P>
    <Image source={require('../assets/images/hello-world.jpg')} />
   </StyledView>
  );
};

export default Main;

樣式化的組件大寫

在樣式化組件庫中,元素名稱必須始終大寫。這樣,咱們如今能夠將自定義樣式應用於咱們的應用程序,並能夠選擇使用React Native的內置樣式系統或樣式化組件庫。

路由

在網頁上,咱們可使用HTML錨連接將一個HTML文檔連接到任何其餘文檔,包括咱們本身網站上的文檔。對於JavaScript驅動的應用程序,咱們使用路由將JavaScript渲染的模板連接在一塊兒。那麼移動應用程序呢?對於這些,咱們將在屏幕之間路由用戶。在本節中,咱們將探討兩種常見的路由類型:基於選項卡的導航和堆棧導航。

使用React導航的選項卡式路由

爲了執行路由,咱們將利用React Navigation庫,這是React NativeExpo團隊推薦的路由解決方案。最重要的是,它使實現帶有平臺特定的外觀通用路由模式變得很是簡單。

首先,讓咱們首先在src目錄中建立一個名爲screens的新目錄。在screens目錄中,讓咱們建立三個新文件,每一個文件包含一個很是基本的React組件。

src/screens/favorites.js中添加如下內容:

import React from 'react';
import { Text, View } from 'react-native';

const Favorites = () => {
  return (
   <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
    <Text>Favorites</Text>
   </View>
  );
};

export default Favorites;

src/screens/feed.js中添加它:

import React from 'react';
import { Text, View } from 'react-native';

const Feed = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Feed</Text>
    </View>
  );
};

export default Feed;

最後,將其添加到src/screens/mynotes.js中:

import React from 'react';
import { Text, View } from 'react-native';

const MyNotes = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>My Notes</Text>
    </View>
  );
};

export default MyNotes;

而後,咱們能夠在src/screens/index.js中建立一個新文件,用做咱們應用程序路由的根目錄。咱們將從導入初始的reactreact-navigation依賴關係開始:

import React from 'react';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';

// import screen components
import Feed from './feed';
import Favorites from './favorites';
import MyNotes from './mynotes';

導入這些依賴項後,咱們可使用React NavigationcreateBottomTabNavigator,在這三個屏幕之間建立一個標籤導航器,定義應在咱們的導航中顯示哪些React組件屏幕:

const TabNavigator = createBottomTabNavigator({
  FeedScreen: {
    screen: Feed,
    navigationOptions: {
      tabBarLabel: 'Feed',
    }
  },
  MyNoteScreen: {
    screen: MyNotes,
    navigationOptions: {
      tabBarLabel: 'My Notes',
    }
  },
  FavoriteScreen: {
    screen: Favorites,
    navigationOptions: {
      tabBarLabel: 'Favorites',
    }
  }
});

// create the app container
export default createAppContainer(TabNavigator);

最後,讓咱們更新src/Main.js文件,除了導入路由器以外什麼也不作。如今應簡化爲如下內容:

import React from 'react';
import Screens from './screens';

const Main = () => {
  return <Screens />;
};

export default Main;

經過在終端中輸入npm start命令,確保你的應用程序正在運行。如今,你應該在屏幕底部看到選項卡導航,在其中點擊選項卡會將你轉到適當的屏幕(圖22-4)。 在這裏插入圖片描述

22-4如今咱們可使用選項卡式導航在屏幕之間導航

堆棧導航

第二種路由選擇類型是堆棧導航,其中概念上將屏幕「堆疊」在一塊兒,從而使用戶能夠更深刻地瀏覽堆棧。考慮一個新聞應用程序,用戶在其中查看文章的摘要。用戶能夠點擊新聞文章標題,並在堆棧中更深刻地瀏覽到文章內容。 而後,他們能夠單擊「後退」按鈕,導航迴文章提要,或者導航到另外一個文章標題,從而更深刻地瀏覽堆棧。

在咱們的應用程序中,咱們但願用戶可以從筆記的摘要切換到筆記自己並返回。 讓咱們看看如何爲每一個屏幕實現堆棧導航。首先,讓咱們建立一個新的NoteScreen組件,它將包含堆棧中的第二個屏幕。使用最少的React Native組件在src/screens/note.js上建立一個新文件:

import React from 'react';
import { Text, View } from 'react-native';

const NoteScreen = () => {
  return (
    <View style={{ padding: 10 }}>
      <Text>This is a note!</Text>
    </View>
  );
};

export default NoteScreen;

接下來,咱們將對路由器進行更改,啓用NoteScreen組件的堆疊導航。爲此,咱們將從react-navigation-stack以及新的note.js組件導入createStackNavigator。在src/screens/index.js中,將導入內容更新以下:

import React from 'react';
import { Text, View, ScrollView, Button } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
// add import for createStackNavigator
import { createStackNavigator } from 'react-navigation-stack';

// import screen components, including note.js
import Feed from './feed';
import Favorites from './favorites';
import MyNotes from './mynotes';
import NoteScreen from './note';

經過導入咱們的庫和文件,咱們能夠實現堆棧導航功能。在咱們的路由器文件中,咱們必須告訴React Navigation哪些屏幕是「可重疊的」。對於咱們每一個選項卡式路由,咱們但願用戶可以導航到「筆記」屏幕。繼續並按以下所示定義這些堆棧:

const FeedStack = createStackNavigator({
  Feed: Feed,
  Note: NoteScreen
});

const MyStack = createStackNavigator({
  MyNotes: MyNotes,
  Note: NoteScreen
});

const FavStack = createStackNavigator({
  Favorites: Favorites,
  Note: NoteScreen
});

如今,咱們能夠更新TabNavigator來引用堆棧,而不是單個屏幕。爲此,請更新每一個TabNavigator對象中的screen屬性:

const TabNavigator = createBottomTabNavigator({
  FeedScreen: {
    screen: FeedStack,
    navigationOptions: {
      tabBarLabel: 'Feed'
    }
  },
  MyNoteScreen: {
    screen: MyStack,
    navigationOptions: {
      tabBarLabel: 'My Notes'
    }
  },
  FavoriteScreen: {
    screen: FavStack,
    navigationOptions: {
      tabBarLabel: 'Favorites'
    }
  }
});

總之,咱們的src/screens/index.js文件應以下所示:

import React from 'react';
import { Text, View, ScrollView, Button } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { createStackNavigator } from 'react-navigation-stack';

// import screen components
import Feed from './feed';
import Favorites from './favorites';
import MyNotes from './mynotes';
import NoteScreen from './note';

// navigation stack
const FeedStack = createStackNavigator({
  Feed: Feed,
  Note: NoteScreen
});

const MyStack = createStackNavigator({
  MyNotes: MyNotes,
  Note: NoteScreen
});

const FavStack = createStackNavigator({
  Favorites: Favorites,
  Note: NoteScreen
});

// navigation tabs
const TabNavigator = createBottomTabNavigator({
  FeedScreen: {
    screen: FeedStack,
    navigationOptions: {
      tabBarLabel: 'Feed'
    }
  },
  MyNoteScreen: {
    screen: MyStack,
    navigationOptions: {
      tabBarLabel: 'My Notes'
    }
  },
  FavoriteScreen: {
    screen: FavStack,
    navigationOptions: {
      tabBarLabel: 'Favorites'
    }
  }
});

// create the app container
export default createAppContainer(TabNavigator);

若是咱們在模擬器或設備上的Expo應用程序中打開應用程序,則不會發現明顯區別。這是由於咱們還沒有向堆疊導航添加連接。讓咱們更新src/screens/feed.js組件以包括一個堆疊的導航連接。

爲此,首先包括React NativeButton依賴項:

import { Text, View, Button } from 'react-native';

如今,咱們能夠包括一個按鈕,在按下該按鈕時,將導航到note.js組件的內容。咱們將傳遞組件props,其中將包含導航信息,並添加一個包含標題和onPress道具的:

const Feed = props => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Note Feed</Text>
      <Button title="Keep reading" onPress={() => props.navigation.navigate('Note')}
      />
    </View>
  );
};

這樣,咱們應該可以在屏幕之間進行導航。單擊「Feed」屏幕中的按鈕以導航至「Node」屏幕,而後單擊箭頭以返回(圖22-5)。

在這裏插入圖片描述

22-5單擊按鈕連接將導航到新屏幕,而單擊箭頭將使用戶返回上一屏幕

添加屏幕標題

添加堆棧導航器會自動在咱們的應用程序頂部添加標題欄。咱們能夠設置樣式,甚至刪除該頂部欄。如今,讓咱們在堆棧頂部的每一個屏幕上添加一個標題。爲此,咱們將在組件自己以外設置組件NavigationOptions。在src/screens/feed.js中:

import React from 'react';
import { Text, View, Button } from 'react-native';

const Feed = props => {
// component code
};

Feed.navigationOptions = {
  title: 'Feed'
};

export default Feed;

咱們能夠對其餘屏幕組件重複此過程。

src/screens/favorites.js中:

Favorites.navigationOptions = {
  title: 'Favorites'
};

src/screens/mynotes.js中:

MyNotes.navigationOptions = {
  title: 'My Notes'
};

如今,咱們每一個屏幕的頂部導航欄都將包含一個標題(圖22-6)。

在這裏插入圖片描述

22-6 navigationOptions中設置標題會將其添加到頂部導航欄

Icons

目前,咱們的導航功能已完成,但缺乏可視化組件以使用戶使用更友好。值得慶幸的是,Expo使在咱們的應用程序中包含圖標變得異常容易。咱們能夠搜索Expo提供的全部圖標expo.github.io/vector-icons。包括許多圖標集,例如Ant DesignIoniconsFont AwesomeEntypoFoundationMaterial圖標和Material Community圖標。這爲咱們提供了開箱即用的多種選擇。

讓咱們在選項卡式導航中添加一些圖標。首先,咱們必須導入咱們要使用的圖標集。在咱們的案例中,咱們將經過在src/screens/index.js中添加如下內容來使用Material Community圖標:

import { MaterialCommunityIcons } from '@expo/vector-icons';

如今,咱們想在組件中使用圖標的任何地方,均可以將其包含在JSX中,包括設置屬性,例如大小和顏色:

<MaterialCommunityIcons name="star" size={24} color={'blue'} />

咱們將圖標添加到標籤導航中。React Navigation包含一個名爲tabBarIcon的屬性,該屬性容許咱們設置圖標。咱們能夠將此做爲函數傳遞,使咱們可以設置tintColor,以便活動選項卡圖標的顏色與非活動圖標的顏色不一樣:

const TabNavigator = createBottomTabNavigator({
  FeedScreen: {
   screen: FeedStack,
   navigationOptions: {
    tabBarLabel: 'Feed',
    tabBarIcon: ({ tintColor }) => (
     <MaterialCommunityIcons name="home" size={24} color={tintColor} />
    )
   }
  },
  MyNoteScreen: {
   screen: MyStack,
   navigationOptions: {
    tabBarLabel: 'My Notes',
    tabBarIcon: ({ tintColor }) => (
     <MaterialCommunityIcons name="notebook" size={24} color={tintColor} />
    )
   }
  },
  FavoriteScreen: {
   screen: FavStack,
   navigationOptions: {
    tabBarLabel: 'Favorites',
    tabBarIcon: ({ tintColor }) => (
     <MaterialCommunityIcons name="star" size={24} color={tintColor} />
    )
   }
  }
});

這樣,咱們的選項卡式導航將顯示圖標(圖22-7)。 在這裏插入圖片描述

22-7 咱們應用程序的導航如今包括圖標

結論

在本章中,咱們介紹瞭如何構建React Native應用程序的基本組件。如今,你能夠建立組件,向其中添加樣式並在它們之間導航。但願經過此基本設置,你能夠看到React Native的驚人潛力。藉助最少的新技術,你已經能夠打造使人印象深入且專業的移動應用程序的起點。在下一章中,咱們將使用GraphQL在應用程序中包含來自API的數據。

若是有理解不到位的地方,歡迎你們糾錯。若是以爲還能夠,麻煩您點贊收藏或者分享一下,但願能夠幫到更多人。

相關文章
相關標籤/搜索