React Native小技巧

作者: 阳光下慵懒的驴 | 来源:发表于2017-10-23 11:52 被阅读174次

    ListView 标签流式布局

    contentContainerStyle={styles.listContainer}
    listContainer:{
    flexDirection:'row',
    flexWrap:'wrap',
    },
    
    

    这种方式只能实现类似标签的高度相等,宽度不同的布局,不能实现高度不同,宽度相同的瀑布流布局
    row的最外层需要设置确定的高度

    ListView 瀑布流

    row设置为绝对布局,计算位置

    renderRow执行的次数比dataSource的数量少

    如果出现renderRow执行的次数比dataSource的数量少的情况,
    需要设置:
    initialListSize={20} // 可以把值改为dataSource的length
    如果不设置,renderRow只能执行前几条数据, 想显示其他数据, 只能通过改变任意state来实现

    得到text的高度

    <Text onLayout={(event)=>this._textOnLayout(event)} />
    
    _textOnLayout(event){
        console.log(event.nativeEvent.layout.height,'onLayout');
    }
    

    ListView从下向上排列

    <ListView contentContainerStyle={styles.listViewContent}/>
    listViewContent:{
        flex:1,
        //从下向上排列
        justifyContent:'flex-end'
    }
    

    得到组件宽高

    this.refs.row.measure(function(ox,oy,width,height,px,py){
        cellHeight=height;
    });
    
    <View style={styles.row} ref="row"/>
    
    row:{
        flex:1,
        backgroundColor:'#FFFFFF',
        borderTopWidth:1/2,
        borderBottomWidth:1/2,
        borderColor:'#dddddd',
        marginTop:10/2,
        marginBottom:10/2
    },
    

    指定某个组件

    var _listView: ListView;
    <ListView ref={(listView)=>{_listView=listView;}}/>
    

    版本更新

    openAppStore: ()=> {
      var url = '';
      if (Platform.OS === 'ios') {
        url = 'itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&id=1156814163';
      } else {
        url = 'http://a.app.qq.com/o/simple.jsp?pkgname=com.girtu.girtu'
      }
    
      Linking.openURL(url).catch(err => console.error('An error occurred', err));
    },
    
    checkoutUpdate: ()=> {
      let setLaterUpdateTime = (time) => {
        AsyncStorage.setItem('update_time', time);
      }
    
      let getLaterUpdateTime = () => {
        return AsyncStorage.getItem('update_time')
      }
    
      // 点击了稍后更新, 保存当前时间
      let laterUpdate = ()=> {
        setLaterUpdateTime(new Date().toString())
      }
    
      // 点击立即下载只是跳转到商店,本地不做处理,如果没有更新,下次进入依然提醒
      // 点击稍后下载,本地记录时间,10天后再次提醒
      let showAlert = ()=> {
        Alert.alert('有新版本发布, 是否更新', '', [
          {text: '马上下载', onPress: ()=>module.exports.openAppStore()},
          {text: '稍后更新', onPress: ()=>laterUpdate()}
        ])
      }
    
      // 计算时间差, 如果大于10天就显示alert, 否则什么都不做
      let calculateDateDiff = (oldDate)=> {
        oldDate = new Date(oldDate)
        let newDate = new Date(); //结束时间
        let differDate = newDate.getTime() - oldDate.getTime(); //时间差的毫秒数
        let days = Math.floor(differDate / (24 * 3600 * 1000)); ////计算出相差天数
        if(days >= 10) {
          showAlert()
        }
      }
    
      setTimeout(()=> {
        // 假设获取到版本号后
        let newVersion = '2.3.3';
        let oldVersion = DeviceInfo.getVersion();
        if (newVersion > oldVersion) {
          getLaterUpdateTime()
            .then((oldDate)=> {
              // 如果有时间就计算时间差, 没有时间就直接显示
              if (oldDate) {
                calculateDateDiff(oldDate)
                // calculateDateDiff(1489075200000)
              } else {
                showAlert()
              }
            })
            .catch((e)=> {
              showAlert()
            })
        }
      }, 2000)
    },
    

    navigationBar颜色渐变

    // 参数格式为#ffffff 或者 #ffffff00
    function hexToRGBA(hex) {
      var a = 1
      if (hex.length == 9) {
        a = parseInt(hex.substr(7, 2), 16) / parseInt('ff', 16)
      }
    
      let r = parseInt(hex.substr(1, 2), 16)
      let g = parseInt(hex.substr(3, 2), 16)
      let b = parseInt(hex.substr(5, 2), 16)
    
      let rgba = `rgba(${r}, ${g}, ${b}, ${a})`
      return {
        string: rgba,
        r,
        g,
        b,
        a
      }
    }
    
    updateProgress(progress, fromIndex, toIndex) {
      var routes = this.props.navState.routeStack
      var fromRoute = routes[fromIndex]
      var toRoute = routes[toIndex]
    
      let {navColor} = fromRoute
    
      if (fromRoute.navColor != toRoute.navColor) {
        let fromRGBA = utils.hexToRGBA(fromRoute.navColor)
        let toRGBA = utils.hexToRGBA(toRoute.navColor)
        const {r: toR, g: toG, b: toB, a: toA} = toRGBA
        const {r: fromR, g: fromG, b: fromB, a: fromA} = fromRGBA
        let minusR = toR - fromR
        let minusG = toG - fromG
        let minusB = toB - fromB
        let minusA = toA - fromA
    
        let r = toR - minusR * (1 - progress)
        let g = toG - minusG * (1 - progress)
        let b = toB - minusB * (1 - progress)
        let a = toA - minusA * (1 - progress)
    
        navColor = `rgba(${r}, ${g}, ${b}, ${a})`
    
        this.setState({
          progressStyle: {
            ...this.state.progressStyle,
            backgroundColor: navColor,
          }
        })
      }
    
      this._nav && this._nav.updateProgress(progress, fromIndex, toIndex)
    }
    

    旋转rotate

    let iwidth = util.size.width;
    let iheight = iwidth / mediaInfo.width * mediaInfo.height
    
    // 如果是旋转过的图片,重新计算
    let rotate = ??; // 角度 字符串
    if (rotate == '90' || rotate == '270') {
       iheight = util.size.width
       iwidth = iheight * (mediaInfo.width / mediaInfo.height)
       let translateXY = (iwidth > iheight ? 1 : -1 ) * (Math.abs(iwidth - iheight) / 2)
       translateXY *= (rotate == '90' ? 1 : -1 )
    
        return (
            <View style={{
                position: 'absolute',
                left: 0,
                top: 0,
                width: iwidth, // 如果90度或者270度,宽高需要反过来,因为是先旋转再设置宽高
                height: iheight,
                transform: [
                    {rotate: `${rotate}deg`},
                    {translateX: translateXY},
                    {translateY: translateXY}
                ]}}
            />
       );
     } else {
        return (
            <View style={{
                position: 'absolute',
                left: 0,
                top: 0,
                width: iwidth,
                height: iheight,
                transform: [
                    {rotate: `${rotate}deg`},
                ]
                }]}
            />
       )
     }
    

    子view上下拉伸

    justifyContent: 'space-between',
    alignSelf: 'stretch'
    

    WebView自动获取高度

    在html中监听高度的变化,把title设置为高度,当title变化时,会触发WebView的onNavigationStateChange方法,获取到高度。

    <WebView
        {...this.props}
        source={{html: `<!DOCTYPE html><html><body>${this.props.htmlBody}<script>window.onload=function(){window.location.hash = 1;document.title = document.body.clientHeight;}</script></body></html>`}}
        javaScriptEnabled={true}
        style={[{height: this.state.height}, this.props.style]}
        scrollEnabled={false}
        automaticallyAdjustContentInsets={true}
        contentInset={{top:0,left:0}}
        onNavigationStateChange={(info)=>{
          if (info.title) {
            this.setState({
               height: parseInt(info.title) + 20
             })
           }
         }}
    />
    

    画三角

    // 画三角。style:
    triangle: {
        width: 0,
        height: 0,
        borderStyle: 'solid',
        borderWidth: 8,
        marginTop: -8,
        borderTopColor: 'transparent',//下箭头颜色
        borderLeftColor: 'transparent',//右箭头颜色
        borderBottomColor: Colors.BACKGROUND_GRAY,//上箭头颜色
        borderRightColor: 'transparent'//左箭头颜色
    },
    

    iOS图片更新不及时显示新图片的解决办法

    bug产生的原因:iOS的Image更换uri不会马上清空显示的内容,而是加载成功后才替换,所以在加载过程中依然显示旧图片。
    解决:

    1. 从Image加载的角度不好解决,所以要让Image重新创建,就要从ListView下手,而ListView更新已存在的row只是刷新,不是重新创建
    2. react为组件提供了key属性,用于同级别的组件根据key的不同来优化渲染,原理就是如果key相同就刷新,key不同就重新创建
    3. 在ListView的renderRow的最外层component添加key属性,设置为当然数据的唯一id,就可以在更新时重新创建Image,(不可以设置为row的索引,没有任何对优化的帮助而且会造成不可预料的问题)
    4. 进一步优化,重新创建item会造成多余的开销,而现在只需要更新Image,所以renderRow的component去掉key属性,给Image添加key属性,设置为url,解决。

    RN iOS图片缓存位置

    APP路径/Library/Caches/[Bundle ID]/fsCachedData

    引入装饰器

    npm i --save-dev babel-plugin-transform-decorators-legacy
    修改.babelrc

    {
        "presets": ["react-native"],
        "plugins": ["transform-decorators-legacy"]
    }
    

    相关文章

      网友评论

        本文标题:React Native小技巧

        本文链接:https://www.haomeiwen.com/subject/dmoouxtx.html