ant-design-vue导航菜单a-menu的详细使用

本文详细介绍了Ant Design Vue的导航菜单组件`a-menu`的使用,重点解析了关键API如`defaultSelectedKeys`和`selectedKeys`的差异,以及在生成多级菜单时如何选择函数式组件的使用方式。注意,一级和二级菜单可通过普通循环生成,而三级及以上则建议使用函数式组件以遵循官方推荐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ant-design-vue导航菜单a-menu的详细使用


此文章包含了递归生成三级菜单,刷新状态保留,只展开一个父级菜单等常见问题。

一、效果

可以看到递归生成三级菜单,刷新状态保留,只展开一个父级菜单等常见问题得以解决。我自己的电脑设备老旧,反应缓慢的问题请忽略。
在这里插入图片描述

一、关键的API

说实话遇到问题了不知道该怎么解决,说白了还是不懂得API的使用,对相关的API不够了解,熟悉了API怎么操作都行。下面说说用到但是又容易混淆的API。

  • 1.defaultSelectedKeys 默认选中的key
    这里的key对应的是a-menu-item上面绑定的key,如果被选中,会进行导航的跳转以及被给予高亮状态。
  • 2.openKeys 展开的a-sub-menu的key
    这里的key对应的是a-sub-menu上面绑定的key。如果绑定在a-menu上,对应的子菜单会打开。
  • 3.selectedKeys 受控选中的key
    这里的key对应的是a-menu-item上面绑定的key,如果被选中,会进行导航的跳转以及被给予高亮状态。

与defaultSelectedKeys 有什么区别:
这两个属性为二选一使用,如果同时使用时,defaultSelectedKeys无效,将会以selectedKeys为准。
如果你只是希望指定一个初始化选中的菜单项,请使用defaultSelectedKeys;
如果你需要每次通过传入不同的props改变Menu组件的选中项,请使用selectedKeys。

二、注意事项

此处强调一点,如果是一级以及二级菜单的生成,普通的两层for循环结合递归以及v-if生成即可。如果是想使用a-menu生成三级或者三级以上的菜单,那么就需要定义在单文件内定义函数式组件。那为什么不推荐单文件的形式定义组件,而是使用函数式组件?以下是官方文档的说明:
在这里插入图片描述

三、代码

<template>
  <a-layout id="components-layout-demo-custom-trigger" style="height:100%">
    <a-layout-sider theme="light" v-model="collapsed" :trigger="null" collapsible>
      <div >
          <a-menu
            :inlineIndent="inlineIndent"
            :defaultSelectedKeys="[$route.path]"
            :openKeys="openKeys"
            mode="inline"
            :inline-collapsed="collapsed"
            @openChange="onOpenChange"
            @click="menuClick">
            <!-- 菜单遍历的开始 -->
            <template v-for="item in list">
              <!-- 如果当前遍历项没有children,视为子菜单项,注意所有的key都是path用于路由跳转,以及当前选中记录 -->
              <a-menu-item v-if="!item.children" :key="item.path">
                <i :class="item.icon" />
                <span>{{ item.title }}</span>
              </a-menu-item>
              <!-- 否则视为子菜单,传入菜单信息并且运用下面定义的函数式组件 -->
              <sub-menu v-else :key="item.path" :menu-info="item" />
            </template>
        </a-menu>
      </div>
    </a-layout-sider>
    <a-layout>
      <a-layout-content :style="{ margin: '24px 16px', padding: '24px', background: '#fff', minHeight: '280px' }">
        <router-view/>
      </a-layout-content>
    </a-layout>
  </a-layout>
