翻译 | 《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 Native
的API
文档对每一个元素可用的属性进行了分类。
图22-1
。使用<Image
>标签,咱们能够将图像添加到咱们的应用程序中(Windell Oskay
摄)
咱们的应用程序并无作不少事情,可是在下一节中,咱们将探讨如何使用React Native
的内置样式支持和样式化组件来改善外观。
样式和样式组件
做为应用程序开发人员和设计师,咱们但愿可以对应用程序进行样式设置,能够具备良好的外观、感受和用户体验。有许多UI
组件库,例如NativeBase
或React Native Elements
,一般提供了许多预约义且可自定义的组件。
这些都是值得一看的,但出于咱们的目的,让咱们探索如何组合本身应用程序的样式和布局。
正如咱们已经看到的,React Native
提供了一个style
属性,该属性容许咱们将自定义样式应用于应用程序中的任何JSX
元素。样式名称和值与CSS
的样式名称和值匹配,除了名称使用camelCase
编写外,例如lineHeight
和backgroundColor
。让咱们更新/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 Native
的StyleSheet
库来帮助组织和重用咱们的样式。
首先,咱们须要将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 Components
和Emotion
。我认为这些提供了更简洁的语法,与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 Native
和Expo
团队推荐的路由解决方案。最重要的是,它使实现带有平台特定的外观通用路由模式变得很是简单。
首先,让咱们首先在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
中建立一个新文件,用做咱们应用程序路由的根目录。咱们将从导入初始的react
和react-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 Navigation
的createBottomTabNavigator
,在这三个屏幕之间建立一个标签导航器,定义应在咱们的导航中显示哪些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 Native
的Button
依赖项:
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 Design
,Ionicons
,Font Awesome
,Entypo
,Foundation
,Material
图标和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
的数据。
若是有理解不到位的地方,欢迎你们纠错。若是以为还能够,麻烦您点赞收藏或者分享一下,但愿能够帮到更多人。