当我得知在 tailwindcss 的生态中,能够支持 React Native 时,我感觉有点激动啊!因为我确实不太喜欢 RN 中样式的语法设计。由于这种写法,我甚至都不太想开发 React Native 的项目。
直到我苦练并熟练掌握了之后 tailwindcss,我才又重新找回了对 React Native 的热情。真是不容易啊!
他默认支持的语法是这样的。样式被设计成为一个对象,然后在 style 中通过调用属性的方式写入样式。
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
const LotsOfStyles = () => {
return (
<View style={styles.container}>
<Text style={styles.red}>just red</Text>
<Text style={styles.bigBlue}>just bigBlue</Text>
<Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
<Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text>
</View>
);
};
const styles = StyleSheet.create({
container: {
marginTop: 50,
},
bigBlue: {
color: 'blue',
fontWeight: 'bold',
fontSize: 30,
},
red: {
color: 'red',
},
});
export default LotsOfStyles;
由于我接触 React Native 比较早,当时智能提示也不完善,写起来比直接写 css 痛苦多了。
现在好了,直接支持 tailwindcss 了。开发 React Native 的舒适度将会得到极大的提升。
<View className='ml-4'>
<Text className='mt-2'>Phoenix Bakepxr</Text>
<Text className='text-gray-400 text-sm mt-1'>Created an iOS App Store build.</Text>
<View className='mt-2 bg-blue-100 py-[2px] rounded-full w-24 items-center'>
<Text className='text-sm text-blue-500'>Building...</Text>
</View>
</View>
tailwindcss 无法直接支持 React Native。因为 RN 并不支持 css。tailwind 也只能将 className
编译成对应的 css 代码。
所以想要在 RN 项目中直接使用 tailwindcss 是有难度的。除此之外,React Native 项目中的元素属性也并不支持 className
。
所以要做到这个事情,必须要做一个中间的转化。好在社区中已经有比较成熟的 css-to-rn
这种类似的理念,它们可以将 css 代码转化为 React Native 样式代码,所以代码转化逻辑大概如下
StyleSheet
代码在这个逻辑之下,tw 和 uno 都有效的支持了 React Native 项目,但是 unocss 并没有一个完整的文档来说明自己支持到了什么程度。文档之所以非常重要,是因为 React Native 在样式上的基础能力和 css 相比比较薄弱,因此许多的 css 能支持的,RN 都不支持。
使用者需要基于文档去快速的辨别哪些属性得到了支持,哪些属性没有得到支持。在文档这一块,unocss 做得不是很好。
NativeWind
是一个维护得比较完善的三方库,我们可以利用它来做到在 React Native 项目中使用 tw. 它提供了对 React Native 、Expo、Next.js 等项目的支持,由于我的项目是基于 React Native CLI 创建的,因此只介绍如何在散装项目中引入,其他的大家可以在其文档中查看
https://www.nativewind.dev/v4/getting-started/react-native
首先,我们需要在项目中安装如下依赖
yarn add nativewind@^4.0.1
yarn add react-native-reanimated
yarn add tailwindcss
然后需要专门针对 iOS
的支持安装 Reanimated
的 pod 依赖
npx pod-install
依赖处理好了之后,我们需要修改配置文件。我的配置文件依次如下所示
tailwind.config.js
// tailwind.config.js
module.exports = {
content: [],
content: ["./App.{js,jsx,ts,tsx}", "./src/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {},
},
plugins: [],
}
babel.config.js
module.exports = {
presets: ['module:@react-native/babel-preset', "nativewind/babel"],
plugins: ["react-native-reanimated/plugin",]
};
metro.config.js
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const { withNativeWind } = require('nativewind/metro')
/**
* Metro configuration
* https://reactnative.dev/docs/metro
*
* @type {import('metro-config').MetroConfig}
*/
const config = mergeConfig(getDefaultConfig(__dirname), {
/* your config */
});
module.exports = withNativeWind(config, { input: './global.css' })
最后需要调整在元素中支持 className 属性,因此需要修改 ts 的声明,在项目根目录中,创建 nativewind-end.d.ts
文件
/// <reference types="nativewind/types" />
这样配置就全部搞定了,在根目录中,创建一个 global.css
文件,并写入如下代码
@tailwind base;
@tailwind components;
@tailwind utilities;
然后在项目顶层组件中引入该 css 文件
import './global.css';
配置完成之后,我们就可以在 React Native 代码中编写 tailwindcss 中,演示效果如下图所示。
然后我啪啪啪一通写,几分钟就快速的完成了如下布局。果然好用。
虽然我最终配置成功了,但是部分细节配置还是跟官方文档有一点不太一样,因此中间也经历了好几次报错,调整了细节之后才运行成功。大家在使用时,要结合自己的项目版本、我的文章、官方文档的介绍一起使用。
NativeWind 配置成功之后,我们不仅可以直接使用 tailwind,我们还可以在 RN 项目中直接使用 css。
例如我定义一个css样式
.bg-red2 {
background-color: red;
}
然后运用到组件中
这样红色的背景就直接生效了.
但是在使用时需要注意的是,RN 项目中的 css 支持是不完善,所以有的属性可能会没有效果,需要我们在使用的过程中自己鉴别。
NativeWind 文档中,详细的为我们列出了可以支持的属性与样式,因此在使用时最好是结合该文档去对照什么样的属性在 ReactNative 中是不被支持的。
文档中还提供了一些钩子函数给我们使用,例如当我们想要支持暗黑模式时,我们可以使用 setColorScheme
来切换颜色模式。
import { colorScheme, useColorScheme } from "nativewind";
// Use imperatively
colorScheme.set("dark" | "light" | "system");
export default function App() {
// Or as a hook
const { setColorScheme } = useColorScheme();
setColorScheme("dark" | "light" | "system");
}
在文档中,也为我们介绍了如何自定义配置。这里和 tailwindcss 不太一样的是,NativeWind 提供了一些平台能力,例如,针对同一个属性,我们可以在不同的平台使用不同的颜色
// tailwind.config.js
const { platformSelect } = require("nativewind/theme");
module.exports = {
theme: {
extend: {
colors: {
error: platformSelect({
ios: "red",
android: "blue",
default: "green",
}),
},
},
},
};
我们也可以使用 platformColor
获取平台本身自带的系统色
const { platformColor } = require("nativewind/theme");
module.exports = {
theme: {
extend: {
colors: {
platformRed: platformSelect({
android: platformColor("systemRed"),
web: "red",
}),
},
},
},
};
在 React Native 中支持 tailwindcss,对于前端项目架构师而言有独特的意义,因为这可以极大的提升团队的项目开发体验。并且我们可以在 React Native 项目开发与 web 项目开发中,获得一致的开发体验。
当然一定要注意的是,在项目中一定要结合项目设计规范重新指定自己的颜色与尺寸。
而且比较舒适的一点是,我们引入 NativeWind 之后,可以仅在个别页面中使用它,而无需全局替换。这是一个渐进式的升级方案。