react native hooks 无限级分类菜单/折叠菜单/树形菜单

最近用react-native开发App的时候,用到一个侧边栏多级菜单,通过点击,实现无限分级菜单的核心功能(父子关系,展开与收起),在没有DOM的情况下,一时不知道怎么实现了。。。

View结构如下:

<view style="sidebar">
  <view>
    <view style="title">菜单1</view>
    <view>
      <view style="title">菜单1-1</view>
      <view></view>
    </view>
  </view>
  <view>
    <view style="title">菜单2</view>
    <view>
      <view style="title">菜单2-1</view>
      <view></view>
    </view>
  </view>
</view>

数据如下:

let data1 = [
  {
    id: 1,
    pid: 0,
    name: '员工管理',
  },
  {
    id: 3,
    pid: 1,
    name: '添加员工',
  },
  {
    id: 4,
    pid: 1,
    name: '删除员工',
  },
  {
    id: 5,
    pid: 4,
    name: '按姓名删除',
  },
  {
    id: 6,
    pid: 4,
    name: '按工号删除',
  },
  {
    id: 2,
    pid: 0,
    name: '菜单管理',
  },
  {
    id: 7,
    pid: 2,
    name: '修改菜单',
  }
];

let tree1 = [
  {
    id: 1,
    name: '员工管理',
    children: [
      {
        id: 3,
        name: '添加员工',
        children: []
      },
      {
        id: 4,
        name: '删除员工',
        children: [
          {
            id: 6,
            name: '按姓名删除',
            children: []
          },
          {
            id: 7,
            name: '按工号删除',
            children: []
          }
        ]
      }
    ],
  },
  {
    id: 2,
    name: '菜单管理',
    children: [
      {
        id: 5,
        name: '修改菜单',
        children: []
      }
    ],
  },
];

样式如下:

const styles = StyleSheet.create({
  sidebar: {
    width: 200,
    backgroundColor: 'rgba(0,0,0,.3)',
  },
  title: {
    padding: 5,
    textAlign: 'center',
    color: '#fff',
    fontSize: 18,
  },
  item: {
    backgroundColor: '#012658',
  }
});

辅助函数:

const arr2tree = (data, pid) => {
  let result = [], temp;
  for (let i = 0; i < data.length; i++) {
    if (data[i].pid == pid) {
      let obj = {"name": data[i].name, "id": data[i].id, "pid": data[i].pid};
      temp = arr2tree(data, data[i].id);
      if (temp.length > 0) {
        obj.children = temp;
      } else {
        obj.children = [];
      }
      result.push(obj);
    }
  }
  return result;
};

组件如下:

import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, TouchableOpacity} from 'react-native';

function Menu() {
  const [tree, setTree] = useState([]);
  
  useEffect(() => {
    let tree = arr2tree(data1, 0);
    setTree(tree);
  }, []);
  
  const onPress = (menuObj) => {
    console.log(menuObj);
    // 在这里操作data1或者tree1
  };
  
  const createMenu = (menuObj) => {
    let vdom = [];
    if (menuObj instanceof Array) { // 子级菜单
    let list = [];
      for (let item of menuObj) {
        list.push(createMenu(item));
      }
      vdom.push(
        <View style={styles.item} key={Date.now()}>
          {list}
        </View>
      );
    } else { // 父级菜单
      vdom.push(
        <View key={menuObj.id}>
          <TouchableOpacity onPress={() => onPress(menuObj)}>
            <Text style={styles.title}>{menuObj.name}</Text>
          </TouchableOpacity>
          {createMenu(menuObj.children)}
        </View>
      )
    }
    return vdom;
  };
  
  return (
    <View style={styles.sidebar}>
      {createMenu(tree)}
    </View>
  )
}

目前进度:点击每一项,可以取到当前项数据,但是,怎么实现显示/隐藏,还在思考。
朋友们有没有什么好办法?

阅读 2.3k
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题