移动端Tabs展示菜单个数自适应屏幕大小

文章描述了一种在移动端项目中使用React和Antd-Mobile开发时,如何通过计算内联宽度实现顶部菜单Tab的屏幕适配策略,当Tab数量超出屏幕宽度时,将多余的选项放在下拉菜单中的解决方案。
摘要由CSDN通过智能技术生成

需求如下

        移动端顶部菜单Tab个数要适配屏幕,且不能有滚动操作,将剩余的选项展示在更多下拉菜单当中。

        项目使用的是react+antd-mobile,组件中也没找到有对应的组件;自己封装了菜单逻辑,实现了效果

思路:

  1.   由于项目是没有多语言的,一个12px的汉字占据位置的宽度大概是18px;
  2.  需要知道菜单tabs的总宽度,然后匹配每个tab有多少个字,再加上间距,如果宽度超过tabs的总宽度,就展示更多菜单,然后将剩余的tabs以列表形式展示在下拉菜单当中 
  3. tabs数据当中,给个当前宽度能展示最大个数的标识,我用isMax表示;   

     有了以上思路,我们可以利用innerWidth去计算,实现以上逻辑。代码如下:

      js部分:首先我们处理tabs数据,通过innerWidth计算出可以展示tab的最大个数,给最大个数的那条数据添加一个isMax标识:

 const fetchDepthData = (year: any) => {
    getInfoWealthByYear({ year }).then((res: any) => {
      if (res?.success) {
        const DATA = res.data || [];
        DATA.forEach((e: any) => {
          if (e.equalCheck === 1) {
            e.names = e.names + '等';
          }
        });

        const _data = DATA.map((e: any, index: any) => {
          return {
            label: e.researchArea,
            value: index,
            width: e.researchArea.length * 18,
            checked: false,
          };
        }).filter(
          (ele: any, index: any, self: any) =>
            self.findIndex((e: any) => e.label === ele.label) === index,
        );
        let currentWidth = 0;
        let _max = window.innerWidth - 280;
        for (let i = 0; i < _data.length; i++) {
          currentWidth += _data[i].label.length * 18 + 12;
          if (currentWidth >= _max) {
            _data[i].isMax = true;
            break;
          }
        }
        if (DATA.length) {
          _data[0].checked = true;
          setResearchAreas(_data);
          setWealthData(
            DATA.filter((e: any) => e.researchArea === _data[0].label),
          );
          setdepthData(DATA);
        }
      } else {
        setResearchAreas([]);
        setWealthData([]);
        setdepthData([]);
      }
    });
  };

   html部分:在渲染时,要查找isMax的数据,然后将剩余的数据展示在下拉菜单当中;

<div
              style={{
                display: 'flex',
                flex: '1',
                justifyContent: 'space-between',
                height: '100%',
                alignItems: 'center',
                padding: '0',
              }}
            >
              {researchAreas
                .slice(0, researchAreas.findIndex((t: any) => t.isMax) + 1)
                .map((e: any) => (
                  <div
                    key={e}
                    className={styles.subMenu}
                    style={{
                      width: e.width + 'px',
                      padding: '0 6px',
                      color: e.checked ? '#1677ff' : '#333',
                    }}
                    onClick={() => {
                      areaClick(e);
                    }}
                  >
                    {e.label}
                  </div>
                ))}
              <div
                style={{
                  display:
                    researchAreas.length >
                      researchAreas.findIndex((t: any) => t.isMax) + 1
                      ? 'block'
                      : 'none',
                }}
              >
                <Dropdown ref={dropDownRefDep}>
                  <Dropdown.Item key="type" title="更多">
                    <div className={styles.yearDropDown}>
                      {researchAreas
                        .slice(researchAreas.findIndex((t: any) => t.isMax) + 1)
                        .map((ele: any) =>
                          ele.label ? (
                            <div
                              className={styles.depDropdown}
                              key={ele.value}
                              onClick={() => {
                                researchAreas.forEach((t: any) => {
                                  t.checked = t.label === ele.label;
                                });
                                setWealthData(
                                  depthData.filter(
                                    (e: any) => e.researchArea === ele.label,
                                  ),
                                );
                                setResearchAreas([...researchAreas]);
                                setTimeout(() => {
                                  dropDownRefDep.current?.close();
                                }, 200);
                              }}
                              style={{
                                height: '30px',
                                lineHeight: '30px',
                                margin: '0 12px',
                              }}
                            >
                              <span
                                style={ele.checked ? { color: '#1677ff' } : {}}
                              >
                                {ele.label}
                              </span>
                            </div>
                          ) : (
                            ''
                          ),
                        )}
                    </div>
                  </Dropdown.Item>
                </Dropdown>
              </div>
            </div>

效果如下:

        竖屏:

        横屏:

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值