React中实现按品牌首字母实现右侧导航

先看一下最终效果

 直接上代码

html

  <div className="brand-list">
                {/* 显示字母 */}
                <div className="show-letter" style={{ display: this.state.showLetter }}>
                    {this.state.showLetter_text}
                </div>
                {/* 右侧导航 */}
                <div className="right-nav" onTouchStart={this.fnStart.bind(this)} onTouchMove={this.fnMove.bind(this)} onTouchEnd={this.fnEnd.bind(this)} ref='right-nav'>
                    {this.state.navData.map((el, i) =>
                        <div className="item" key={i} >
                            {el}
                        </div>
                    )}

                </div>
                {/* 头部 */}
                <div className="header " ref="header">
                    <div className="iconfont back" onClick={this.back.bind(this)}> 
                        &#xe605;
                    </div>
                    <div className="title">
                        选择品牌
                    </div>
                </div>
                {/* 内容 */}
                <div className="brand-content" ref="content" onScroll={this.domScroll.bind(this)}>
                    {/* 猜你喜欢 */}
                    <div className="guess-like" ref="guess-like">

                        <div className="guess-like-title">
                            猜你喜欢
                        </div>
                        <div className="guess-like-con">
                            <div className="item">
                                <img src={car_icon1} alt="" />
                                <div className="text">
                                    大众
                                </div>
                            </div>
                            <div className="item">
                                <img src={car_icon2} alt="" />
                                <div className="text">
                                    沃尔沃
                                </div>
                            </div>
                            <div className="item">
                                <img src={car_icon3} alt="" />
                                <div className="text">
                                    日产
                                </div>
                            </div>
                            <div className="item">
                                <img src={car_icon4} alt="" />
                                <div className="text">
                                    本田
                                </div>
                            </div>
                        </div>
                    </div>
                    {/* 不限品牌 */}
                    <div className="unlimited" ref="unlimited">
                        <div className="title" ref="title">
                            ⭐
                        </div>
                        <div className="unlimited-con">
                            不限品牌
                        </div>
                    </div>
                    {/* 首字母排序 */}
                    <div className="list" ref="list">
                        {this.state.data.map((el, i) =>
                            <div className={this.returnClass(el)} key={i}>
                                <div className="item-con">
                                    <div className="car_icon">
                                        <img src={this.returnsrc(el)} alt="" />
                                    </div>
                                    <div className="car_name">
                                        {
                                            el.mod
                                        }
                                    </div>
                                </div>
                            </div>
                        )}
                    </div>
                </div>
            </div>

css