</template>
<script>
import { Menu } from 'ant-design-vue';
// 定义函数式组件
const SubMenu = {
  template: `
      <a-sub-menu :key="menuInfo.path" v-bind="$props" v-on="$listeners">
        <span slot="title">
          <i :class="menuInfo.icon" /><span>{{ menuInfo.title }}</span>
        </span>
        <template v-for="item in menuInfo.children">
          <a-menu-item v-if="!item.children" :key="item.path">
            <i :class="item.icon" />
            <span>{{ item.title }}</span>
          </a-menu-item>
          <sub-menu v-else :key="item.path" :menu-info="item" />
        </template>
      </a-sub-menu>
    `,
  name: 'SubMenu',
  // must add isSubMenu: true 此项必须被定义
  isSubMenu: true,
  props: {
    // 解构a-sub-menu的属性,也就是文章开头提到的为什么使用函数式组件
    ...Menu.SubMenu.props,
    // 接收父级传递过来的菜单信息
    menuInfo: {
      type: Object,
      default: () => ({}),
    },
  },
};
export default {
  data() {
    return {
      // 菜单缩进
      inlineIndent:12,
      // 默认不折叠
      collapsed: false,
      // 全部顶级父节点,用来控制所有父级菜单只展开其中的一项,可用遍历菜单信息进行赋值
      rootSubmenuKeys: ['/infomationManage','/safeInfoManage','/qualityInfoManage'],
      // 展开的父菜单项
      openKeys: [], 
      // 选中的子菜单项
      defaultSelectedKeys: [this.$route.path], 
      // 菜单信息,可从后台获取
      list: [
        {
          key: '1',
          title: '项目信息管理',
          path: '/infomationManage',
          icon:'iconfont icon-information'
        },
        {
          key: '2',
          title: '安全信息管理',
          path: '/safeInfoManage',
          icon:'iconfont icon-anquan',
          children: [
            {
              key: '2.1',
              title: '安全风险管理',
              path: '/safeRisk',
              icon:'',
              children: [
                { 
                  key: '2.1.1',
                  title: '风险分类管理',
                  path: '/riskClassifyManage',
                  icon:'',
                },
                {
                    key: '2.1.2',
                    title: '分类辨识',
                    path: '/classifyIdentity',
                    icon:'',
                }
              ],
            },
          ],
        },
        {
          key: '3',
          title: '质量信息管理',
          path: '/qualityInfoManage',
          icon:'iconfont icon-zhiliang',
          children:[
              {
                  key: '3.1',
                  title: '质量控制点管理',
                  path: '/controlPointManage',
                  icon:'',
              }
          ]
        }
      ],
    }
  },
  created(){
    // 将从缓存中取出openKeys
    const openKeys = window.sessionStorage.getItem('openKeys')
    if(openKeys){
      // 存在即赋值
      this.openKeys = JSON.parse(openKeys)
    }
  },
  methods: {
    // 点击菜单,路由跳转,注意的是当点击MenuItem才会触发此函数
    menuClick({ item, key, keyPath }) {
      // 获取到当前的key,并且跳转
      this.$router.push({
        path: key
      })
    },
    onOpenChange(openKeys) {
      // 将当前打开的父级菜单存入缓存中
      window.sessionStorage.setItem('openKeys', JSON.stringify(openKeys))
      //  控制只打开一个
      const latestOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1);
      if (this.rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
        this.openKeys = openKeys;
      } else {
        this.openKeys = latestOpenKey ? [latestOpenKey] : [];
      }
    },
  },
  // 注册局部组件
  components: {
    'sub-menu': SubMenu,
  },
};
</script>
<style>
</style>
<think>好的,用户现在在问关于在RT-Thread系统中驱动GT911触摸屏的信息或教程,以及示例代码。我需要先回顾一下RT-Thread的文档和相关组件。记得RT-Thread有一个传感器框架,可能触摸屏驱动会集成在这里。另外,用户之前提到的GT9147示例,可能GT911的驱动方式类似,都是通过I2C通信,注册为触摸设备。 首先,检查RT-Thread的官方文档或者GitHub仓库,看看是否有GT911的驱动支持。可能GT911和GT9147都属于Goodix的触摸芯片,驱动代码结构可能相似。需要确认硬件连接,比如I2C接口的引脚配置,中断引脚和复位引脚的使用。 然后,用户可能需要配置board.h中的相关宏定义,比如I2C总线名称、设备地址、中断引脚号等。示例代码可能包括初始化函数、中断处理、读取坐标数据等部分。此外,RT-Thread可能使用rt_touch框架,所以需要注册touch设备,并实现open、close、control等操作。 另外,用户提到的引用中有关littlevgl2rtt项目,说明可能需要与LittlevGL图形库集成,所以驱动成功后,触摸数据会被传递到GUI部分。需要注意配置正确的分辨率和触摸点数量。 用户可能遇到的问题包括I2C通信失败、中断无法触发、坐标数据不正确等,需要建议他们检查硬件连接、配置参数,以及使用i2c工具进行测试。同时,参考GT9147的示例代码进行适配,因为两者驱动方式可能相似,只需修改部分寄存器地址或初始化序列。 最后,生成相关问题,帮助用户进一步解决可能遇到的调试问题、配置步骤或与其他组件的集成。</think>在RT-Thread系统中驱动GT911触摸屏的开发可分为以下关键步骤,基于其传感器框架和触摸设备驱动模型: ### 一、硬件配置要点 1. 确认开发板的I2C接口定义,GT911通常需要连接: - SCL/SDA(I2C时钟/数据线) - INT(中断信号引脚) - RST(复位控制引脚) 2. 在`board.h`中配置设备地址,GT911默认地址为$0x5D$或$0x14$(根据TS引脚电平) ### 二、驱动移植示例代码 ```c #include <rtdevice.h> #define GT911_ADDR 0x5D #define GT911_INT_PIN GET_PIN(C, 5) #define GT911_RST_PIN GET_PIN(C, 6) static void gt911_irq_handler(void *args) { rt_touch_irq_handler((rt_device_t)args); } static struct rt_touch_ops gt911_ops = { .touch_readpoint = gt911_read_point, .touch_control = gt911_control }; int rt_hw_gt911_init(void) { struct rt_touch_config cfg; cfg.dev_name = "i2c1"; // 指定I2C总线 rt_touch_t touch_dev = rt_calloc(1, sizeof(struct rt_touch_device)); touch_dev->info.type = RT_TOUCH_TYPE_CAPACITANCE; touch_dev->info.vendor = RT_TOUCH_VENDOR_GT911; touch_dev->ops = &gt911_ops; rt_pin_mode(GT911_INT_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_attach_irq(GT911_INT_PIN, PIN_IRQ_MODE_FALLING, gt911_irq_handler, touch_dev); rt_hw_touch_register(touch_dev, "gt911", RT_DEVICE_FLAG_INT_RX, &cfg); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_gt911_init); ``` ### 三、关键开发要点 1. **中断处理**:需要实现坐标数据的读取和上报,建议使用`rt_touch_irq_handler`作为中断入口 2. **寄存器配置**:需按照数据手册初始化触摸芯片,包含: ```c static rt_err_t gt911_control(rt_device_t dev, int cmd, void *args) { switch (cmd) { case RT_TOUCH_CTRL_GET_ID: i2c_read_reg(GT911_PRODUCT_ID_REG, id_buf, 4); break; case RT_TOUCH_CTRL_SET_X_RANGE: gt911_set_reg(GT911_X_RANGE_REG, *(rt_uint16_t*)args); break; } return RT_EOK; } ``` 3. **坐标解析**:在`gt911_read_point`函数中需要处理原始数据包,通常包含$5$个触控点的$X/Y$坐标(每个坐标用$2$字节表示) ### 四、调试方法 1. 使用`i2c-tools`工具验证I2C通信 ```shell msh > i2c probe 1 # 扫描i2c1总线 msh > i2c read 1 0x5D 0x8140 2 # 读取产品ID ``` 2. 查看触摸设备注册状态 ```shell msh > list_device touch gt911 # 应显示已注册设备 ``` 3. 使用`touch_test`命令验证数据流 ```shell msh > touch_test gt911 [398,288] [press] # 将显示实时坐标 ``` ### 五、GUI集成 与LittlevGL图形库对接时,需在`lv_port_indev_init`中设置输入设备: ```c rt_device_t touch = rt_device_find("gt911"); lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = rt_touch_read_callback; lv_indev_drv_register(&indev_drv); ``` 相关问题
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值