React Native:用JavaScript开发移动应用(txt+pdf+epub+mobi电子书下载)

作者:Truong Hoang Dung

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

React Native:用JavaScript开发移动应用

React Native:用JavaScript开发移动应用试读:

前言

本书是一本介绍React Native框架的实用快速入门指南。你并不需要成为一名Objective-C的开发高手,当你阅读完这本书之后,我相信你就能够在一天时间内把自己的想法变为实际的应用,发布到Apple Store上去。

本书中你将学到的内容

• 学习如何搭建和调试一个React Native应用。

• 学习如何设计构建一个iOS应用。

• 学习如何布局iOS界面。

• 学习如何使用基本的React Native/iOS控制器和模块。

• 学习如何使用Node.js搭建你自己的API服务器。

• 学习如何在你的应用中使用SQLite数据库。

• 学习如何在应用中集成第三方库。

• 学习如何测试组件。

• 学习ReactJS的设计模式。

如何阅读本书

如果你本身就从事Web开发工作,那么这本书特别符合你的需求。书中的内容能够帮你通过React Native技术将你熟悉的Web开发理念直接应用到iOS开发中。

本书不会让你通过参考一些网站来学习枯燥的概念点,而会带你从零开始学习这些内容。在我一开始写这本书的时候,只是计划写一个电子书来说明开发应用的步骤,并且认为这样已经足够了。但是在写作的过程中,我的想法发生了改变。我发现在学习完React/React Native的理念后,自己就可以随处使用它们了,所以对学习者来说,在掌握所有的React Native技术开发自己的iOS应用之前,真正学习并理解所有的概念是非常有必要的。

有一个好消息是,Android版本的React Native也将会发布。那时候,你在本书中学到的所有东西都可以自然而然地应用到Android应用开发中了。

本书的组织结构

• 每章的开头都会介绍一个概念,帮你了解这个概念在Web开发中是如何体现的。然后我们会将这个概念过渡到React Native开发中,让你知道这个概念在React Native中如何具体体现,这个概念哪些部分做了转变,哪些没有变化,或者哪些部分被舍弃了。

• 在本书的最后,将帮你运用所有学到的知识来开发一个真实的应用。第1章安装配置新项目创建新的React Native应用程序创建步骤

在React Native的主页上,你能看到以下的内容。

配置环境要求

1. OS X:目前只有OS X中能够安装使用iOS的开发环境,并且Xcode也只能运行在Mac上。

2.最新版的Xcode开发工具:在Mac的App Store上下载就可以。

3.推荐使用Homebrew来安装node、watchman和flow。

4.使用命令行brew install node来安装node。

5.使用命令行brew install --HEAD watchman来安装watchman。我们推荐安装watchman,否则你可能会需要一个node文件来监控开发中的bug。

6.使用命令行brew install flow,如果你要使用flow的话。

快速开始

1.使用命令行npm install -g react-native-cli。

2.使用命令行react-native init AwesomeProject。

3.使用命令行cd AwesomeProject。

在新创建的文件夹AwesomeProject中:

1.使用Xcode打开AwesomeProject.xcodeproj文件并运行项目。

2.用你常用的文本编辑器打开index.ios.js文件,选中几行修改一下代码。

3.在Xcode中打开iOS模拟器,按下组合键Cmd+R(两次)重新加载应用,来观察修改的效果。

恭喜你!你刚刚已经成功地修改并运行了你的第一个React Native应用。应用程序分析

我们来仔细研究一下新创建的应用程序。

首先来看一下AwesomeProject/下都包含着什么内容:

1.文件夹AwesomeProject.xcodeproj

2.文件夹iOS

3.文件index.ios.js

4.文件夹node_modules/

5.文件package.json

为了让你能有一个全面的了解,这里会详细地说明一下运行react-native命令初始化Awesome-Project项目时都发生了什么事情。

• 新建了一个名为AwesomeProject的文件夹。

• 在这个文件夹中建立package.json文件。

• npm install --save react-native命令开始运行,这个命令安装了react-native及其依赖,这些依赖放在AwesomeProject/node_modules文件夹中。在AwesomeProjec-t/package.json中声明react-native,作为你的项目的依赖。

