现在前端圈子最热的莫过于ReactNative。以Web的开发方式来开发Native,并且仗这facebook这个国际互联网公司做保证,这种革命性的产品都让前端coder和客户端coder都炸开了。 本文打算以ReactNative的Text标签的角度,这个最基本的标签,来带你跨入入ReactNative的世界的第一步。
如果把React Native 上的View标签对应成web的div标签,那么想把Text标签对应为web的Span标签或者P标签真是大错特错。严格来说,你应该把Text当初一个ReactNative的组件!(是的,本身就是!) Text标签在ReactNative上非常非常的常用,其属性方法,内部细节为开发者所必须掌握的。同时我们能透过Text标签,也能理解ReactNative上的一些设计理念。
这点大家应该都比较清楚,如果使用View标签输出文本,ReactNative是会直接报错的,我们必须用Text标签包起来。
// 直接编译不通过,少年 <View> Some text </View> // success <View> <Text>Some text </Text></View>
二, 关于Text的嵌套
Text元素是一种特殊的相对布局。如果Text标签嵌套Text标签,Text内层的不再是flexbox布局,而是纯文本布局。即是,内层Text元素设置长宽间距都是没有效果的。另外,一点注意的是,Text元素内层也只能是Tex元素而已,其他元素会直接编译报错。但是如果Text元素的外层嵌套元素是View的话,这时候Text元素却又是块级元素,是能够使用flexbox布局。
看官方的一个Demo:
<Text style={{marginBottom: 20}}> <Text >你的所言所行,全都闪烁着光芒,太过刺目,于是我闭上了眼睛,,,</Text> <Text style={{width:300,height:40,containerBackgroundColor:'#454545',color:'#ECD011'}}>但是内心还是无法停止对你的憧憬</Text> </Text> <View style={{marginBottom: 20}}> <Text>你的所言所行,全都闪烁着光芒,太过刺目,于是我闭上了眼睛,,,</Text> <Text style={{width: 300,height:40,containerBackgroundColor:'#454545',color:'#ECD011'}}>但是内心还是无法停止对你的憧憬</Text> </View>
可以发现,Text内嵌Text可以理解为一个大Text元素,内部的Text元素都只是用于设置独立的文本样式。其设置了containerBackgroundColor由于只能作用于块级元素,而不生效。
使用View内嵌Text,内嵌的Text元素是个正常的块级元素(两个Text元素自动换行),并且可以设置长宽。containerBackgroundColor也正常。
再来举个看个例子
<View style={{padding: 0, backgroundColor: '#454545', flexDirection: 'row'}}> <Text style={[ {backgroundColor: 'red', padding: 30, flex: 1}]}> 设置padding和flex </Text> <Text style={[ {backgroundColor: 'red', margin: 30, flex: 1}]}> 设置margin和flex </Text> </View>
可以是看出,View元素的内嵌Text设置padding,margin甚至flex都是没有问题的。
## Text的样式继承
废话不多说,我们直接看个例子。
<View style={{color: 'red'}}><Text>你好,我的父层是View</Text></View> <Text style={{color: 'red'}}><Text>你好,我的父层是Text</Text></Text>
我们可以发现,父层是Text标签的时候,样式能够进行继承的。但当父层时View的时候,却不行。 在Web上,如果我们在body标签上设置font-family,font-size,或者color等等,我们在任何一个没有覆盖这些样式的的Dom上面,是能够继承这些CSS属性的。但是在ReactNative 上是却没有这样的样式继承机制的!要想实现Web上常用的全局定义字体样式的方式,我们在最外层的View上面赋值是没有效果的。
对!只有嵌套的Text才能有font相关属性的继承能力。
## 设置全局文本样式
我们理解了Text的样式继承,及其元素嵌套对Text元素的影响。但是很快就发现了我们实际项目开发中非常常见的问题:如何设置全局文本样式?
我就不卖关子,解决方案是:“Component”+Text标签内联。
通过React的Component设计,让每一公共的文本样式定义一个Component!是的,你没有听错,为一个公共的文本样式或者一个Class定义一个Component。React框架的设计App是希望一个App就是一个大的Component,分别有各个功能模块的Component组成。而每个功能模块Component又能划分各个小的Component的,而在ReactNative的世界里,你可能需要为一段文本样式定义一个这样的Component。可见其Component划分的粒度之细。
## 为什么这样设计? For Component
我们先来另外一个问题: 为什么要设置Text标签(组件)
当浏览器尝试渲染一个text node节点,会遍历dom树的上层直到遇到有font-size的属性,然后渲染。而这个过程中,任何的dom节点都是可以有font-size属性,而Web的这种设计是方便易用性,img标签也是可以的,即使语义是不正确的。
而在ReactNative中,将严格控制这点。你必须包裹文本使用Text标签,不能使用View及其它标签组件。也是正是这一规定,我们不能在全局设置文本样式。但是我们推荐你封装一个Component来定义你的全局样式!是的,你可以设置一个MyAppText来设置全局文本样式,同时再设置一个MyTitleText,MyDescText等来设置不同组件,实现不同的样式继承问题。是的,在ReactNative上,全民组件,即使是一个Class也可以封装成一个Component,这也是react的设计思想。
这种严谨的约束的文本风格,将会产生更好的应用。
一方面,React组件设计时考虑到更加严谨的独立隔离环境,这一你的这个组件就能够在任何应用程序上应用而不带有任何依赖,包括样式。只要相信组件传递的属性是相同的,组件渲染和行为都是一样的。如果我们的文本风格按照Web上的继承关系,组件间的样式将会相互影响,而违背组件的独立性。
另一方面,这一的设计对代码实现是简单的。我们不需要遍历整个Dom树来决定要显示的每一个文本节点。文本样式继承只是在组件内部,不影响其他组件和系统本身。