游牧周记第41期
日常
阳台种菜
九层塔、冰菜、生菜、羽衣甘蓝又割了一茬。
正好在B站看到一个视频,关于吃蔬菜的危害(我是一名生物专业的学生,这就是为什么我不吃蔬菜),其实是有道理的,我懂。 当然他还有关于不吃水果等的视频。
关注
HTX Studio
虽然知道何同学很厉害,但他们在国内发布的视频我都看得不多(感觉比影视飓风强点不多)。 本周突然在Youtube看到了他的英文版,而且发音不太像AI(如果是真的,那他的English is quite good.。 现在有117万订阅,每个视频10w+播放,这是只有6个长视频的情况下,BTW,我全部看完了。 几乎所有的评论都在感叹其制作质量和内容是降维打击。 可能老外们不会注意到这些优秀的团队都来自杭州。
开发
Expo SDK 54后发生的问题
发现ThemeProvider似乎不能动态的调整了,也就是value不能变化。 还在找原因。
CLI 型 AI 开发工具
装了Claude Code和Gemini Cli,下一步还有Codex,总得用到的,先看看吧。 CC由于封号原因,先用了国内某代理,价格比官方贵一倍,还随时抽风。 Gemini Cli用Google Account的API Key连接auth,每次用之前把终端proxy调到位。 Codex还没开始,因为必须注册pro账号,还是等代理吧。 哎国内开发就是找罪受。
React Native Dimensions函数
- 问题:react native中, Dimensions.get('screen')和 Dimensions.get('window')获取的数据有何不同?
- 回答(by Kimi):
在 React Native 中,Dimensions.get('screen')
和 Dimensions.get('window')
都可以获取设备的尺寸信息,但它们返回的数据含义不同,适用于不同的场景。
✅ 一句话区别:
-
Dimensions.get('window')
:获取的是应用窗口的尺寸(不包括状态栏、导航栏等系统 UI)。 -
Dimensions.get('screen')
:获取的是整个屏幕的尺寸(包括 状态栏、导航栏等系统 UI)。
📌 举个例子(以竖屏 Android 手机为例):
表格
复制
属性 | window | screen |
---|---|---|
width | 应用可用宽度 | 屏幕总宽度 |
height | 应用可用高度(不含状态栏/导航栏) | 屏幕总高度(含状态栏/导航栏) |
⚠️ 注意事项:
-
在 iOS 上,
window
和screen
通常是一样的(除非有状态栏隐藏或特殊布局)。 -
在 Android 上,两者经常不同,尤其是有虚拟导航栏的设备。
-
如果你在做全屏布局或适配刘海屏,建议优先使用
window
,因为它反映的是应用实际可用区域。
✅ 最佳实践:
-
用
Dimensions.get('window')
来布局页面内容。 -
用
Dimensions.get('screen')
来调试或获取设备总尺寸(很少用于布局)。
🔍 示例代码:
JavaScript
复制
import { Dimensions } from 'react-native';
const window = Dimensions.get('window');
const screen = Dimensions.get('screen');
console.log('Window:', window);
console.log('Screen:', screen);
✅ 总结一句话:
window
是你能用的,screen
是你能看的。布局用window
,调试看screen
。
React Native组合样式的性能问题
由于我的个人代码最佳styling实践中,大量采用了style=[...]方式的应用,以保持一定程度的灵活性,并希望至少做到超过或与tailwindcss(NativeWind)一致的性能。
但与单一style参数比,组合会多大程度上影响性能开销呢? 问了grok。
react native 代码:
const styles=StyleSheet.create({
a: { margin: 16},
b:{ padding: 16},
c:{ margin: 16, padding: 16 }})
...
<View style={[styles.a, styles.b]}> ...
<View style={styles.c}> ...
这两种写法,性能上差距大吗?如果[...]中组合数增加呢?
在 React Native 中,使用 StyleSheet.create
定义样式并通过 style
属性应用样式时,[styles.a, styles.b]
和 styles.c
这两种写法的性能差异需要从样式合并和 渲染的机制来分析。以下是详细解答:
1. 两种写法的本质
[styles.a, styles.b]
:这是将多个样式对象组合成一个数组,React Native 会在运行时将这些样式合并为一个单一的样式对象。合并过程会按照数组中样式的顺序,后面样式的属性会覆盖前面样式的同名属性(如果有冲突)。styles.c
:这是一个单一的样式对象,React Native 直接应用这个样式,没有合并过程。
2. 性能差异分析
a. 单一样式对象(styles.c
)
- 优点:React Native 直接使用
styles.c
中的样式定义,无需额外的合并操作。样式解析和应用过程更直接,理论上性能开销最小。 - 适用场景:当样式固定且无需动态组合时,单一样式对象是性能最佳的选择。
b. 样式数组([styles.a, styles.b]
)
- 合并开销:React Native 在运行时会对样式数组进行合并,生成一个最终的样式对象。这个合并过程涉及对象属性的复制和覆盖,会有一定的性能开销。
- 开销大小:对于
[styles.a, styles.b]
这样只有两个样式的数组,合并开销非常小,在大多数情况下几乎可以忽略。React Native 的样式系统经过优化,处理少量样式的合并性能影响微乎其微。 - 动态性和灵活性:样式数组允许动态组合样式(例如根据条件添加或移除样式),这在需要动态调整 UI 的场景下非常有用。
c. 组合数增加的影响
- 如果样式数组中的组合数增加(例如
[styles.a, styles.b, styles.d, styles.e]
),合并开销会略微增加,因为需要处理更多的样式对象。 - 性能影响:
- 合并多个样式对象的时间复杂度大致是线性的,取决于样式对象的属性数量。每个样式对象的属性越多,合并过程的开销越大。
- 在实际应用中,除非样式数组非常长(例如几十个样式对象)或样式对象包含大量属性(例如几十个属性),否则性能影响通常不会明显。
- React Native 的样式系统是高效的,合并操作在 JavaScript 层执行,且最终样式会被缓存,减少重复计算。
d. 缓存与优化
- React Native 的
StyleSheet.create
创建的样式对象会被缓存,样式 ID 会被传递到原生层,避免每次都重新解析样式。 - 对于样式数组,React Native 会在第一次合并时生成一个新的样式 ID,之后的渲染会复用这个 ID,因此重复渲染的性能开销较小。
- 如果样式数组的内容是动态变化的(例如根据状态或 props 动态添加样式),每次变化都会触发新的合并操作,可能会增加少量开销。
3. 实际性能差距
- 少量样式组合(例如
[styles.a, styles.b]
):性能差距可以忽略不计。现代设备的 JavaScript 引擎和 React Native 的优化使得这种场景下的合并开销非常小。 - 大量样式组合(例如超过 10 个样式对象):性能开销会略有增加,但除非在高频渲染的场景(如 FlatList 的每一项都动态组合大量样式)或低性能设备上,否则用户难以感知到差异。
- 单一样式对象(
styles.c
):始终是最优选择,因为它避免了合并步骤,但灵活性较低。
4. 建议与最佳实践
- 优先使用单一样式对象:如果样式是固定的,尽量将所有样式定义在一个对象中(如
styles.c
),避免不必要的合并开销。 - 合理使用样式数组:当需要动态组合样式(例如根据条件应用不同样式)时,使用样式数组是合理的选择。尽量控制数组长度,避免不必要地拆分样式。
- 优化动态样式:
- 如果动态样式频繁变化,可以使用
useMemo
缓存样式数组,减少重复计算。例如:const combinedStyles = useMemo(() => [styles.a, condition ? styles.b : styles.d], [condition]);
- 避免在高频渲染组件(如 FlatList 或 SectionList 的渲染项)中使用过于复杂的动态样式组合。
- 如果动态样式频繁变化,可以使用
- 测试性能:在低端设备或复杂场景下,使用 React Native 的性能监控工具(如
Performance Monitor
或React DevTools
)测试实际性能影响。
5. 结论
[styles.a, styles.b]
和styles.c
的性能差距在大多数情况下微乎其微,特别是在样式数组较短(2-3 个样式)时。- 如果样式数组中的组合数显著增加(例如 10 个以上样式对象),合并开销会略有增加,但通常不会对用户体验产生明显影响。
- 为追求最佳性能,优先使用单一样式对象(如
styles.c
),但在需要动态性和灵活性的场景下,合理使用样式数组并配合优化手段(如useMemo
)是可接受的。
感觉和我想的差不多。 如果和tailwindcss的方式对比呢?
在 React Native 中使用 NativeWind(Tailwind CSS 的 React Native 实现)时,多个样式组合的写法(如 className="m-4 p-4 bg-blue-500"
) 与原生 React Native 的 StyleSheet.create
样式组合( 如 [styles.a, styles.b]
或 styles.c
)在性能上的处理机制有相似之处,但也有一些关键差异。以下是详细分析,针对 NativeWind 的样式组合与性能处理,并与 React Native 原生样式系统进行对比。
1. NativeWind 的样式组合机制
NativeWind 将 Tailwind CSS 的类名(如 m-4 p-4
)转换为 React Native 的样式对象。它在构建时或运行时将类名映射到对应的样式属性,生成类似于 StyleSheet.create
的样式对象,最终传递给 React Native 的原生渲染层。
-
样式组合的处理:
- 当你写
className="m-4 p-4 bg-blue-500"
,NativeWind 会解析这些类名,生成一个合并后的样式对象,类似于:{
margin: 16,
padding: 16,
backgroundColor: '#3B82F6'
} - 多个类名会被合并为单一的样式对象,类似于 React Native 的
[styles.a, styles.b]
合并过程。 - NativeWind 的样式解析通常在 JavaScript 层完成,解析后的样式对象会被缓存(通过
StyleSheet.create
或类似机制),并传递到原生层。
- 当你写
-
与 React Native 原生样式的对比:
- 相似之处:NativeWind 的样式最终会被转换为 React Native 的样式对象,性能上依赖于 React Native 的样式系统。因此,合并多个样式的开销与
[styles.a, styles.b]
的合并过程类似。 - 不同之处:NativeWind 需要额外的类名解析步骤(将字符串类名映射到样式对象),这在首次解析时会引入少量开销。React Native 的
StyleSheet.create
直接使用预定义的 JavaScript 对象,没有解析步骤。
- 相似之处:NativeWind 的样式最终会被转换为 React Native 的样式对象,性能上依赖于 React Native 的样式系统。因此,合并多个样式的开销与