• 全局安装react-native CLI(react-native命令行)工具,并且将控制权交给本地的CLI工具,就是AwesomeProject/node_modules/react-native/local-cli/cli.js文件。

• 接下来执行AwesomeProject/node_modules/react-native/init.sh文件。这个文件是用来生成标准代码的脚本,比如index.ios.js、iOS文件夹中的Objective-C代码,以及Awesome-Project.xcodeproj文件夹中的Xcode项目配置。

我们已经看到,React Native是基于JavaScript的。这些JavaScript代码在index.ios.js中组成一个真实的应用。

package.json文件对于已经使用过Node.js的开发者来说并不陌生,它定义了我们项目的一些元数据。更重要的是,它声明了react-native作为我们项目的依赖。

node_modules文件夹是npm install命令进行项目初始化时生成的。它包含react-native源代码、其他的npm依赖、大量的JavaScript和Objective-C代码。

初始化进程也提供了最基本的Xcode项目定义和一些附加的Objective-C样板代码,它们允许我们在Xcode中打开一个项目并运行一个应用,而不需要任何其他的附加条件。这些本来都应该是手动完成的,但是因为包含了很多流程化的内容,而且这些内容不管我们创建什么类型的应用都是需要的,所以就可以通过react-native来简化这些步骤。

如果要将第三方库整合到React Native项目中,请在根目录下增加Podfile文件。

Podfile是一个类似于package.json的东西,它为CocoaPods做依赖管理,声明了Objective-C库的依赖。我们将在本书后面讨论更多有关它的细节。

可以看出,我们的AwesomeProject项目是一个综合的项目。它是一个Xcode项目,也是一个NPM项目。它是一个基于JavaScript的React Native应用,也包含了很多iOS胶水代码,用来让我们的JavaScript代码运行在iOS环境中。在已有的iOS应用中集成React Native

接下来我们来看一个例子,看看如何在已经存在的iOS应用中集成React Native的内容。首先建立一个简单的iOS应用

如果你已经有一个原生的iOS的应用了,则可以跳过这一步。如果你还没有现成的原生iOS应用,可以先通过Xcode来建立一个应用,步骤如下。

1.打开Xcode,选择Create a new Xcode project。

2.选择Single View Application建立一个最简单的单页面的应用,然后点击Next按钮。

3.给建立的应用命名(我命名为simpleApp),并选择要保存的目录,点击create就建立了一个最简单的应用,只不过这个应用目前并没有内容和逻辑。安装React Native

要在一个已经存在的App中集成React Native的内容,我们就需要先安装React Native。不同于之前的安装方式,我们需要通过CocoaPods来安装。CocoaPods是用于iOS/Mac开发的一个包管理工具。在下面的三种应用场景下,你可以考虑在项目中使用CocoaPods。

• 你想要将第三方库(第三方库使用了CocoaPods)整合到新创建的React Native项目中。

• 目前你的项目使用CocoaPods来管理依赖和库。

• 你想要将React Native框架添加到一个现有的项目中。

如果你还没有安装CocoaPods,运行下面这个命令来安装:sudo gem install cocoapods

注意,你需要提前安装Ruby来使用gem命令。

根据React Native官网最新的说明,它用io.js来取代了node.js。让我们按照官网的指导来进行io.js的安装和配置。如果之前安装过node.js,则先运行命令:brew unlink node

这样可以完成node的解绑。然后运行:brew install iojsbrew link iojs --force

进行io.js的安装和配置。

现在我们已经准备好使用CocoaPods了,使用CocoaPods来安装React Native吧。

1.进入到刚才那个iOS应用的文件目录,建立一个文件,命名为Podfile。在使用CocoaPods安装React Native时,Podfile相当于一个配置文件,告诉安装程序需要下载安装哪些内容。

2.在Podfile中添加如下的文本内容。 pod 'React' pod 'React/RCTText'

