-
Notifications
You must be signed in to change notification settings - Fork 2
Home
Taro 是一套遵循 React 语法规范的多端开发解决方案,但是目前当我们使用 Taro 的时候,在不同端上的开发体验还有不一致的地方,所以我们也都期待能有一套多端统一的解决方案提供,能够以最小差异的方式向开发者提供更好的开发体验。
在构建页面的时候,我们可以通过 flexbox 高效地完成页面代码,虽然并不是所有属性都可以全平台适应的,但是它在全平台都能够得到很好的支持,而且所有平台可以很容易通过它来绘制通用性很高的页面,这也就是为什么我们选择使用 flexbox 方案来完成这个跨端演示项目。
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒子模型提供最大的灵活性,任何一个容器都可以被指定为 Flex 布局。Flex 布局,可以简便、完整、响应式地实现各种页面布局,且在除了 IE 之外的浏览器上都表现良好。
尽管 Flex 布局在 web 端可以在各个浏览器端很好的适应,但是在 Taro 上使用 flexbox 去完成跨端开发之前,我们依旧还需要注意一些和常规开发中使用 flexbox 不同的要点。
在 RN 上有些属性的支持程度和对应值都是有区别的,所以我们进行了如下的整理。
- 不支持的属性: flex-flow, order
- 不支持的值: flex-wrap 属性的 wrap-reverse 值,以及 align-items 和 align-self 的 baseline 值
- flex-direction 的默认值是 column 而不是 row,这也是为什么我们添加了这个样式
.flex { display: flex; flex-direction: row; }
- align-content 属性
- 需要 rn 版本 0.58+
- 只在 flex-direction 属性为 column 或 column-reverse 时生效 (测试环境: RN V0.59.10)
- flex-basis 属性
- ScrollView 组件会导致属性失效
- 如果没有足够空间,组件不会发生收缩 (应该是设置了 flex-shrink 属性值默认为 0)
- flex 属性
- 只能为 number 类型
- 当 flex > 0 时,组件大小将与其弹性值成比例。因此,flex 设置为 2 的组件将占用空间的两倍作为 flex 设置为 1 的组件
- 当 flex = 0 时,组件根据 width 和 height 确定大小,且不会发生变化。
- 当 flex = -1 时,组件通常根据 width 和 height 确定大小。但是,如果没有足够的空间,组件将收缩到 minWidth 和 minHeight。
在项目中,我们已经将所有通用支持的方法写到 scss 文件中,如果大家需要可以直接使用我们已经提供的 flexbox 样式,按如下方法在自己全局的层级样式表中引入我们已经提供的样式。
@import 'https://raw.githubusercontent.com/NervJS/taro-flexbox/master/flexbox-demo/src/asset/flex.scss';
不同的平台如 Web、React-Native、微信小程序等各有特色,平台之间的差异很大,会导致很多额外的开发成本。那么如果我们想要完成一个多端项目该怎么做呢?
我们开始从比较容易入手的方向考虑,如果采用模块化组件或是 css-in-js 的方案去完成样式的构建会是一个好的方案么?
在目前的前端生态中,模块化组件开发会是个很棒的方案,覆盖模式下构建开箱即用的组件同时可以提供方法来覆盖样式再好不过了,但是如果放到小程序开发的模式中,这就会有个很严重的问题,那就是如果我们在层级样式表中写到的样式,是不能直接传给组件来覆盖样式的,组件和组件的隔离在不同小程序中很难被打破。
/* CustomComp.js */
export default class CustomComp extends Component {
static defaultProps = {
className: ''
}
render () {
return <View className={this.props.className}>这段文本的颜色不会由组件外的 class 决定</View>
}
}
/* MyPage.js */
export default class MyPage extends Component {
render () {
return <CustomComp className="red-text" />
}
}
/* MyPage.scss */
.red-text {
color: red;
}
如果大家尝试上述的写法,会发现 red-text 类中的样式并没有生效,那么在这种情况下我们如果考虑是使用 css-in-js 会好么?很遗憾,如果你使用它,我们将不会为这些需要运行时处理的样式补全前缀。
这两个方案都不是合适的方案,那么我们该怎么做呢?试着去打破小程序的组件限制么?我们在微信小程序官方的文档中找到 externalClasses 这个方法,可以先来尝试。
/* CustomComp.js */
export default class CustomComp extends Component {
static externalClasses = ['my-class']
render () {
return <View className="my-class">这段文本的颜色由组件外的 class 决定</View>
}
}
/* MyPage.js */
export default class MyPage extends Component {
render () {
return <CustomComp className="red-text" />
}
}
/* MyPage.scss */
.red-text {
color: red;
}
但是这也并非所有的开发平台都能够提供给开发者相关的方法,所以我们只能转换目光到另一个 addGlobalClass 方法上,这个方法不仅在所有小程序都能够支持,Taro 在 React Native 端也提供了同样的方法给大家,这样我们也可以避开 css modules 这个体验稍差的方法。
/* CustomComp.js */
export default class CustomComp extends Component {
static options = {
addGlobalClass: true
}
render () {
return <View className="red-text">这段文本的颜色由组件外的 class 决定</View>
}
}
/* 组件外的样式定义 */
.red-text {
color: red;
}
那么关于 flexbox 的知识,如果文中有遗漏的,大家可以跟着我们的项目来梳理知识,也可以到 MDN 上查看相关的文档,值得注意的是在 flexbox 布局中 justify-content 属性的 space-evenly 值和 gap 属性在 web 端通用性很低,所以并没有添加到项目中和其他的属性一起介绍。
space-evently on desktop
space-evently on mobile
gap in flex
希望这篇文章可以为你提供一些帮助。