zoukankan      html  css  js  c++  java
  • 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版将携带动画参数和其他高级功能参数,那就要等这篇博文更新啦!

  • 相关阅读:
    矩阵运算(二维数组)
    AndroidManifest.xml
    单位和尺寸
    java Map集合类
    http相关
    文件管理与XMl、JSON解析
    Handler与多线程
    App内容分享
    Fragment以及懒加载
    广播接收器与短信
  • 原文地址:https://www.cnblogs.com/rockyf/p/react-native-viewstack.html
Copyright © 2011-2022 走看看