react-native学习笔记——ViewStack组件
今天来写一个组件,相信很多人都会用到的——ViewStack。
ViewStack组件无疑是UI中很重要的一个组件,可惜react-native并没有内嵌进去,需要开发者自己去实现。
实现原理很简单,就是根据索引来显示一个子视图,用一个render即可完成:
1 render(){ 2 return( 3 <View> 4 {this.props.children[this.props.index]} 5 </View> 6 ); 7 }
这样,一个最简单的ViewStack就完成了,那怎么使用呢:
1 <ViewStack index={this.state.tabIndex}> 2 <PageSNS/> 3 <PageGroup/> 4 <PageLibrary/> 5 <PageChat/> 6 <PageProfile/> 7 </ViewStack>
通过修改state的tabIndex来切换子视图即可。
是不是挺简单呢!但是,你用着用着就会发现,这有点问题,当你来回切换视图的时候,会发现,子视图的状态每次都重置了,比如在PageSNS视图上,你滚动列表到了下面,然后切换到了其他子视图,再切换回来,会发现列表又从回到顶部了。
那么问题来了,有些开发者就想要这样的体验,那没事。而有些需求确是必须要保留状态,那怎么整呢?
为什么子视图会被重置呢?那就要涉及到react的渲染机制了,它会再render的时候遍历一次所有子节点,把要卸载的都卸载掉,要装载的给装载上去,那就一目了然了。我们的简单版ViewStack仅仅是每次渲染一个子视图,而其他的时候会被卸载掉,当要重新渲染那个视图的时候,那个视图其实已经不在了,在只是新new出来(或者从对象池里拿出来并初始化后)的那个视图了,所以这就是问题的所在了。
那么怎么保留子视图的状态呢?(这个状态并不是react的state机制,而说得是整个视图的逻辑状态,好吧,我也扯不清楚了)
我做了一些测试,发现只要组件被卸载了,那么这个组件就不可能恢复了,或者说恢复代价有点高。当然,方法是有的,而且很简单,只是这种方法比较鲁莽,听我道来。
在使用Navigator组件的时候,会发现,他的子视图怎么能保留状态呢,这个很神奇,难道他把什么引用存起来了?然后我深入Navigator的源码看了下去,发现他坑爹把全部子视图都render了,把要显示的视图给显示,而不需要显示的则移到了屏幕外面,就这么简单啦,我也懵了,原来就是这种方法,相信你也会说一句靠之类的感叹词吧,但是它的确就是这么做的,所以我说这种方法有些鲁莽。
然后我就写下了2.0版的ViewStack:
1 /** 2 * Created by rockyl on 15/11/08. 3 */ 4 var React = require('react-native'); 5 var { 6 StyleSheet, 7 Component, 8 View, 9 } = React; 10 var Dimensions = require('Dimensions'); 11 var SCREEN_WIDTH = Dimensions.get('window').width; 12 var SCREEN_HEIGHT = Dimensions.get('window').height; 13 14 class ViewStack extends Component { 15 constructor(props) { 16 super(props); 17 } 18 19 static get defaultProps(){ 20 return { 21 index: 0, 22 } 23 }; 24 25 render(){ 26 this.views = this.props.children.map((page, i)=>{ 27 var style = this.props.index == i ? [styles.viewBase] : [styles.viewBase, styles.viewDisabled]; 28 return ( 29 <View 30 key={'view_' + i} 31 style={style}> 32 {page} 33 </View> 34 ); 35 }); 36 return ( 37 <View style={[styles.container, this.props.style,]}> 38 {this.views} 39 </View> 40 ); 41 } 42 } 43 44 var styles = StyleSheet.create({ 45 container: { 46 flex: 1, 47 overflow: 'hidden', 48 }, 49 viewBase: { 50 position: 'absolute', 51 overflow: 'hidden', 52 left: 0, 53 right: 0, 54 bottom: 0, 55 top: 0, 56 }, 57 viewDisabled: { 58 top: SCREEN_HEIGHT, 59 bottom: -SCREEN_HEIGHT, 60 }, 61 }); 62 63 module.exports = ViewStack;
so easy!
用法和简单版是一样的。
再然后,你用着用着就会发现,这切换的时候好生硬啊,秒切,略缺少点什么用户体验,比如说滚动之类的动画也要啊。
2.1版将携带动画参数和其他高级功能参数,那就要等这篇博文更新啦!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
2013-11-08 Go语言实现-观察者模式