标签

React Native

React Native 是一个由 Facebook 开发的开源框架,它允许开发人员使用 JavaScript 和 React 构建原生移动应用程序。它使用与 React 类似的组件和声明式的编程模型,能够为 iOS 和 Android 平台创建性能优异的用户界面。

React Native
服务端5月30日 23:22
React Native 中如何正确接入 Lottie 动画?在 React Native 里接入 Lottie,核心不是把组件渲染出来,而是把安装、资源路径、播放控制和性能边界都处理好。很多项目第一次接入能跑,后面却在 Android 缺资源、iOS 没 pod、列表卡顿、远程 JSON 加载失败上反复踩坑。建议把 Lottie 当成一种需要生命周期管理的原生视图,而不是普通图片组件。 ## 安装和基础配置 常规项目先安装 `lottie-react-native`,iOS 再执行 Pod 安装。Expo 项目要确认 SDK 版本支持的 Lottie 版本,不要随意升级到不匹配的包。动画 JSON 可以用本地 `require`,也可以远程加载;稳定性优先的启动页、支付成功、空状态动画,建议随包发布。 ```bash npm install lottie-react-native cd ios && pod install ``` ```tsx import LottieView from 'lottie-react-native'; import { useEffect, useRef } from 'react'; export function LoadingLottie() { const ref = useRef<LottieView>(null); useEffect(() => { ref.current?.play(); return () => ref.current?.reset(); }, []); return ( <LottieView ref={ref} source={require('./assets/loading.json')} autoPlay={false} loop style={{ width: 120, height: 120 }} /> ); } ``` ## 播放控制要跟页面状态绑定 `autoPlay` 很方便,但复杂页面不建议到处开。更稳的方式是用 `ref` 控制 `play`、`pause`、`reset`,并在页面不可见、弹窗关闭或列表项离屏时暂停。进度联动可以用 `progress`,但频繁从 JS 更新 progress 会有成本,手势场景要特别留意掉帧。 ```tsx function ResultAnimation({ active }: { active: boolean }) { const ref = useRef<LottieView>(null); useEffect(() => { if (active) ref.current?.play(0, 60); else ref.current?.pause(); }, [active]); return <LottieView ref={ref} source={require('./success.json')} loop={false} />; } ``` ## Android 和 iOS 的边界不完全一样 Android 更容易遇到硬件加速、图片资源目录和低端机掉帧问题;iOS 更常见的是 Pod、版本兼容和资源打包问题。不要把一端验证通过当成全端通过,尤其是包含渐变、遮罩、文本图层的动画。上线前至少用一台低端 Android 和一台旧 iPhone 跑真实页面,不要只看模拟器。 ## 推荐的组件封装 业务里可以封一层轻量组件,把尺寸、循环、错误降级和播放时机收口。这样设计更新动画时,页面不用到处改参数;如果某个版本播放器有兼容问题,也能集中降级。封装不要太厚,保留 `source`、`loop`、`onAnimationFinish` 这类常用能力即可。 ```tsx type Props = { source: object; active: boolean; size?: number }; export function AppLottie({ source, active, size = 120 }: Props) { const ref = useRef<LottieView>(null); useEffect(() => { active ? ref.current?.play() : ref.current?.pause(); }, [active]); return <LottieView ref={ref} source={source} style={{ width: size, height: size }} />; } ``` ## 远程加载要有降级和缓存 如果业务必须远程下发 JSON,至少要准备加载中占位、失败静态图和版本缓存。接口返回后不要直接相信内容可播放,可以先校验 `fr`、`op`、`layers` 等关键字段,再交给 LottieView。否则一次错误配置就可能让页面出现空白区域,用户不会知道这是动画资源坏了,只会觉得页面没做好。 缓存也要有边界。运营动画可以短缓存,关键流程动画最好随 App 版本固定,避免服务端改动影响老客户端。需要灰度时,可以把动画版本号写进配置,出现兼容问题时回滚到上一个 JSON,而不是临时发版。 ## 追问 ### 本地 JSON 和远程 JSON 应该怎么选? 本地 JSON 稳定、首屏可控,适合关键流程和无网也要展示的动画。远程 JSON 灵活,适合运营活动、节日皮肤和可灰度替换的内容,但要处理加载失败、缓存和版本回滚。取舍在于更新频率和可靠性:越关键越本地,越运营越远程。踩坑点是远程 JSON 改了字段后旧 App 播放器不兼容,结果线上动画直接空白。 ### `autoPlay` 和手动 `play()` 有什么区别? `autoPlay` 会在组件挂载后自动开始,写法简单,适合单个静态页面。手动 `play()` 可以跟页面焦点、弹窗状态、接口完成时机绑定,更适合真实业务。边界是如果组件频繁挂载卸载,`autoPlay` 可能导致动画重复从头播放,看起来像闪烁。复杂页面里宁愿多写几行生命周期控制,也不要让动画自己乱跑。 ### React Native 列表里使用 Lottie 为什么容易卡? 列表滚动时,LottieView 作为原生视图创建成本不低,多个动画同时播放会叠加解析和绘制压力。更稳的做法是默认显示静态首帧,只有选中、曝光或需要强调的 item 才播放。FlatList 参数也要控制窗口大小和初始渲染数量。取舍是视觉动感少一点,但滚动不会被动画拖垮。 ### 动态换色应该改 JSON 还是用 `colorFilters`? 如果只有少量主题色,设计导出多份 JSON 最稳,测试成本低。需要运行时跟随品牌色或暗黑模式时,可以用 `colorFilters`,但前提是图层 keypath 命名稳定。踩坑是设计改了图层名,客户端过滤器失效却不报错。边界是渐变、图片、预合成里的颜色不一定能被简单过滤器覆盖。 ### 动画不显示时应该按什么顺序排查? 先确认 JSON 能在 LottieFiles 或设计工具里正常预览,再看 RN 资源路径、包版本和平台构建日志。Android 缺图片时检查资源目录,iOS 异常时先确认 `pod install` 和 clean build。然后再排查样式尺寸,因为 `width/height` 为 0 也会让你误以为动画坏了。不要一开始就重装依赖,很多问题其实只是路径或容器尺寸。
前端2024年7月9日 23:51
如何使用React Native应用程序实现GraphQL?### 使用React Native实现GraphQL的步骤 1. **选择合适的GraphQL客户端库** 在React Native中实现GraphQL通常会使用一个客户端库,比如`Apollo Client`或者`Relay`. 这两个库都提供了丰富的功能来帮助开发者更方便地与GraphQL API交互。 **示例**:选择`Apollo Client`,因为它易于集成并且文档齐全,社区支持也非常好。 2. **设置GraphQL客户端** 安装必要的包并创建一个客户端实例,这将用于与GraphQL服务器交互。 ```bash npm install @apollo/client graphql ``` **代码示例**: ```jsx import { ApolloClient, InMemoryCache } from '@apollo/client'; const client = new ApolloClient({ uri: 'https://your-graphql-endpoint.com/graphql', cache: new InMemoryCache() }); ``` 3. **在React Native组件中使用GraphQL** 使用Apollo Client的`useQuery`、`useMutation`等Hooks来在React Native组件中获取数据或执行操作。 **代码示例**: ```jsx import { useQuery, gql } from '@apollo/client'; const GET_DATA = gql` query GetData { users { id name } } `; function MyComponent() { const { loading, error, data } = useQuery(GET_DATA); if (loading) return <Text>Loading...</Text>; if (error) return <Text>Error :(</Text>; return ( <FlatList data={data.users} keyExtractor={({ id }) => id} renderItem={({ item }) => <Text>{item.name}</Text>} /> ); } ``` 4. **处理缓存和状态管理** Apollo Client提供了内置的缓存机制,可以帮助管理应用状态与数据缓存,优化应用的响应速度和用户体验。 **代码示例**: ```jsx const client = new ApolloClient({ uri: 'https://your-graphql-endpoint.com/graphql', cache: new InMemoryCache({ typePolicies: { User: { keyFields: ["id"] } } }) }); ``` 5. **优化性能和错误处理** 利用Apollo Client的高级特性如`errorPolicy`、`fetchPolicy`等来控制数据的加载行为和错误处理逻辑。 **代码示例**: ```jsx const { loading, error, data } = useQuery(GET_DATA, { errorPolicy: 'all', fetchPolicy: 'cache-and-network' }); ``` 6. **测试和调试** 使用Apollo Client Devtools等工具可以帮助开发者更好地理解和调试GraphQL查询。 通过适当的客户端库和合理的架构设计,React Native应用可以高效地实现并使用GraphQL,从而提供丰富的数据交互和用户体验。
前端2024年7月9日 23:51
React Native 如何实现滑动菜单(抽屉)导航?在React Native中实现滑动菜单(抽屉导航)是一种常见的功能,可以让用户通过从屏幕一侧滑动来访问不同的页面或菜单选项。以下是实现这一功能的步骤,我将结合一个具体的例子来阐述。 ### 1. 安装和引入必要的库 首先,我们需要使用React Navigation库,它是React Native中最流行的导航解决方案之一。为了实现抽屉导航,我们需要安装以下几个包: ```bash npm install @react-navigation/native npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context npm install @react-navigation/drawer ``` 安装完这些必要的库后,我们需要在项目的入口文件(通常是`App.js`)中引入`react-native-gesture-handler`,确保抽屉导航和其他手势功能能够正常工作: ```javascript import 'react-native-gesture-handler'; ``` ### 2. 配置抽屉导航器 接下来,我们需要设置抽屉导航器。首先,创建一个抽屉导航容器和几个屏幕来作为菜单项: ```javascript import * as React from 'react'; import { View, Text } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createDrawerNavigator } from '@react-navigation/drawer'; function HomeScreen() { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Screen</Text> </View> ); } function NotificationsScreen() { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Notifications Screen</Text> </View> ); } const Drawer = createDrawerNavigator(); function MyDrawer() { return ( <Drawer.Navigator initialRouteName="Home"> <Drawer.Screen name="Home" component={HomeScreen} /> <Drawer.Screen name="Notifications" component={NotificationsScreen} /> </Drawer.Navigator> ); } export default function App() { return ( <NavigationContainer> <MyDrawer /> </NavigationContainer> ); } ``` 在这个例子中,我们创建了两个简单的屏幕(HomeScreen 和 NotificationsScreen),然后使用`createDrawerNavigator`来创建一个抽屉导航器。每个屏幕都被添加为抽屉的一个菜单项。 ### 3. 自定义抽屉导航的样式和行为 React Navigation提供了多种方式来自定义抽屉导航的样式和行为。例如,我们可以自定义抽屉的宽度、背景色、项目样式等: ```javascript <Drawer.Navigator drawerContentOptions={{ activeTintColor: '#e91e63', itemStyle: { marginVertical: 5 }, }} drawerStyle={{ backgroundColor: '#c6cbef', width: 240, }} > {/* screens */} </Drawer.Navigator> ``` ### 4. 整合到现有的应用中 将抽屉导航整合到已有的React Native应用中通常涉及将它设置为顶级导航器或者在特定屏幕中嵌入。确保所有的导航层次结构都遵循最佳实践,以保持代码的可维护性和性能。 通过这些步骤,你可以在React Native应用中实现一个功能丰富且响应流畅的滑动菜单(抽屉导航)。这种类型的导航非常适合提供快速访问多个导航路径的应用,如社交媒体应用、电子商务应用等。