Vue3问题:如何实现级联菜单的数据懒加载?

前端功能问题系列文章,点击上方合集↑

序言

大家好,我是大澈!

本文约3100+字,整篇阅读大约需要5分钟。

本文主要内容分三部分,第一部分是需求分析,第二部分是实现步骤,第三部分是问题详解。

如果您只需要解决问题,请阅读第一、二部分即可。

如果您有更多时间,进一步学习问题相关知识点,请阅读至第三部分。

1. 需求分析

实现级联菜单效果,点击一级菜单某一项,就会加载出对应的二级菜单内容,点击二级菜单某一项,就会加载出对应的三级菜单内容,以此类推,最后一级为五级菜单。

对于加载而言,必须是懒加载效果,即点击菜单某一项时,才会真正去请求加载对应的下一级菜单内容。

对于菜单最后一级内容,要插入一个输入框,在输入框内,用户可以任意输入版本号,并且要求输入框不可被选中。

当然,我们的正题是数据的懒加载,级联菜单中插入不可被选中的输入框实现算是附加内容了。

Vue3问题:如何实现级联菜单的数据懒加载?_第1张图片

Vue3问题:如何实现级联菜单的数据懒加载?_第2张图片

2. 实现步骤

2.1 为什么要使用数据懒加载

在项目中,我们使用数据的懒加载,会有如下好处

  • 提升用户体验

  • 减少初始加载时间

  • 减轻网络资源的消耗

了解了这些好处之后,再就是要了解数据懒加载的应用场景。

这部分比较有用,所以多叙述一些。

数据懒加载在以下场景中特别有用:

  • 长列表或分页数据:当你有一个包含大量数据的列表或分页功能时,可以使用数据懒加载来延迟加载列表项或分页数据。只有当用户滚动到可见范围时才加载新的数据,从而提高初始加载速度和响应性能。

  • 图片或媒体资源:对于包含大量图片或媒体资源的页面,可以使用数据懒加载来延迟加载这些资源。只有当图片或媒体元素进入视口时才进行加载,从而减少初始加载时间和网络资源的消耗。

  • 条件性加载:当一些数据或组件只在特定条件下才需要显示或使用时,可以使用数据懒加载。根据条件动态加载数据或组件,避免不必要的加载和资源占用。

  • 路由级别的懒加载:在Vue的路由中,可以使用懒加载来按需加载路由组件。只有当用户访问某个路由时才进行组件的加载,提高初始加载速度和路由切换的性能。

  • 异步加载模块:对于大型的Vue项目,可以使用数据懒加载来异步加载模块,减少初始加载时间。将模块分割成小块,并在需要时按需加载,提高应用的性能和可维护性。

上述场景在此部分只做简单描述,如果你有空余时间,各个场景具体代码实例请见第三部分总结。

我们这次的需求实现,就是符合第1条场景。

2.2 数据懒加载代码实例

当选中某一级时,动态加载该级下的选项。

通过lazy开启动态加载,并通过lazyload方法来设置加载数据源。

  • lazyload方法有两个参数,第一个参数node为当前点击的节点,第二个resolve为数据加载完成的回调(必须调用)。

  • node可以解构出level参数,它从0开始计数,指明当前点击节点的层级。

  • 为数据对象添加leaf属性,是为了指明哪一级的对象是叶子节点。

模板代码:


逻辑代码:


  // 级联面板配置项
  const props = reactive({
    // 开启懒加载
    lazy: true,
    // 懒加载加载数据源方法
    async lazyLoad(node, resolve) {
      const { level } = node;

      // 已经有数据了,不需要重复请求了
      if (node.children && node.children.length > 0) return;

      // 模拟掉接口
      setTimeout(() => {
        let result;
        switch (level) {
          case 0: // 一级目录
            result = [
              {
                value: "0",
                label: "行内转账-手机号",
                children: []
              },
              {
                value: "1",
                label: "行内转账-银行账号",
                children: []
              },
              {
                value: "2",
                label: "汇款到当地银行",
                children: []
              },
              {
                value: "3",
                label: "汇款到钱包",
                children: []
              },
              {
                value: "4",
                label: "转账到CUPD",
                children: []
              }
            ];
            break;
          case 1: //二级目录
            // 省略此处代码...
            
            break;
          case 2: //三级目录
            // 省略此处代码...

            break;
          case 3: //四级目录
            // 省略此处代码...

            break;
          case 4: // 五级目录
            result = [
              {
                value: "最低系统版本",
                label: "最低系统版本要求"
              },
              {
                value: "0",
                label: "不启用"
              },
              {
                value: "1",
                label: "内测"
              },
              {
                value: "2",
                label: "上线"
              }
            ];

            // 设置五级菜单为叶子节点,无子节点
            result.forEach((item) => {
              item.leaf = level >= 4;
            });
            break;
          default:
            result = [];
            break;
        }

        resolve(result);
      }, 1000);
    }
  });

2.3 插入输入框代码实例

通过插槽和条件判断,在级联面板中插入输入框,其中data.label为节点对象的名称。

通过@click.stop阻止事件冒泡、宽度为父元素的100%、以及清除级联面板组件一些默认样式,实现了输入框不可被选中的效果。

模版代码:


      

样式代码:


.el-cascader-panel.is-bordered {
    border: none;
  }
.el-cascader-menu:last-child .el-cascader-node:nth-of-type(1):has(.searchText) {
  margin-bottom: 30px;
  padding: 0;
  &:hover,
  &:focus {
    background: #fff;
  }
}
.el-cascader-menu__list {
  padding: 20px 0;
}

3. 问题详解

3.1 关于CascaderProps配置项的参数一览

Vue3问题:如何实现级联菜单的数据懒加载?_第3张图片

3.2 懒加载各个场景代码实例总结

长列表或分页数据懒加载:



图片懒加载:



条件性数据懒加载:



路由懒加载(基于 Vue Router):

const Home = () => import('./components/Home.vue');
const About = () => import('./components/About.vue');
const Contact = () => import('./components/Contact.vue');

const routes = [
  { path: '/home', component: Home },
  { path: '/about', component: About },
  { path: '/contact', component: Contact },
];

const router = new VueRouter({
  routes,
});

异步加载模块(基于 import() 动态导入语法):



结语

建立这个平台的初衷:

  • 打造一个仅包含前端问题的问答平台,让大家高效搜索处理同样问题。

  • 通过不断积累问题,一起练习逻辑思维,并顺便学习相关的知识点。

  • 遇到难题,遇到有共鸣的问题,一起讨论,一起沉淀,一起成长。

感谢关注微信公众号:“程序员大澈”,然后加入问答群,让我们一起解决实现所有BUG!

你可能感兴趣的:(前端问题合集,vue.js,javascript,css,html,前端)