前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React-Native 版高仿淘宝、京东商城首页、商品分类页面

React-Native 版高仿淘宝、京东商城首页、商品分类页面

作者头像
子晋
发布2022-01-18 21:25:37
3K0
发布2022-01-18 21:25:37
举报
文章被收录于专栏:子晋城子晋城

高仿淘宝、京东等商城首页、商品分类页面,正在做商城项目的同学有福啦,看看是你们想要的效果吗?

项目地址:https://github.com/pengzhenjin/react-native-mall

效果图

已实现功能

  • 沉浸式状态栏
  • 酷炫的顶部导航动画
  • 消息角标
  • 循环轮播图
  • 搜索
  • 商品一级分类
  • 商品二级分类
  • 商品子分类
  • 顶部滑动的tab、智能下拉菜单

用到的技术

  • 自定义 Badge(角标)
  • 动画、动画插值器
  • Swiper 轮播图
  • 自定义 tab
  • 自定义 popup 弹窗下拉菜单
  • FlatList、SectionList

重点代码解析

MallHome.js

代码语言:javascript
复制
/**
     * 滚动条监听事件
     * @param event
     */
    onScrollFunc = (event) => {
        // 将滚动的值绑定到渐变动画
        Animated.event([{nativeEvent: {contentOffset: {y: this.state.logoOpacity}}}])(event)
 
        // 将滚动的值绑定到边距动画
        Animated.event([{nativeEvent: {contentOffset: {y: this.state.searchViewMargin}}}])(event)
    }
代码语言:javascript
复制
renderSearchView = () => {
        const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity)
 
        const marginRight = this.state.searchViewMargin.interpolate({
            inputRange: [0, 80], // 当滚动条滚动到0~80的位置时
            outputRange: [0, 80], // 将右边距改为从0~80
            extrapolate: 'clamp' // 滚动超出0~80的范围,不在更改边距
        })
        const marginTop = this.state.searchViewMargin.interpolate({
            inputRange: [0, 160], // 当滚动条滚动到0~160的位置时
            outputRange: [0, -36], // 将上边距改为从0~-36
            extrapolate: 'clamp' // 滚动超出0~160的范围,不在更改边距
        })
 
        return (
            <AnimatedTouchableOpacity
                style={styles.top_search_container(marginRight, marginTop)}
                activeOpacity={0.8}
                onPress={this.gotoSearch}
            >
                <Image style={styles.top_search_icon} source={iconSearch} />
                <Text style={styles.top_search_text}>{'新品'}</Text>
            </AnimatedTouchableOpacity>
        )
    }

GoodsCategory.js 解析

代码语言:javascript
复制
render() {
        return (
            <View style={styles.container}>
                <View style={styles.first_category_container}>
            // 一级分类列表,采用FlatList
                    <FlatList
                        ref={refs => this.flatList = refs}
                        keyExtractor={(item, index) => index.toString()}
                        data={this.state.firstCategoryData}
                        renderItem={this.renderFirstCategoryItem}
                        ItemSeparatorComponent={this.renderSeparatorLine}
                    />
                </View>
                <View style={styles.second_category_container}>
            // 二级、三级分类列表,采用SectionList
                    <SectionList
                        ref={refs => this.sectionList = refs}
                        renderSectionHeader={this.renderSecondCategorySectionHeader}
                        renderItem={this.renderSecondCategoryItem}
                        sections={this.state.secondCategoryData}
                        ItemSeparatorComponent={null}
                        ListHeaderComponent={null}
                        ListFooterComponent={null}
                        keyExtractor={(item, index) => index + item}
                    />
                </View>
            </View>
        );
    }
代码语言:javascript
复制
  // 点击一级分类时,需要计算滚动条的位置
    onClickFirstCategoryItem = (item, index) => {
        this.setState({selectedFirstCategoryIndex: index});
 
        // 计算当前 item 的高度
        const indexHeight = firstCategoryItemHeight * index;
 
        // 计算屏幕一半的高度
        const halfHeight = (height - 65) / 2;
 
        // 如果当前 item 的高度 大于 屏幕一半的高度,就让滚动条滚动 indexHeight - halfHeight 高度(类似京东商品分类效果)
        if (indexHeight > halfHeight) {
            this.flatList.scrollToOffset({
                animated: true,
                offset: indexHeight - halfHeight,
            });
        }
 
        this.sectionList.scrollToLocation({
            animated: true,
            itemIndex: 0,
            sectionIndex: 0,
        });
    };

TopTabView.js 解析

代码语言:javascript
复制
     /**
     * 显示下拉菜单
     * @param index 当前选中时的 tab 下标
     */
    showDropdownMenu = (index) => {
        // measure方法测量"箭头图标"在页面中的位置、宽高
        this.arrowIcon.measure((x, y, width, height, pageX, pageY) => {
            const topOffset = pageY + height // 计算"下拉菜单"距离页面顶部的偏移量
            this.dropdownMenu.show(topOffset, index) // 显示"下拉菜单"
        })
    }

组件的 measure((x, y, width, height, pageX, pageY) => {}) 方法可以动态的获取组件在屏幕中的位置、宽高信息。measure 方法的参数 x,y 表示组件的相对位置,width,height 表示组件的宽度和高度,pageX,pageY 表示组件相对于屏幕的绝对位置。

TopDropdownMenu.js 解析

代码语言:javascript
复制
// 使用 Modal 来实现弹窗菜单,达到遮罩效果
 render() {
        const {isVisible, data, topOffset} = this.state;
        return (
            <Modal
                animationType="fade"
                transparent={true}
                onRequestClose={() => this.hide()}
                visible={isVisible}
            >
                <TouchableOpacity
                    style={styles.container}
                    activeOpacity={1}
                    onPress={() => this.hide()}
                >
                    <FlatList
                        style={[styles.content_container, {top: topOffset}]}
                        keyExtractor={(item, index) => index.toString()}
                        data={data}
                        renderItem={this.renderItem}
                        horizontal={false}
                        numColumns={2}
                        renderSeparator={null}
                    />
                </TouchableOpacity>
            </Modal>
        );
    }
代码语言:javascript
复制
   // 使用绝对布局和 top 来计算弹窗菜单的位置,其中 top 是动态计算的
    content_container: {
        position: 'absolute',
        top: 0,
        backgroundColor: '#FFFFFF',
    },
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 效果图
  • 已实现功能
  • 用到的技术
  • 重点代码解析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档