• 移动开发
  • 跨平台
  • 前端

【免费下载链接】nativewind

The utility-first workflow you love from Tailwind CSS in your React Native applications.

项目地址: https://gitcode.com/gh_mirrors/na/nativewind
点击查看 免费下载

导读

本篇指南讲解 NativeWind(v2 版本线)中最关键的一步:完成安装与配置后,如何真正"开始编码"。围绕官方《Start Coding》文档的示例代码,我们将完整解析从 StyleSheet.create 迁移到 className 的改写过程,并补充 Babel 插件、styled() 高阶组件、TypeScript 类型与底层实现依据,让你能立即在自己的 React Native 项目中用 Tailwind 工具类编写样式。

安装完成之后:开始编码

官方文档在完成依赖安装、Tailwind 配置与 Babel 插件接入后,给出了一个简洁的结论:"Thats it 🎉 Start writing code!"——也就是说,前面所有步骤(创建项目、安装 nativewind 与 tailwindcss、初始化 tailwind.config.js、在 babel.config.js 中加入插件)做完之后,就可以直接用 className 属性写 Tailwind 工具类了,无需任何额外样板代码。

这一结论基于 NativeWind 的 Babel 插件机制:插件会在编译期自动将组件的 className 处理为原生样式,这也是它与"必须手动包裹组件"的旧方案的差异所在(后文会介绍不启用 Babel 时的替代写法)。

核心示例:从 StyleSheet 到 className 的迁移

下面这段 diff 是官方文档的核心内容,完整展示了一个 Expo 应用默认 App.js 的改写过程:

import { StatusBar } from 'expo-status-bar';
import React from 'react';
- import { StyleSheet, Text, View } from 'react-native';
+ import { Text, View } from 'react-native';