这两行的内容告诉CocoaPods安装命令需要下载安装的内容为React和React/RCTText (需要安装React和React中的Text组件)。同理,如果需要通过CocoaPods下载安装其他的内容,只要在Podfile中添加相应的内容就可以。

然后在终端中执行以下命令:pod install

至此,你已经成功安装了React Native。创建React Native应用

接下来创建一个React Native应用,在iOS应用文件目录下建立React Native的内容。

1.建立一个目录,例如为ReactComponent: mkdir ReactComponent

2.在ReactComponent目录中,增加index.ios.js。这个文件中的内容实际上就是我们要在iOS应用中使用的React Native的内容。代码如下: 'use strict'; var React = require('react-native'); var { Text, View } = React; var styles = React.StyleSheet.create({ container: { flex: 1, backgroundColor: 'red' } }); class SimpleApp extends React.Component { render() { return ( This is a simple application. ) } } React.AppRegistry.registerComponent('SimpleApp', () => SimpleApp);

在代码中出现的SimpleApp就是我们创建的组件的名称,我们后面会用到。将React Naitve集成到iOS应用中去

到目前为止,基本的准备工作已经完成了,下面我们来将React Native的内容集成到iOS应用中去。首先,我们要打开之前新建的那个简单的iOS应用。但是要注意一下,不是通过.xcodeproj文件来打开项目,而是通过.xcworkspace文件来打开项目。

使用Xcode打开项目以后,看一下Xcode的界面,左侧边栏如图所示。

在侧边栏的simpleApp下,有一个Main.storyboard。点击这个文件后,在界面的中部就会显示一个区域,它是一个虚拟的设备界面,我们可以在这个界面上添加类似文本框、按钮等一些组件。

在右侧边栏中,我们能看到一些内置的组件,可以通过拖动将一些组件放置到界面中。在其中找到View组件,拖动到虚拟界面中。

接下来,我们要建立一个新类,命名为UIView。它是UIView的一个子类。在Xcode中新建一个文件,选择类别为Cocoa Touch Class。

将新建的类命名为ReactView,使它作为UIView的子类。再选择存放的路径,完成文件的新建。新建完成后,自动生成两个文件:ReactView.h和ReactView.m。在视图控制器ViewControl.m中修改代码如下:#import "ViewController.h"#import "ReactView.h"@interface ViewController ()@property (weak, nonatomic) IBOutlet ReactView *reactView;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically // from a nib.}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}@end

相对于修改之前的内容,增加了“#import "ReactView.h"”和“@property (weak, nonatomic) IBOutlet ReactView *reactView; ”。这里对ReactView视图所做的管理内容就是禁用了AutoLayout。这只是一个简单的例子,在实际的项目中,你应该打开AutoLayout,并设置相应的约束。

下一步,RCTRootView要出场了。你可以这样简单地理解RCTRootView的作用,它是React Native应用的生存空间。RCTRootView对象负责加载React Native(实际上就是通过JavaScript代码完成的App)的内容并渲染出来。打开ReactView.m文件,添加以下内容:#import "ReactView.h"#import "RCTRootView.h"@implementation ReactView/*// 如果你需要自定义绘制过程,只需要覆盖 drawRect 方法就可以了。// 一个空的实现过程对性能会有影响,所以不用的话,就先注释掉了。- (void)drawRect:(CGRect)rect { // 绘制代码}*/- (void)awakeFromNib { NSString *urlString = @"http://localhost:8081/index.ios.bundle"; NSURL *jsCodeLocation = [NSURL URLWithString:urlString]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"SimpleApp" launchOptions:nil]; [self addSubview:rootView]; rootView.frame = self.bounds;}@end

内容添加完成了。打开Main.storyboard界面,选中我们之前添加的那个view,在右侧边栏中将这个view的所属类修改为ReactView。

完成这些操作后,就可以启动服务器,查看一下结果是如何显示的。

在终端中进入项目的根目录,运行下面的命令启动服务器。JS_DIR=pwd/ReactComponent; cd Pods/React; npm run start --root $JS_DIR

然后在Xcode中运行项目,在弹出的虚拟机中能看到如下页图所示的效果:

