Vue 垂直菜单设计思路分析

发布于 2021-12-12 21:45:46 字数 3056 浏览 1220 评论 0

有这样一个需求,左侧菜单点击展开右侧菜单,右侧菜单点击又可以垂直展开第三级菜单,为了展开第三级,第二级的菜单中设计了添加一个变量用于控制展开和收起的状态,无样式的代码如下:


<body>
  <div id="app">
      <nav>
        <ul class="first-menu">
          <li v-for="(item,index) in menus" :key="item.name" @click="setSecondMenu(item)"> {{item.text}} </li>
        </ul>
        <ul class="second-menu">
          <li v-for="right in secondMenus" :key="right.name" @click="toggleThirdMenu(right)">
            {{right.text}}:{{right.expand}}
          </li>
        </ul>
      </nav>

  </div>

  <script>
    var app = new Vue({
      el: '#app',
      data() {
        let menus = [{
          text: "产品",
          name: "product",
          children: [{
            name: "product_manage",
            text: "产品方案管理"
          }, {
            name: "activity_manage",
            text: "市场活动管理"
          }],

        }, {
          name: "sales",
          text: "销售",
          children: [{
            name: "customer_manage",
            text: "客户管理"
          }],
        }];
        return {
          menus,
          secondMenus: [],
        }
      },
      methods: {
        setSecondMenu(menu) {
          menu.children.forEach(d => d.expand = false)
          this.secondMenus.splice(0);
          this.secondMenus.push(...menu.children);
        },
        toggleThirdMenu(menu) {
          menu.expand = !menu.expand;
        }
      }
    })
</script>
</body>

在点击了第一级的菜单后,我们给第二级的菜单进行赋值,在赋值前给菜单设置了 expand: false 的初始值。再点击第二级菜单的时候,期望修改 expand 的值,来达到伸缩第三级的目的,但实际发现 expand 在界面上根本没有生效,菜单上始终展示的是false。

最后调试的结果基本可以确定:在 menus 中已经对数据进行了侦听,再将其中对象的children设置expand:false 并且赋值给secondMenus,Vue不会对新增加的expand的字段进行侦听。因为menus中的侦听,已经包含了对该子结构的侦听

解决办法有多种:

(1)在 menus 中定义所有的需要使用 expand 的结构中,增加 expand:false,从而一开始就会侦听

let menus = [{
  text: "产品",
  name: "product",
  children: [{
    name: "product_manage",
    expand: false,
    text: "产品方案管理"
  }, {
    name: "activity_manage",
    expand: false,
    text: "市场活动管理"
  }],

}, {
  name: "sales",
  text: "销售",
  children: [{
    name: "customer_manage",
    expand: false,
    text: "客户管理"
  }],
}];

(2)在设置 secondMenus 的时候,不要直接使用 menus 中的数据,而是进行复制后再给 secondMenus,从而让 Vue 进行新的侦听:

setSecondMenu(menu) {
  let menus = menu.children.map(d => Object.assign({expand: false}, d));
  this.secondMenus.splice(0);
  this.secondMenus.push(...menus);
},

(3)是否可以通过 $set 方式来给 secondMenus 中需要出发改变的对象来赋值呢?答案是可以的:

toggleThirdMenu(menu) {
    this.$set(menu, 'expand', !menu.expand);
}

最后发现一个比较有意思的地方,第三个解决方案中我们将如下代码进行修改,会发现更改不再生效:

toggleThirdMenu(menu) {
  menu.expand = !menu.expand;
  console.log('menu.expand = ' + menu.expand)
  this.$set(menu, 'expand', menu.expand);
}

尽管随机进行的 console 发现是改变后的值,但是在 $set 的设置无效。可能需要对原理有更深的理解才能解释。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

秋意浓

暂无简介

文章
评论
513 人气
更多

推荐作者

qq_VRzBBA45

文章 0 评论 0

痴情

文章 0 评论 0

文章 0 评论 0

Mu.

文章 0 评论 0

凉薄对峙

文章 0 评论 0

不落城

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文