export default function App() {
  return (
-   <View style={styles.container}>
+   <View className="flex-1 items-center justify-center bg-white">
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

- const styles = StyleSheet.create({
-   container: {
-     flex: 1,
-     backgroundColor: '#fff',
-     alignItems: 'center',
-     justifyContent: 'center',
-   },
- });

这段改动里包含三个关键动作,逐一看懂它们,你就掌握了 NativeWind v2 的核心用法:

1. 移除 StyleSheet 的导入与创建

diff 中删掉了 import { StyleSheet, Text, View } from 'react-native' 中的 StyleSheet,文件末尾的 StyleSheet.create({...}) 及其 styles.container 对象也被整体删除。在 NativeWind 下,样式声明不再以 JS 对象形式集中定义,而是以工具类字符串的形式直接写在组件上。

2. 用 className 替代 style 属性

原来的 <View style={styles.container}> 改写为 <View className="flex-1 items-center justify-center bg-white">。这一行包含了 4 个 Tailwind 类:

工具类含义(对应原 StyleSheet 属性)
flex-1flex: 1
items-centeralignItems: 'center'
justify-centerjustifyContent: 'center'
bg-whitebackgroundColor: '#fff'

可以看到,原本需要 4 行声明式样式对象表达的内容,现在一行字符串即可完成,且语义与 Tailwind CSS 完全一致。

3. 仅移除样式相关的 import,组件本身不变

Text、View 仍直接从 react-native 导入,StatusBar 依旧来自 expo-status-bar。这体现了 NativeWind v2 在 Babel 插件模式下"零侵入"的特点——组件源码结构保持不变,只是样式书写方式从 style 对象切换为 className 字符串。

前置条件回顾:依赖与配置文件

_start-coding.md 假定你已完成安装配置,这里把官方快速开始文档(如 Expo 快速开始、Create React Native App 快速开始)中的步骤补全,确保上面的代码真正可运行。

安装依赖

依据 _dependencies.mdx,需要同时安装 nativewind 与 tailwindcss。其中 tailwindcss 只在构建期使用,因此作为开发依赖安装:

npm install nativewind
npm install --save-dev tailwindcss@3.3.2

或使用 Yarn:

yarn add nativewind
yarn add --dev tailwindcss@3.3.2

:::caution 版本约束 NativeWind v2 不支持 Tailwind CSS 3.3.2 以上的版本。若需使用最新版 Tailwind,官方建议升级到 NativeWind v4(对应仓库内 v4 迁移文档)。 :::

初始化并配置 Tailwind

npx tailwindcss init

然后在生成的 tailwind.config.js 中填写 content 路径,让 Tailwind 扫描到所有组件文件(将 <custom directory> 替换为实际目录,如 screens):

// tailwind.config.js
module.exports = {
- content: [],
+ content: ["./App.{js,jsx,ts,tsx}", "./<custom directory>/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

接入 Babel 插件

以 Expo 项目为例,修改 babel.config.js:

// babel.config.js
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
+   plugins: ["nativewind/babel"],
  };
};

仓库中 packages/nativewind/babel.js 的实现非常精简——它直接转发到 react-native-css-interop/babel,说明 v2 的样式编译核心由 react-native-css-interop 包承担,nativewind 包在其上封装出面向用户的 API。这也解释了为什么"无需额外样板":Babel 插件在编译期完成类名到原生样式的转换。

不使用 Babel 插件:styled() 高阶组件方案

Babel 插件的使用是可选的。官方配套片段 _start-coding-components.md 指出:如果不启用 Babel 转换,就需要用 styled 高阶组件手动包裹组件。同一个 App 的等价写法如下:

import { StatusBar } from 'expo-status-bar';
import React from 'react';
- import { StyleSheet, Text, View } from 'react-native';
+ import { Text, View as RNView } from 'react-native';
+ import { styled } from 'nativewind';

+ const View = styled(RNView)

export default function App() {
  return (
-   <View style={styles.container}>
+   <View className="flex-1 items-center justify-center bg-white">
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

- const styles = StyleSheet.create({
-   container: {
-     flex: 1,
-     backgroundColor: '#fff',
-     alignItems: 'center',
-     justifyContent: 'center',
-   },
- });

与 Babel 方案相比,区别仅在于:

  • 引入 styled 并生成 const View = styled(RNView);
  • 组件使用这个被包裹的 View,从而获得 className 能力。

两种方案的业务组件代码完全一致,因此即使最初选择手动包裹,后续接入 Babel 插件也不需改动业务代码。

深入 styled():className 与 tw 属性

依据 styled() 参考文档,styled() 是一个高阶组件(HOC),它让组件能接受 tw 或 className 属性,两者在编译后都会转成 StyleSheet 对象并通过 style prop 传入组件,语义上没有任何区别:

import { Text } from "react-native";
import { styled } from "nativewind";

const StyledText = styled(Text);

function App() {
  return (
    <>
      <StyledText tw="font-bold">Hello world.</StyledText>
      <StyledText className="font-bold">Hello world.</StyledText>
    </>
  );
}

styled() 还支持两种进阶用法:

  • 默认样式:第二个参数传入类名字符串,即可为组件提供基础样式,类似于 styled-components 的写法:
const StyledView = styled(View, 'flex-1 items-center justify-center');
const StyledText = styled(Text, 'font-bold');
  • 解析更多属性:通过 props 或 classProps 配置项,让额外的组件属性(如 react-native-svg 的 fill/stroke)也能接收工具类字符串。完整说明见 styled() 参考文档。

TypeScript 支持:一行声明启用类型提示

若项目使用 TypeScript,官方 TypeScript 文档 给出最简方案:新建 nativewind-env.d.ts 文件,写入一行 triple-slash 指令即可通过声明合并扩展 React Native 的类型:

/// <reference types="nativewind/types" />

:::caution 命名注意事项 不要将该文件命名为 nativewind.d.ts,也不要与同目录下的文件/文件夹(如存在 /app 目录时的 app.d.ts)或 node_modules 中的包名(如 react.d.ts)同名,否则 TypeScript 编译器不会拾取这些类型声明。 :::

底层原理与源码佐证

从源码结构可以印证上述流程的实际调用链:

  • Babel 插件转发:packages/nativewind/babel.js 直接 require("react-native-css-interop/babel"),即 v2 的编译期转换能力由 react-native-css-interop 提供;
  • 公共 API 出口:packages/nativewind/src/index.tsx 从 react-native-css-interop 再导出 StyleSheet、cssInterop、remapProps、vars 等能力,并导出 useColorScheme 等运行时工具,说明 nativewind 包是对底层互操作层的一层友好封装;
  • 构建期编译:依据 overview 文档,NativeWind 在应用构建阶段完成样式处理,运行时仅保留一个轻量级内核,用于按需应用响应式样式(如设备方向、深色模式变化),这也是"开始编码"后无需关心样式生成细节的原因。

小结:开始编码的三种形态

结合上述内容,完成配置后你可以用三种方式书写样式,按需选择:

  1. Babel 插件模式(推荐):直接在任何组件上写 className,无需引入额外 API;
  2. styled() 高阶组件模式:const View = styled(RNView) 后同样使用 className/tw,适合希望显式控制哪些组件接收样式、或需要 props/classProps 高级配置的场景;
  3. 条件拼接模式:在业务代码中基于状态动态拼接类名字符串(如 ["font-bold", italic && "italic"].join(" ")),再交给 className,保留完整条件逻辑能力。

无论选择哪种方式,迁移的落点都相同:删掉 StyleSheet.create,把样式语义浓缩进 Tailwind 工具类字符串中。现在,打开你的 App.js,从 flex-1 items-center justify-center bg-white 开始吧。

  • 移动开发
  • 跨平台
  • 前端

【免费下载链接】nativewind

The utility-first workflow you love from Tailwind CSS in your React Native applications.

项目地址: https://gitcode.com/gh_mirrors/na/nativewind
点击查看 免费下载
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