显示的红色区域内容就是我们在index.ios.js中完成的。这就说明,通过React Native完成的内容已经集成到一个原生的iOS应用中了。链接库和模块

ReactNative现在支持命令行接口(command line interface)来生成一个新的库。react-native new-library SampleModule

生成SampleModule后,你需要将SampleModule.xcproject链接到Xcode中,再将库文件夹拖动到Xcode的项目名称下就可以了。

如果你的Xcode构建失败,请参考以下几个步骤来解决:

1.从github上复制ReactNative的代码仓库。 git clone https://github.com/facebook/reactnative

2.将Examples/SampleApp文件夹复制到AwesomeProject下。 mkdir Examples/AwesomeProject cp -R Examples/SampleApp/* Examples/AwesomeProject

3.运行packager.sh来指向AwesomeProject目录。 packager/packager.sh --root=./Examples/AwesomeProject

4.在Xcode中重新打开AwesomeProject项目,再次构建。在设备上运行React Native应用

注意,在设备上运行React Native应用需要Apple开发者账号,并需要绑定设备。本书只是覆盖到了React Native的部分。

通过移动设备访问开发服务器

你可以使用开发服务器来快速迭代开发,不过如果你选择这种方式的话,你的电脑和手机必须连接在同一个无线网络中。

1.打开iOS目录下的AppDelegate.m文件。

2.把构建地址中的IP地址从localhost修改成为你的设备IP。

3.在Xcode中选择你的手机作为构建目标,点击“Build and run”按钮。

使用离线包

你也可以将所有的JavaScript代码打包到应用中。使用这种方式,测试时不需要连接开发服务器,也不用将App提交到AppStore上。

1.打开iOS/AppDelegate.m文件。

2.将注释jsCodeLocation=[[NSBundle mainBundle]…取消。

3.在终端中进入所写应用的根目录,运行react-native bundle命令。

绑定脚本支持两种参数:

• --dev:设置DEV变量的值为true。设置为true以后,会有很多的警告等调试信息。在实际的生产环境中建议设置DEV=false。

• --minify:使用UglifyJs压缩JS代码。

如果你的项目已经开发了一段时间,你的Xcode工程中有可能不包含main.jsbundle。要添加main.jsbundle,只需右击你的项目目录,选择“Add Files to…”,然后选main.jsbundle即可。

React Native到底是什么

如果你已经进行到这一步,那么要恭喜你一下了,你应该已经能够在你自己的手机上运行AwesomeProject了。现在是时候去弄清楚究竟发生了什么。

•画布(Canvas):你经常使用UIWindow类创建的窗口应用。

•画笔(Brush):使用UIViewController类在画布上绘图。

•颜料(Paint):应用中的颜料。使用画笔、颜料在画布上绘图。

对于更复杂的应用设计,你可能需要多个画笔和画布,它们按照上下级关系嵌套,来构成图形用户界面,如下图所示。

示例:// 创建 Canvasself.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen ].bounds];// 创建 BrushMyViewController *rootViewController = [[MyViewController alloc] init];rootViewController.launchOptions = launchOptions;// 在 Canvas 上使用 Brushself.window.rootViewController = rootViewController;[self.window makeKeyAndVisible];return YES;

在上面的代码中,先是使用Frame创建了一个Canvas,之后创建了Brush。然后使用rootViewController来将Brush关联到Canvas。在Brush中,你也可以创建Paint, Paint对于Brush来说是一个subView:RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AdmobTest" launchOptions:self.launchOptions];rootView.frame = CGRectMake(0, 50, viewRect.size.width, viewRect.size.height - 0);[self.view addSubview:rootView];

如果你愿意,还可以增加很多的subView。不错吧!

所以React Native实际上只是一个Paint。看看下面的代码:NSURL *jsCodeLocation;jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"SampleApp" launchOptions:self.launchOptions];

由上面的代码可以看到,定义一个新的React Native视图,只需要传递下面两个参数。

• jsCodeLocation地址:是一个React组件的本地或者远程URL地址。

• 模块的名称:你在index.ios.js文件中通过AppRegistry注册的名称。AppRegistry.registerComponent('SampleApp', () => SampleApp);

在完成React Native视图的创建后,现在你就可以使用这个视图的属性了,就好像使用其他原生的iOS视图一样。它对于你的项目来说就是Paint。练习

这一章就讲到这里了,在开始下一章的学习之前,做一个小练习吧。

练习内容

创建一个新的React Native视图,然后将这个视图放到一个视图控制器中,设置视图的背景样式为蓝色。

请尽量自己完成练习。如果你是iOS开发初学者,我建议你还是学习一些基本的Objective-C知识。

答案

首先打开Xcode并且创建两个文件:MyViewController.h和MyViewController.m。文件中的代码如下:// MyViewController.h#import #import "RCTRootView.h"@interface MyViewController : UIViewController@property (weak, nonatomic) NSDictionary *launchOptions;@end// MyViewController.m#import "MyViewController.h"@implementation MyViewController- (void)viewDidLoad{ [super viewDidLoad]; NSURL *jsCodeLocation; jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AdmobTest" launchOptions:self.launchOptions]; rootView.frame = CGRectMake(0, 50, viewRect.size.width, viewRect.size.height - 50); [self.view addSubview:rootView];}@end

现在修改SampleApp中AppDelegate.m文件的内容:#import "AppDelegate.h"#import "MyViewController.h"@implementation AppDelegate(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ //NSURL *jsCodeLocation; // 加载 JavaScript 代码,按照你自己的需求将相应的内容取消注释 /* 选项 1 * 从开发服务器加载文件,从代码仓库的根目录启动服务器: * * $ npm start * * 在设备上运行时,将 'localhost’修改成你电脑的 IP 地址。并且 * 需要确认你的电脑和 iOS 设备在同一个 Wi-Fi 网络环境中。 * jsCodeLocation = [NSURL URLWithString: @"http://localhost :8081/index.ios.bundle"]; */ /* 选项 2 * 通过磁盘中预绑定文件加载。重新生成静态包,运行命令 * * $ curl http://localhost:8081/index.ios.bundle -o main.jsbundle * * 并且将下面一行代码释放出来 * jsCodeLocation = [[NSBundle mainBundle] * URLForResource:@"main" * withExtension:@"jsbundle"]; */ RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"AwesomeProject" launchOptions:launchOptions]; self.window = [[UIWindow alloc] initWithFrame:[ UIScreen mainScreen].bounds]; // UIViewController *rootViewController = [[ UIViewController alloc] init]; /* 将上面的代码替换为 */ MyViewController *rootViewController = [[MyViewController alloc] init]; rootViewController.launchOptions = launchOptions; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES;}@end

