10-8 根据选中类别动态生成首页模块的顶部标签导航器和modal

在之前的章节中,我们已经完成了分类模块的功能。在这一节中,我们将根据用户选择的类别动态生成首页的顶部标签导航器和 Model。

一、动态生成顶部标签导航器

  1. 更新 HomeTabs.tsx 文件

    navigator/HomeTab.tsx 文件中,使用 createMaterialTopTabNavigator 创建导航器,并根据用户选择的类别动态生成标签页:

    typescript 复制代码
    import React from 'react';
    import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
    import { connect, ConnectedProps } from 'react-redux';
    import { RootState } from '@/models/index';
    import Home from '@/pages/Home';
    
    export type HomeTabParamList = {
      [key: string]: {
        modelNamespace: string;
        category: string;
      };
    };
    
    const Tab = createMaterialTopTabNavigator<HomeTabParamList>();
    
    const mapStateToProps = ({ category }: RootState) => ({
      myCategorys: category.myCategorys,
    });
    
    const connector = connect(mapStateToProps);
    
    type IProps = ConnectedProps<typeof connector>;
    
    function HomeTabs({ myCategorys }: IProps) {
      return (
        <Tab.Navigator>
          {myCategorys.map((category) => (
            <Tab.Screen
              key={category.id}
              name={category.id}
              component={Home}
              options={{
                tabBarLabel: category.name,
              }}
              initialParams={{
                modelNamespace: category.id,
                category: category.id,
              }}
            />
          ))}
        </Tab.Navigator>
      );
    }
    
    export default connector(HomeTabs);

二、动态生成 Model

  1. 安装 dva-model-extend

    bash 复制代码
    yarn add dva-model-extend
  2. 创建 createModel 函数

    models 文件夹中创建一个 createModel.ts 文件:

    typescript 复制代码
    import modelExtend from 'dva-model-extend';
    import home from '@/models/home';
    
    interface Cached {
      [key: string]: number;
    }
    
    const cached: Cached = {
      home: 1,
    };
    
    function registerModel(model: Model) {
      if (!cached[model.namespace]) {
        app.model(model);
        cached[model.namespace] = 1;
      }
    }
    
    export function createModel(namespace: string) {
      const model = modelExtend(home, {
        namespace,
      });
    
      registerModel(model);
    }
  3. 更新 HomeTabs.tsx 文件

    HomeTabs.tsx 文件中,动态生成 Model 并绑定到导航器:

    typescript 复制代码
    import { createModel } from '@/models/createModel';
    
    function HomeTabs({ myCategorys }: IProps) {
      myCategorys.forEach((category) => {
        createModel(category.id);
      });
    
      return (
        <Tab.Navigator>
          {myCategorys.map((category) => (
            <Tab.Screen
              key={category.id}
              name={category.id}
              component={Home}
              options={{
                tabBarLabel: category.name,
              }}
              initialParams={{
                modelNamespace: category.id,
                category: category.id,
              }}
            />
          ))}
        </Tab.Navigator>
      );
    }

三、更新页面组件

  1. 更新 Home 页面的 mapStateToProps

    typescript 复制代码
    import { findRouteNameFromNavigatorState } from '@/utils/index';
    
    const mapStateToProps = (
      state: RootState,
      props: { route: { params: { modelNamespace: string } } }
    ) => {
      const { modelNamespace } = props.route.params;
      const modelState = state[modelNamespace];
      return {
        carousels: modelState.carousels,
        channels: modelState.channels,
        hasMore: modelState.pagination.hasMore,
        gradientVisible: modelState.gradientVisible,
        loading: state.loading.effects['home/fetchChannels'],
      };
    };
  2. 创建 findRouteNameFromNavigatorState 函数

    utils/index.ts 文件中创建该函数:

    typescript 复制代码
    export function findRouteNameFromNavigatorState(
      state: NavigationState
    ): string {
      let route = state.routes[state.index];
      while (route.state) {
        route = route.state.routes[route.state.index];
      }
      return route.name;
    }

四、总结

在本节中,我们根据用户选择的类别动态生成了首页的顶部标签导航器和 Model。通过使用 dva-model-extend 库,我们能够动态创建 Model,确保每个标签页的数据独立。这样,每个标签页都可以根据选择的类别独立加载和显示数据。

下一节,我们将学习如何实现手势响应系统,完成频道模块的功能。

相关推荐
寅时码1 小时前
React 之死·终章:一个 useRef,把闭包陷阱、依赖数组、漫天 rerender 全送走
前端·react.js·ai编程
不好听6131 小时前
HTML 事件监听机制:从 DOM Level 0 到 React 合成事件
前端·react.js·html
wordbaby1 小时前
为什么刷新页面就 404?聊聊 SPA 路由与 Nginx 的那点事
前端
不好听6132 小时前
React 核心概念:JSX、组件与数据驱动
前端·react.js
触底反弹2 小时前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听6132 小时前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue2 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue2 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法
小林ixn3 小时前
从 onclick 到 React 合成事件,再到完整应用逻辑:一次前端架构的深度剖析
前端·react.js·前端框架
Csvn3 小时前
🧩「找不到模块」排查全记录——Monorepo 下 TypeScript 路径别名的 5 种「不通」与根治方案
前端