React Native 浅入门 —— 结构篇

权当一个笔记,再写写或许更明白点

结构布局

说到布局,首先作为一个前端同学,我想到的是:div、p、span、section … 以及 article、header、footer…

这些非语义化的&语义化的标签,在前端的世界中,是用于按层级、按语义去实现一个可读的结构。

一个经典的 HTML 结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<header>
<nav>
<ul>
<li>首页</li>
<li>文章列表</li>
</ul>
</nav>
</header>
<section id="article-list">
<h1>文章列表</h1>
<article>
<header>
<hgroup>
<h1>title</h1>
<h2>作者</h2>
</hgroup>
</header>
<section>
<p>第一段</p>
<p>第二段</p>
</section>
<aside>
<ul>
<li>tag1</li>
<li>tag2</li>
</ul>
</aside>
</article>
...
</section>
<footer>
CopyRight
</footer>

写 HTML 的时候,我们往往是直接就设计完了这样的一个结构,一个 big picture,当然我们还是先按大块设计,再去设计细节!不过在设计结构的时候,基本一直都能看到完整的东西。

而在 React Native 中,讲究的是 Component 的复用,是不断的分层/块去编写 Component,但是只有在那个 Component 中才能看到再进一步的结构,因为往往是“你只需要使用我就好了,不需要关心我怎么显示的。”

React 也是一样,不信去看最终 React 展现到浏览器中的样子吧,还是那么一堆 div 标签,干读基本读晕。

话题转回来,我们要这么展现文章列表:

1
2
3
...
<ArticleList />
...

所以,我们需要设计个列表页:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class ArticleList extends React.Component {
...
render() {
return (
<Text>文章列表</Text>
<ListView
dataSource={this.state.datasource}
renderRow={this._renderArticle />
);
}
_renderArticle(rowData: string, sectionID: number, rowID: number) {
...
return (
<TouchableHighlight onPress={() => this._pressArticle(rowID)}>
<Article id="{articleId}" />
</TouchableHighlight>
)
}
}

在这里确定了:我要以 ListView 的方式展现列表,点击的时候,使用 Article 的视图展现内容。

所以还需要写个 Article(在写的时候直接按全屏搞的,导航什么的留给 Navigator 搞定,我才不管。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Article extends React.Component {
render() {
return (
<View style="{articleStyles.header}">
<View styles="{articleStyles.title}">
<Text>title</Text>
</View>
<ArticleAuthor name="Leo" />
</View>
<View style="{articleStyles.content}">
<Text>第一段</Text>
<Text>第二段</Text>
</View>
<View style="{articleStyles.aside}">
<ArticleTags />
</View>
);
}
}

这样的过程,导致我们不能对当前的视图有一个像 HTML 那样的总览,看到的永远是块,而不是结构。而且由于 App 的场景专注性是极强的,所以它实际上更多的是 Navigator 式的浏览,而不是像 Web 大多数时候都要展现一个完整的 Nav 放在那里。

所以在文章列表后,点击展现 Article 的时候,我们使用 navigator 提供了一个返回按钮(最多再提供上一篇、下一篇),不需要再提供 Nav 了,而且这些都跟 Article 没啥关系,Article 只关注自己要展现的东西,而且以全屏的方式展现。

事实上很多 Web 站点也开始使用这种方式了。

这样的好处是,独立性很强,复用性也很强。坏处是:如果你“查看元素”,只会吐槽什么鬼东西!

不过思路是 OK 的,不过说实话我更喜欢 webcomponents,这样的结构看起来不是更好么?基本也是一个玩路

webcomponents 理念下的一个 DOM 结构

标签映射

已经存在的基础映射

如图所示:当前 React Native 提供的跟基础 HTML 元素相关的Component(默认0.8-stable)

缺了那么多的标签,让被惯坏了的前端怎么玩……

别的还好,View 和 Text 这两个东西,基本就要冒充很多标签的行为了:

先说Text

在 React Native 的世界中,只有一种文本标记:Text。只要你要显示文字,就必须放在 Text 标签中,没的商量。

所以 Text 对于前端同学来说,就约等于 p、div、h1~h6、section、span 等等标签,先吐会儿……

标题基本就是:

1
<Text style="{某个styles.title}">标题内容</Text>

段落可能就是:

1
<Text style="{某个styles.paragraph}">标题内容</Text>

我们还是更细一些,在 Web 的世界中,文本可能为(不会出现在移动领域的就不提了,例如鼠标悬浮的 title):

Text Types

不是简单的一一对应的关系,可能需要不断的组合。并且在 Web 中重新实现 UI 的方式,在这里依然存在,所以有可能对应的就是某个你自行实现的或者引用自外部库的 Component。

在 React Native 中,文本是信息,所以一个 Text 就够了,将文本的组合,或许引入交互,或许引入图片等等 视为 Component,转到组件的世界里去玩,而不是平铺的画板上直接画内容。

再说View

在 React Native 中,View 是最基本的视图:
View is a container that supports layout with flexbox, style, some touch handling, and accessibility controls, and is designed to be nested inside other views and to have 0 to many children of any type

所以其实所有的 视图Component 最终都是一个 View 而已。

所以从基础元素的角度来说:View 当前对于我们来说,约等于 div、section 等等所有跟布局相关的元素。

尼玛要用盒模型?要用 flexbox?用 View 吧,还支持无限嵌套的。同时作为容器,全局的行为神马的都往 View 身上扔吧,我就是新的 div,那个爆炸扩散嵌套的 div!

UI 控件

这时候,来说一下 UI 控件,就是在 Web 届很喜欢搞的东东,先看已经提供了的:
当前 React Native 提供的 ui Component(默认0.8-stable)

当然我们可以把基础的 View 和 Text 砍掉后剩下的东西也视为 ui 控件。

Web 届的 UI 种类如此之多,但我们可以庆幸的是,在 APP 中,解决了一个大问题:控件交互的各异性。APP 中是普适性的 UI 交互,就这一种,都这么用,不用去实现什么3、4、5、6种日历控件神马的了。

在 React Native 中,需要不断的根据需求进行可复用性评估,然后不断的开发出 ui Component、业务 Component、通用 Component 等等,因为我的 APP 就是用这些 Component 拼出来的视图!

而这么多自行定义的 Component,你说你不搞各异性体验的 UI??

还有呢

  1. 怎么画图?Canvas 木有了,怎么搞手势解锁呢?
    直接 View 拼接?直接调用 Native 的组件?还是像 lwansbrough/react-native-canvas 现在占位用 WebView 内嵌个 Canvas?还是自行实现一个 Canvas To UIView 绘图的东西?
    我想要的是一个通用的东西,写一个 SwipeUnlocker 出来,是期望 Web、M 站、APP 上都直接可用的,哪个解决方案能满足呢?

2015-08-24 更新
绘图可使用:ReactART,位置:Libraries/ART/ReactNativeART.js

1
2
3
4
5
6
7
8
9
10
11
12
var ReactART = {
LinearGradient: LinearGradient,
RadialGradient: RadialGradient,
Pattern: Pattern,
Transform: Transform,
Path: Path,
Surface: Surface,
Group: Group,
ClippingRectangle: ClippingRectangle,
Shape: Shape,
Text: Text,
};

例子可暂时查看 https://github.com/reactjs/react-page/blob/art/

关于绘图,再单独记录一篇笔记罢:[React Native 浅入门 —— 绘图篇]

  1. Form 没有了,不过还有 tcomb-form-native,不过这东西的使用模式需要适应下……

  2. WebView 有多大的性能问题呢?

  3. 当前来说 OC <-> JS 的 Component 映射是不是还是主流模式?