如你所见,我注释掉了所有默认的SampleApp代码,然后添加了上面创建好的MyViewCon-troller的相关内容。试着编译并运行这个项目,你就能够理解React Native视图了。第2章Flexbox布局介绍

本章分两个部分。第一部分是介绍如何在Web中使用Flexbox布局,第二部分是介绍如何将它应用到React Native框架中。Web开发中的Flexbox布局

如果你是一个Web开发者,第一个问题应该是:

我们已经准备好使用Flexbox布局了吗?

现在,我很高兴地回答这个问题:

是的,我们已经准备好使用Flexbox了。

Flexbox是什么意思呢?

flexible(形容词):能够伸缩或很容易变化,以适应外界条件的变化。

box(名词):通用的矩形容器。

弹性盒模型(The Flexible Box Module),又叫作Flexbox,它的出现具有非常重要的意义。它挖掘了CSS盒模型基本原理,给我们提供了功能更加强大、更有用的模块布局方式。它在CSS中的定义和标记非常简单,通过媒体查询的方式就可以适配和响应变化。想象一下吧,在这样的世界中,我们不需要清除浮动,不需要使用额外的框架,也不需要使用大量冗余的代码来实现响应式栅格布局。Flexbox做了所有这些看起来略显烦琐的工作,所以我们使用起来非常简单——定义flex容器,在容器里面再定义所需的flex项目,仅此而已,如下图。Flexbox布局究竟是什么呢