.brand-list {
  width: 750px;
  background-color: #f5f5f5;
}
.brand-list .show-letter {
  width: 200px;
  height: 200px;
  background-color: #db0303;
  position: fixed;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  margin: auto;
  z-index: 20;
  border-radius: 30px;
  text-align: center;
  line-height: 200px;
  font-size: 100px;
  color: #fff;
}
.brand-list .right-nav {
  position: fixed;
  right: 24px ;
  top: 480px;
  z-index: 20;
  color: #db0303;
  font-size: 18px;
  text-align: center;
}
.brand-list .right-nav .item {
  line-height: 30px;
}
.brand-list .header {
  position: fixed;
  height: 100px;
  width: 100%;
  background-color: #fff;
  z-index: 10;
}
.brand-list .header .back {
  font-size: 38px;
  position: absolute;
  height: 100%;
  left: 30px;
  line-height: 100px;
}
.brand-list .header .title {
  width: 100%;
  height: 100%;
  text-align: center;
  line-height: 100px;
  font-size: 30px;
}
.brand-list .brand-content {
  height: 100vh;
  overflow: scroll;
  box-sizing: border-box;
  background-color: #f5f5f5;
  padding-top: 100px;
}
.brand-list .brand-content::-webkit-scrollbar {
  display: none;
}
.brand-list .brand-content .guess-like {
  height: 260px;
  background-color: #fff;
  margin-bottom: 24px ;
  margin-top: 24px;
}
.brand-list .brand-content .guess-like .guess-like-title {
  height: 58px;
  border-bottom: 2px solid #e9e9e9;
  padding-left: 30px;
  font-size: 22px;
  line-height: 58px;
}
.brand-list .brand-content .guess-like .guess-like-con {
  display: flex;
  justify-content: space-around;
  align-items: center;
  padding-top: 38px;
}
.brand-list .brand-content .guess-like .guess-like-con .item {
  width: 25%;
  text-align: center;
}
.brand-list .brand-content .guess-like .guess-like-con .item img {
  height: 65px;
}
.brand-list .brand-content .guess-like .guess-like-con .item .text {
  font-size: 28px;
  padding-top: 10px;
}
.brand-list .brand-content .unlimited {
  height: 205px;
  background-color: #fff;
  margin-bottom: 24px ;
}
.brand-list .brand-content .unlimited .title {
  height: 84px;
  border-bottom: 2px solid #e9e9e9;
  padding-left: 30px;
  font-size: 22px;
  line-height: 84px;
}
.brand-list .brand-content .unlimited .unlimited-con {
  line-height: 122px;
  font-size: 28px;
  padding-left: 30px;
}
.brand-list .brand-content .list {
  background-color: #fff;
}
.brand-list .brand-content .list .title {
  height: 84px;
  font-size: 22px;
  line-height: 84px;
}
.brand-list .brand-content .list .title .item-con {
  position: relative;
  height: 84px;
  border-bottom: 2px solid #e9e9e9;
  padding-left: 30px;
  background-color: #fff;
}
.brand-list .brand-content .list .title .item-con .car_icon {
  display: none !important;
}
.brand-list .brand-content .list .title .item-con .car_name {
  font-size: 22px;
}
.brand-list .brand-content .list .title .fixed {
  position: fixed;
  top: 100px;
  left: 0;
  right: 0;
  margin: auto;
  padding-left: 30px;
  height: 84px;
  border-bottom: 2px solid #e9e9e9;
  background-color: #fff;
}
.brand-list .brand-content .list .title .fixed .car_icon {
  display: none !important;
}
.brand-list .brand-content .list .title .fixed .car_name {
  font-size: 22px;
}
.brand-list .brand-content .list .item {
  height: 124px;
}
.brand-list .brand-content .list .item .item-con {
  height: 124px;
  display: flex;
  align-items: center;
}
.brand-list .brand-content .list .item .item-con .car_icon {
  height: 124px;
  width: 154px;
  text-align: center;
  line-height: 124px;
  overflow: hidden;
}
.brand-list .brand-content .list .item .item-con .car_icon img {
  width: 75px;
  height: 75px;
}
.brand-list .brand-content .list .item .item-con .car_name {
  flex: 1;
  height: 100%;
  line-height: 124px;
  font-size: 28px;
  border-bottom: 2px solid #e9e9e9;
}

js逻辑代码

class BrandList extends Component {
    constructor(...args) {
        super(...args)
        this.Init()
    }
    // 初始化
    Init() {
        this.brandList = []//存放数据
        this.tops = []//存放内容标题距离顶部的距离
        this.childs = []//存放标题元素
        this.rightTops = []//存放右边导航的位置
        this.navData = ['猜', '⭐']//右边导航数据
        this.state = {
            data: [],
            navData: [],
            showLetter: 'none',//控制提示文字
            showLetter_text: 'A'//控制显示文字
        }
    }
    // 获取数据
    async getData() {
        this.brandList = await getBrand({ phone: 1 })
    }
    // 返回图片
    returnsrc(item) {
        if (item.mod.length === 1) {
            return '#'
        }
        if (item.state) {
            return `http://www.ibugthree.com/${item.icon_src}`;
        } else {
            return `http://www.ibugthree.com/default.gif`;
        }
    }
    // 判断类名
    returnClass(item) {
        // console.log(item.mod.length);
        if (item.mod.length === 1) {
            return 'title'
        } else {
            return 'item'
        }
    }

