翻译 | 《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的数据。

若是有理解不到位的地方,欢迎你们纠错。若是以为还能够,麻烦您点赞收藏或者分享一下,但愿能够帮到更多人。

相关文章
相关标签/搜索