CSS3的Flexible Box(或者说Flexbox)是一种布局模式,这种布局模式适用于不同的屏幕尺寸和不同的显示设备,它给页面元素提供了适配这些情况的能力。

简单来说,我们可以在一个flex容器中标记一些flex子元素,通过CSS来定义布局。Flexbox有很多属性用来定义布局,这些属性结合起来能够实现更多的效果,举例如下。

• flex-direction:通过这个属性,我们能够指定flex容器的子元素是按行显示还是按列显示。我们也可以通过这个属性来定义元素按升序显示还是按降序显示。

• justify-content:通过这个属性,可以声明浏览器如何分配元素之外的可用空间。比如有3个节点,它们组合起来一共占据了容器50%的空间,我们能够指定元素是集中在左边、右边还是中间,或者是均匀地从左往右分布,或者其他的一些方式。

• flex-wrap:通过这个属性,我们能够指定当flex子元素的总宽度超出了容器的空间时,是否换行显示。

上面提到的这些内容只是Flexbox能够提供的一小部分功能,你可以访问MDN(https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes)得到更多的指导和帮助。我鼓励你通过练习去熟悉这些功能,就不再用大量生涩的概念和描述来折磨你了。现在,我们来看看Flexbox是如何解决一些常见问题的。Flexbox教程

本教程不会涵盖到Flexbox的所有知识点,所以如果你想要了解全部知识,我建议你去阅读官方文档。相反,本教程将使用Flexbox来解决一些常见的布局问题,并展示如何快速轻松地使用它们。这些布局模式都是响应式的,能够很好地展示Flexbox的易用性。以下是我们将要实践的案例:

1.一个普通的栅格系统

2.圣杯布局

3.带有可变宽度搜索框的流式导航条

4.两种不同的垂直对齐

下面就让我们来深入了解一下吧!栅格系统

目前,栅格系统在页面的布局管理中占据了很重要的地位。默认盒模型的行为导致在布局中通常会使用float和inline-block等hacks方式来实现,这些方式都有很多人在使用。Flexbox能让我们仅仅使用很少的几行CSS代码就轻松开发出一套功能强大、可扩展的栅格系统。让我们看看怎么做吧。

在传统的栅格系统中,我们必须用某种方式说明在一行中包含有多少个内容节点,然后给每个内容节点设置相应的宽度。通过Flexbox,我们可以在一行中放任意数目的项目,而且这些项目的宽度可以根据容器宽度自动分配。换句话说,在CSS中,我们可以通过一些标记来达到目的,而不用关心一行中放置多少个内容节点,代码如下。

1
2

1
2
3

1
2
3
4

