Флажок vue не правильно связывает данные с помощью v-модели - PullRequest
0 голосов
/ 19 марта 2019

У меня есть список задач, в который вы можете добавить новую задачу, пометить каждую задачу как завершенную, щелкнув флажок, и выбрать видимость списка по всем, активным или завершенным в нижнем колонтитуле.

Когда явыберите «Завершено» в нижнем колонтитуле, отображается только завершенный элемент.

Проблема заключается в том, что при снятии отметки с завершенного элемента в завершенном виде флажок оставшегося (особенно следующего) элемента отображается неправильно.

var STORAGE_KEY = 'todo mvc by vue';
var todoStorage = {
    data: [],
    fetch: function () {
        
        return this.data;
    },
    save: function (data) {
        this.data = data;
        //localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
    }
}

var filters = {
    all: function (todos) {
        return todos;
    },
    active: function (todos) {
        return todos.filter(todo => !todo.completed);
    },
    completed: function (todos) {
        return todos.filter(todo => todo.completed);
    }
}

var app = new Vue({
    el: '.app',
    data: {
        todos: todoStorage.fetch(),
        newTodo: '',
        visiblitys: [{
            title: 'All',
            selected: true,
            filter: filters.all
        }, {
            title: 'Active',
            selected: false,
            filter: filters.active
        }, {
            title: 'Completed',
            selected: false,
            filter: filters.completed
        }]
    },
    computed: {
        todosForShow: function () {
            return this.currentFilter(this.todos);
        },
        currentFilter: function () {
            return this.visiblitys.find(v => v.selected).filter;
        }
    },
    watch: {
        todos: {
            handler: function (todos) {
                todoStorage.save(todos);
            },
            deep: true
        }
    },
    methods: {
        deleteItem: function (todo) {
            this.todos.splice(this.todos.indexOf(todo), 1);
        },
        deleteCompletedItem: function () {
            this.todos = filters.active(this.todos);
        },
        addItem: function (todo) {
            var value = this.newTodo && this.newTodo.trim();
            if (!value) return;

            this.todos.push({
                content: value,
                completed: false
            });
            this.newTodo = '';
        },
        selectVisiblity: function (visiblity) {
            this.visiblitys.forEach(vis => vis.selected = false);
            visiblity.selected = true;
        },
        completeAll: function () {
            this.todos.forEach(todo => todo.completed = true);
        }
    }
});
* {
    box-sizing: border-box;
}

header h1 {
    text-align: center;
}

.container {
    max-width: 800px;
    margin: 0 auto;
}

.new-todo {
    padding: 16px;
    box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
    font-size: 24px;
    width: 100%;
}

li.completed {
    text-decoration: line-through;
}

footer {
    border-top: 1px solid #e6e6e6;
    height: 20px;
    padding: 10px 15px;
    color: #777;
    text-align: center;
    position: relative;
}

.filters {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    left: 0;
    right: 0;
}

.filters li {
    display: inline;
}

.filters li a {
    margin: 3px;
    padding: 3px 7px;
    text-decoration: none;
    border: 1px solid transparent;
    border-radius: 3px;
    color: inherit;
}

.filters li a.selected {
    border-color: rgba(175, 47, 47, 0.2);
}

.todo-count {
    float: left;
    text-align: left;
}

.complete-all {
    float: right;
    cursor: pointer;
    position: relative;
    color: black;
}

.todo-list {
    clear: both;
}

.clear-completed {
    float: right;
    cursor: pointer;
    position: relative;
}

button {
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    font-size: 100%;
    vertical-align: baseline;
    font-family: inherit;
    font-weight: inherit;
    color: inherit;
    -webkit-font-smoothing: antialiased;
}
<header>
    <h1>Todos</h1>
  </header>
  <div class="app container">
    <input class="new-todo" type="text" v-on:keyup.enter="addItem()" v-model="newTodo"
      placeholder="What needs to be done?">
    <section class="main" v-show="todos.length > 0">
      <button class="complete-all" @click="completeAll()">Complete All</button>
      <ul class="todo-list">
        <li v-for="todo in todosForShow" :class="{completed: todo.completed}">
          <input type="checkbox" v-model="todo.completed">
          {{todo.content}} -
          <a href="#" @click.prevent="deleteItem(todo)">remove</a>
        </li>
      </ul>
      <footer>
        <span class="todo-count">{{todos.filter(t=>!t.completed).length}} items left</span>
        <ul class="filters">
          <li v-for="visiblity in visiblitys">
            <a href="#" :class="{selected: visiblity.selected}"
              @click.prevent="selectVisiblity(visiblity)">{{visiblity.title}}</a>
          </li>
        </ul>
        <button class="clear-completed" v-show="todos.some(t=>t.completed)" @click="deleteCompletedItem()">Clear
          Completed</button>
      </footer>
    </section>

    <br>todos raw data:{{this.todos}}
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
  1. начало list in all
  2. выберите завершенное в нижнем колонтитуле list only show completed item
  3. после снятия отметки с первого пункта after I uncheck the first item
...