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

前端毛小悠發表於2020-12-10

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

寫在最前面

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

為了提高大家的閱讀體驗,對語句的結構和內容略有調整。如果發現本文中有存在瑕疵的地方,或者你有任何意見或者建議,可以在評論區留言,或者加我的微信:code_maomao,歡迎相互溝通交流學習。

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

第22章 移動應用程式shell

我妻子是一位攝影師,這意味著她的大部分生活都是基於在矩形框中構圖。在攝影中,有很多變數-物體,光線,角度,但是影像的比例保持一致。在這種限制下,不可思議的事情發生了,塑造了我們看待和記住周圍世界的方式。移動應用程式開發提供了類似的機會。在小巧的矩形螢幕的約束下,我們可以構建具有沉浸式使用者體驗的功能強大的應用程式。

在本章中,我們將開始為應用程式構建shell。為此,我們首先將仔細研究React Native元件的一些關鍵構建塊。然後,我們將通過React Native的內建樣式支援以及我們選擇的CSS-in-JS庫樣式元件,研究如何將樣式應用於我們的應用程式。在介紹瞭如何應用樣式之後,我們將看看如何將路由整合到我們的應用程式中。最後,我們將探索如何使用圖示輕鬆增強我們的應用程式介面。

React Native構建塊

讓我們先來看一下React Native應用程式的基本構建塊。你可能已經猜到React Native應用程式包含用JSX編寫的React元件。但是,如果沒有HTML頁面的DOM(文件物件模組),這些元件到底有什麼用?我們可用於從src/Main.js的“ Hello World”元件開始。現在,我已經刪除了樣式:

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中,你可以在Web任何地方使用標籤。毫無疑問,該標籤用於包含我們應用中的任何文字。

但是,與網頁不同,該標籤用於所有文字。我們還可以通過使用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-6navigationOptions中設定標題會將其新增到頂部導航欄

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的資料。

如果有理解不到位的地方,歡迎大家糾錯。如果覺得還可以,麻煩您點贊收藏或者分享一下,希望可以幫到更多人。

相關文章