Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

如何修改vue数组的值?

代码如下:

<template>
  <div style="display:flex; align-items:center;">
    <div class="left">
      <div v-for="(l, index) in lists" :key="l.id" @click="choose(index)">
        <input type="checkbox" :checked="l.checked">
        <span>{{l.name}}-{{l.side}}</span>
      </div>
    </div>
    <div class="switch" style="margin:0 20px;">
      <div @click="toLeft" style="width:20px;height:20px;border:1px solid #ccc;margin-top:10px;">《</div>
      <div @click="toRight" style="width:20px;height:20px;border:1px solid #ccc;margin-top:10px;">》</div>
    </div>
    <div class="right">
      <div v-for="(l, index) in right" :key="l.id" @click="choose(index)">
        <input type="checkbox" :checked="l.checked">
        <span>{{l.name}} {{l.side}}</span>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      lists: [
        {
          id: 1,
          name: 'list1'
        },
        {
          id: 2,
          name: 'list2'
        },
        {
          id: 3,
          name: 'list3'
        },
        {
          id: 4,
          name: 'list4'
        },
        {
          id: 5,
          name: 'list5'
        },
        {
          id: 6,
          name: 'list6'
        },
        {
          id: 7,
          name: 'list7'
        },
        {
          id: 8,
          name: 'list8'
        }
      ]
    }
  },
  computed: {
    left() {
      return this.lists.filter(el => el.side === 'left')
    },
    right() {
      return this.lists.filter(el => el.side === 'right')
    }
  },
  methods: {
    choose(index) {
      this.lists[index].name = 'ceshi'
      this.lists[index].side ='out'
      this.lists[index].checked = !this.lists[index].checked
      // this.$set(this.lists, index, this.lists[index])
    },
    toLeft() {

    },
    toRight() {

    }
  },
  mounted() {
    this.lists.forEach((el, index) => {
      el.checked = false
      el.side = 'left'
      console.log(el)
      this.$set(this.lists, index, el)
    });
  },
}
</script>

组件初始化的时候在mounted中为lists添加的两个属性值,并使用$set设置为响应式数据,当我点击左侧数据执行choose事件时,如果我注释掉choose事件的第一行,后面两行的sidechecked修改不会触发视图的更新,必须再使用$set。但是如果放开第一行,就可以直接触发视图更新,不需要再使用$set

这是什么情况呢?我在初始化的时候使用$set注册成响应式数据了呀,为什么不能直接修改sidechecked的值呢?
而且我修改的name的值后就可以直接修改了呢、?

使用的是vue快速原型开发vue-cli4, node10V+


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

因为你set方法用错了, 你进去set方法就知道了

function set (target, key, val) {
    ...
    
    // 像你代码里面那样调用, 只会进入这个分支, 只是简单的替换下下而已
    if (Array.isArray(target) && isValidArrayIndex(key)) {
      target.length = Math.max(target.length, key);
      target.splice(key, 1, val);
      return val
    }
    
    ...
  }

你声明lists的时候直接写上 checkedside这两个数值不就好了,干嘛还得用set

如果你非要用Vue.set, 那就像下面这样咯

this.lists.forEach((el, index) => {
    this.$set(this.lists[index], 'checked', false)
    this.$set(this.lists[index], 'side', 'left')
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...