Vue.js 双向绑定的BUG

初学vue时做了一个todo-list的demo,遇到了双向绑定的疑惑

先上代码:


     <div id="todo-list">
        <div class="container">
        <form class="form-inline" role="form"  @submit.prevent>
        <div class="form-group">
          <legend class="control-label" for="todo">待做事项</legend>
          <input class="form-control" type="text" placeholder="请添加新项目" v-model="inputItem">
            <div class="btn btn-info" @click="addItem" @keyup.enter="addItem">添加事项</div>
            <div class="btn btn-danger" @click="removeList">清空事项</div>
          </form>
          </div>
          <ul class="list-group">
            <li class="list-group-item" v-for="item in list">           <p>{{item.isFinished}}</p>
            <span v-show="item.isFinished" class="btn btn-sm btn-success"  @click="finished(item)">已完成</span>
            <span v-show="!item.isFinished" class="btn btn-sm btn-danger" @click="finished(item)">待完成</span>
            <span class="item" :class="{isFinished:item.isFinished}">{{item.name}}</span>
            <span class="btn btn-warning right btn-sm" @click="reomoveItem(item)">删除</span> 
            </li>        
          </ul>
      </div>
      </div>
var todoList = new Vue({
  el:"#todo-list",
  data:{
    item:{
      id:"",
      name:"",
      isFinished:""
    },
    list:[
      {
        id:1,
        name:"吃饭",
        isFinished:false,
      },
      { 
        id:2,
        name:"睡觉",
        isFinished:false,
      },
      { 
        id:3,
        name:"打豆豆",
        isFinished:true,
      }
    ],
    inputItem:""
  },
  methods:{
    addItem:function(){
      if(!this.inputItem) return;
      this.item.name = this.inputItem;
      this.item.isFinished = false;
      this.item.id = this.list.length + 1;
      this.list.push(this.item);
      this.item = {};
      this.inputItem = "";
    },
    reomoveItem:function(item){
      console.log(1);
      this.list.$remove(item);
    },
    removeList:function(){
      this.list = [];
    },
    finished:function(item){
      item.isFinished = !item.isFinished;
      console.log(this.list)
    }
  }
});

demo

Bug的具体表现如下:

新添加的item,除了第一个以外其他都不能进行状态切换。但原先的item与新添加的第一个item则可以。

尝试解决方法:

我在click事件函数中console.log()整个ul,发现子对象的isFinished属性都能够切换,那我推测问题出在了js向html传递的过程中,但是我还是没想明白为什么会导致这种问题

阅读 4.6k
2 个回答

问题是js对象和vue对象混用导致的。
这行代码,this.list.push(this.item);中this.item是一个vue对象,不是一个js数组。把代码换一下就可以了

      var aaaaaa={
        id:this.list.length + 1,
        name:this.inputItem,
        isFinished:false
      };
      this.list.push(aaaaaa);

我运行了代码,不是不能切换,只是不能马上渲染出结果。
这是我改了的代码,测试了下可以正常运行:

addItem:function(){
  if(!this.inputItem) return;
  this.item.name = this.inputItem;
  this.item.isFinished = false;
  this.item.id = this.list.length + 1;
  this.list.push(this.item);
  this.item = {
    id:"",
    name:"",
    isFinished:""
  };
  this.inputItem = "";
}

是这样的,在对象中直接添加新的属性是不会引起页面的重新渲染的。题主看看文档的“深入相应---变化检测”这一节应该就明白了。

这种情况我还有一种处理方法,就是对数组调用一次splice方法,对于题主的场景是这样的:

finished:function(item){
  item.isFinished = !item.isFinished;
  this.list.splice(0,0);
  console.log(this.list)
}

这样写finished的话,就不用修改addItem方法了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题