React小经验,关于多级选项卡的匹配问题,设计一个URL和选项卡逻辑关联的API,可进行书签保存并跳转指定页。

多级选项卡,应该仍有少部分人,会选择写死。其实是有必要去动态渲染的。
毕竟,代码虽然服务于产品,但是产品的支撑性离不开代码的健壮度。

先上代码:

// ...
import { hashToObj, tabArrBindClick } from '../../../lib/kids-tools';

// ...
const CategoryPage = ({
  ...props
}) => {
  const {
    location: { hash },
    history: { push }
  } = props;

  // const tabs = ...

  const tags = tabArrBindClick([{
    title: '全部',
    type: 'all'
  }, {
    title: '精选',
    imgSrc: img_king,
    bcgColor: 'yellow',
    type: 'featured'
  }, {
    title: '光环版 + mBuild',
    bcgColor: 'blue',
    type: 'light'
  }, {
    title: '程小奔',
    bcgColor: 'blue',
    type: 'cxb'
  }, {
    title: 'Python',
    bcgColor: 'green',
    type: 'python'
  }], hash, push, 'tag', '/category');

  // const digitalTabs = ...

  const [tabIndexs, setTabIndexs] = useState({
    type: getTabIndexs[0], // 分类选项卡
    tag: getTabIndexs[1], // 子标签
    order: getTabIndexs[2] // 热度最新
  });

  // hash变化选项卡重渲
  useEffect(() => {
    hashChangeTabIndexs();
  }, [hash]);
	
  // 设置索引
  const hashChangeTabIndexs = () => {
    // 哈希获取索引顺序
    const [typeIndex, tagIndex, orderIndex] = getTabIndexs();
    setTabIndexs({
      type: typeIndex === -1 ? 0 : typeIndex,
      tag: tagIndex === -1 ? 0 : tagIndex,
      order: orderIndex === -1 ? 0 : orderIndex
    })
  }
  
  // 获取哈希对应索引
  function getTabIndexs() {
    // 将hash转成对象
    const { type, tag, order } = hashToObj(hash);
    // 根据值和数组内的标识(type)进行索引定位。
    const typeIndex = tabs.findIndex(i => i.type === type);
    const tagIndex = tags.findIndex(i => i.type === tag);
    const orderIndex = digitalTabs.findIndex(i => i.type === order);
    return [typeIndex, tagIndex, orderIndex];
  }

  return (
  // ...
    <NavTabs
        tabs={tabs}
        activeIndex={tabIndexs.type}
        liStyle={liStyle}
        narrow={true}
      />
    <Tags
       tags={tags}
       activeIndex={tabIndexs.tag}
    />
    <DigitalTabs
       tabs={digitalTabs}
       activeIndex={tabIndexs.order}
       showNum={false}
     />
    // ...
  );
};

export default CategoryPage;

最终效果:

在这里插入图片描述
效果1:首页渲染,无抖动。
效果2:选项卡各种点击,URL会变化,且页面无抖动,可以用于收藏页面。

浅分析:

1、首页渲染,可以根据props.location.hash进行索引定位,在渲染阶段直接赋值。
2、标签点击跳转渲染,每个标签动态绑定onClick字段,并渲染生成合法的URL,再利用push去触发Effect(或者Updated),变化索引。

API设计:

1、循环绑定选项卡(需指定标识字段即变化的哈希的名称 type=news 'type’即名称)

/**
 * 选项卡数组绑定onClick: push跳转事件
 * @param {array} tabs 选项卡数组 (需要携带type标识作为hash名)
 * @param {string} hash 当前URL
 * @param {function} push history.push方法传入
 * @param {string} name 覆写的哈希名称
 * @param {string} pathname 跳转的前置路由 (如:'/user')
 */
export const tabArrBindClick = (tabs, hash, push, name, pathname) => {
  // 将传入的hash键值化,并将
  const hashInfo = hashToObj(hash);
  // 遍历tabs绑定onClick字段
  return tabs.map(t => ({
    ...t,
    onClick: () => push(`${pathname}${objToHash({
      ...hashInfo,
      [name]: t.type
    })}`)
  }))
}

2、哈希与对象相互转化

// 哈希串转对象
export const hashToObj = (hash) => {
  let json = {};
  if (hash.includes('#')) {
    hash.substring(1).split('&').forEach((item, index) => {
      const [field, val] = item.split('=');
      json[field] = val;
    });
  }
  return json;
}

// 对象转哈希串
export const objToHash = (obj) => {
  let hash = '#';
  Object.keys(obj).forEach(field => {
    hash += `${field}=${obj[field]}&`;
  });
  return hash.slice(0, -1);
}

大神们可能会有更简洁的代码去实现,请轻喷小弟,但是基于单页应用,上述的思路应该是正确的。

最后,上述过程链较长,有时为了提高开发效率,且合适,也可以选择写死。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值