    // 滚动时
    domScroll(e) {
        this.scrollTop = e.target.scrollTop
        for (let i = 0; i < this.brandList.length; i++) {
            if(this.child[i].offsetTop-this.scrollTop<this.viewHeight){
                this.brandList[i].state=true;
            }
        }
        this.setState({
            data: this.brandList,
        })
        for (let i = 0; i < this.tops.length; i++) {
            if (this.scrollTop > this.tops[i] && this.scrollTop < this.tops[i + 1]) {
                this.childs[i].children[0].className = 'fixed'
            } else {
                this.childs[i].children[0].className = 'item-con'
            }
        }
    }
    // 点击导航
    fnStart(e) {
        this.y = e.touches[0].pageY - this.refs['right-nav'].offsetTop;
        for (let i = 0; i < this.rightTops.length; i++) {
            if (this.y >= this.rightTops[i] && this.y < this.rightTops[i + 1]) {
                this.refs.content.scrollTop = this.tops[i - 1] - this.refs['guess-like'].offsetHeight - this.refs.unlimited.offsetHeight
                this.setState({
                    showLetter: 'block',
                    showLetter_text: this.navData[i]
                })
            }
            if (this.y >= this.rightTops[i] && this.rightTops[i + 1] === undefined) {
                this.refs.content.scrollTop = this.refs.content.scrollHeight
                this.setState({
                    showLetter: 'block',
                    showLetter_text: this.navData[i]
                })
            }

        }
    }
    fnMove(e) {
        this.y = e.touches[0].pageY - this.refs['right-nav'].offsetTop
        for (let i = 0; i < this.rightTops.length; i++) {
            if (this.y >= this.rightTops[i] && this.y < this.rightTops[i + 1]) {
                this.refs.content.scrollTop = this.tops[i - 1] - this.refs['guess-like'].offsetHeight - this.refs.unlimited.offsetHeight
                this.setState({
                    showLetter: 'block',
                    showLetter_text: this.navData[i]
                })
            }
            if (this.y >= this.rightTops[i] && this.rightTops[i + 1] === undefined) {
                this.refs.content.scrollTop = this.refs.content.scrollHeight;
                this.setState({
                    showLetter: 'block',
                    showLetter_text: this.navData[i]
                })
            }

        }
    }
    fnEnd() {
        this.setState({
            showLetter: 'none'
        })
    }
    // 延迟加载图片
    lazyLoad() {
        this.viewHeight = document.documentElement.clientHeight;
        for (let i = 0; i < this.brandList.length; i++) {
            let top = this.child[i].offsetTop
            this.brandList[i].top = top;
            if (top > this.viewHeight) {
                this.brandList[i].state = false;
            } else {
                this.brandList[i].state = true;
            }
        }


        this.setState({
            data: this.brandList,
        })
    }
    // 返回主页
    back(){
        Control.go(-1)
    }
    async componentDidMount() {
        await this.getData()
        this.setState({
            data: this.brandList,
        })
        // 得到 A-Z 的标题
        for (let i = 0; i < this.brandList.length; i++) {
            if (this.brandList[i].mod.length === 1) {
                this.navData.push(this.brandList[i].mod)
            }
        }
        this.setState({
            navData: this.navData
        })

        // 获取距离顶部的距离
        this.child = this.refs.list.children;
        for (let i = 0; i < this.child.length; i++) {
            if (this.child[i].className === 'title') {
                this.tops.push(this.child[i].getBoundingClientRect().y - this.refs.header.offsetHeight)
                this.childs.push(this.child[i])
            }
        }
        // 获取右边导航的位置
        this.right_nav_child = this.refs['right-nav'].children;
        for (let i = 0; i < this.right_nav_child.length; i++) {
            this.rightTops.push(this.right_nav_child[i].offsetTop)
        }
        // 延迟加载车辆图片
        this.lazyLoad()
    }

具体的实现逻辑思路后续会补上,先把代码存到这里

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值