美文网首页
Vue数据变动侦听不到的问题

Vue数据变动侦听不到的问题

作者: tangyefei | 来源:发表于2019-06-04 15:16 被阅读0次
data-binding.png

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


<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的设置无效。可能需要对原理有更深的理解才能解释。

相关文章

  • Vue数据变动侦听不到的问题

    有这样一个需求,左侧菜单点击展开右侧菜单,右侧菜单点击又可以垂直展开第三级菜单,为了展开第三级,第二级的菜单中设计...

  • 第23周技术周报

    1. Vue中数据变动侦听不到的问题 有一种情况可能略微复杂一点,假定我们有如下数据: 进行某些操作以后,用lis...

  • vue学习之watch与computed的比较

    vue提供了一种通用的方式来观察和响应vue实例上的数据变动:侦听属性。当有一些数据需要随着其他数据变动而变动时,...

  • vue的计算属性 vs 侦听属性

    Vue提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而...

  • 关于Vue为什么不能检测数组变动

    文章出处:链接 问题来源:链接 Vue检测数据的变动是通过Object.defineProperty实现的,所以...

  • 聊聊vue的计算属性computed与侦听器watch

    聊聊vue的计算属性和帧听器 vue的计算属性computed和侦听器watch都是监听数据变化。 compute...

  • vue-nextTick原理

    vue官网:可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列...

  • 2019-01-26

    # VUE的计算属性,方法,侦听器 (1)计算属性,方法,侦听器 ``` {{fullName}} {{fullN...

  • Vue前端面试2021-015

    1、什么是侦听器? 侦听器是Vue中的一个对象,主要用于监听实例中指定变量的数据是否发生更新的处理模块,在实例中通...

  • Watch监听

    侦听器,监听数据的变化,基础用法在vue中,使用watch来响应数据的变化。watch的用法大致有三种。 1、下面...

网友评论

      本文标题:Vue数据变动侦听不到的问题

      本文链接:https://www.haomeiwen.com/subject/ylzlxctx.html