现在让我们看看CSS代码。纯粹出于美观的考虑,我在其中使用了一些附加的样式属性(比如border和padding),但是除了这些内容之外,我们所要使用到的样式属性非常简单,来看一下:.grid { border: solid 1px #e7e7e7; }.grid_row { display: flex; }.grid_item { flex: 1; padding: 12px; border: solid 1px #e7e7e7;}

这样我们就实现了一个栅格系统。.grid_row定义了一个flex的容器,每一个.sub-item的节点作为flex容器中的子元素。在.sub-item中的flex: 1使得所有的项目等宽分布在容器中。现在你可以建立很多的栅格行,每行中的项目数量不限。它们会在容器中等宽分布,你不需要增加任何其他的CSS样式了。

那么如果想要得到一个列布局该怎么做呢?如果你想让栅格容器中的项目按列来分布,只要简单地在.grid-row样式中声明flex-direction:column;就可以实现。在这种情况下,我们只做了一点修改就创建了一个简单的快速响应布局,我们修改后的样式看起来像

这样:

1
2
3
4

1
2
3
4
5
6
7

1
2
3

我们修改后的CSS代码如下:.grid { border: solid 1px #e7e7e7;}.grid__row { display: flex; flex-direction: column;}.grid__item { flex: 1; padding: 12px; border: solid 1px #e7e7e7;}@media all and ( min-width: 480px ) { .grid__row--sm { flex-direction: row; }}@media all and ( min-width: 720px ) { .grid__row--md { flex-direction: row; }}@media all and ( min-width: 960px ) { .grid__row--lg { flex-direction: row; }}

瞧,一个简单的响应式栅格系统的CSS代码只有几行。这个系统的适应性非常强,你甚至可以嵌套栅格,而不必担心它的展现不够理想,如下页图所示。

Nested 1

...

2

1

...

圣杯布局

圣杯布局在网页设计中非常著名,它在Web应用刚出现时就很出名,到今天圣杯布局依然扮演着重要角色,尤其是在内容丰富的网站中使用非常多。早在2006年,A List Apart网站就已经使用这种方式来完美实现页面布局。它利用float、margin负值和最小宽度(min-width)来确保布局不相冲突。这种方式如果要满足现有响应式布局的需求,就需要用到大量的运算、浮动清除等一些特殊的手段。如果一个场景可能需要修改侧边栏的宽度,那你就不得不借助数学运算或者其他方式来实现。

Flexbox布局能够有效地缓解这些让人头疼的问题,我们可以指定列布局或者行布局,也可以明确指定元素的分布顺序,就算不按照它们在页面中出现的顺序也可以。下面是一个典型的圣杯布局。

在我的demo中,圣杯布局是包含在一个页面文档中的,所以并没有上面出现的body标签或者main标签。我们不必关注这个,我们关心的是类名和部分标记,而不是元素本身的外观。特别是要注意用来修饰两个侧边栏的类,它们在标记中有细小的差别。让我们来仔细看看究竟发生了什么。

• 我们有一个父元素,类名为.holy-grail,在这个元素里面,有三个flex容器的子元素。这些子元素的类名分别是.holy-grail__header、holy-grail__body及.holy-grail__footer。

• 这三个元素堆叠起来,占据了容器的所有宽度,所以容器就需要指定子元素的排列方式为列布局。

• 圣杯布局的body由.holy-grail__body管理,它是一个flex子容器。它自己的子元素在较窄的屏幕中应该按照列布局,而在较宽的屏幕中应该按照行布局。

根据上面的分析,我们来建立自己的圣杯布局:.holy-grail { display: flex; flex-direction: column; } .holy-grail__header, .holy-grail__footer { flex: 0 0 100%; } .holy-grail__body { display: flex; } .holy-grail__sidebar { /* 窄屏下不显示 */ } .holy-grail__sidebar--first { order: 1; } .holy-grail__sidebar--second { order: 3; } .holy-grail__content { order: 2; } @media all and ( min-width: 720px ) { .holy-grail__body { flex-direction: row; } .holy-grail__sidebar { flex: 0 0 180px; } .holy-grail__content { flex: 1; } } @media all and ( min-width: 960px ) { .holy-grail__sidebar { flex: 0 0 240px; } }

效果如下图。这真的不能再简单了。我之前提到过断点,在这个布局中,在初始的状态(窄屏幕)下,我们设置了两个flex容器。在第一个断点的情况下,我们修改了body的flex方向,以行布局显示,使用flex属性的简写方式设置侧边栏宽度为180px。这种简写的方式能让我们同时设置flex-grow、flex-shrink属性,以及flex-basis。内容使用flex: 1来填充可用的空间。使用order属性对项目进行排序也是非常简单的。除了那些为了美观而增加的属性,其他真没什么了。之前说过,Flexbox布局的每一列默认宽度都相等。带有可变宽度搜索框的流式导航条

下一个例子很有意思,我们将构造一个全宽度、流式布局的导航。这个导航包含一个搜索框,在获取到焦点的时候会平滑过渡到更大的宽度。通过Flexbox的力量,我们能够给导航增加任意数量的导航项目而不用修改CSS,我将会添加一些额外的类名来实现希望的效果。此外,还将使用一个按钮来进行效果的切换。代码如下:

试读结束[说明:试读内容隐藏了图片]

下载完整电子书

若在网站上没有找合适的书籍,可联系网站客服获取,各类电子版图书资料皆有。

客服微信:xzh432

登入/注册
卧槽~你还有脸回来
没有账号? 忘记密码?