发新贴  快速回复

vue 中 todo-list的 enter和blur 处理编辑完成的问题

路遥知马力
2018-09-12 19:58

练习老师讲的vue的todo-list时发现一个问题,老师的课件里也有这个问题。

当同时都有@keyup.enter 和 @blur 表示编辑完成执行函数时,@keyup.enter会同时删除两个。@blur没问题

附件下载:
 
 
2017年2月8日

这个案例要怎么按回车删除

2018-09-13 09:51  回复本帖
路遥知马力

双击打开编辑后,如果内容为空,失去焦点或点击enter键,就默认删除

2018-09-13 15:25  回复本帖
 
2017年2月8日

路遥知马力 2018-09-13 15:25发表的内容:

双击打开编辑后,如果内容为空,失去焦点或点击enter键,就默认删除

最后一个双击编辑,内容为空,按下回车键的时候,不仅触发了键盘事件,也触发了blur事件。
2018-09-13 17:44  回复本帖
路遥知马力

对呀,就是这个问题,但是就算是进行两次删除,也只是删除title为空的,也不应该删除两条呀。有没有解决办法。

2018-09-13 19:14  回复本帖
 
2017年2月8日

路遥知马力 2018-09-13 19:14发表的内容:

对呀,就是这个问题,但是就算是进行两次删除,也只是删除title为空的,也不应该删除两条呀。有没有解决办法。

我先说下原因,按下键盘,删除,由于删除了,元素也失去了光标,固会触发keyup事件和blur事件。而这两个事件传进去的都是同一个item,固它们的title都是空,都会走if。然后findIndex找到的会返回找到的索引值,找不到的会返回-1,而数组方法splice中的-1是从最后一位查找,固也能找到,所以都是删除最后一个,两次事件就会删除两个。
如果修正,我的做法是,判断到是keyup事件,直接return掉,然后手动触发blur事件,具体看我下面的代码。

2018-09-14 09:53  回复本帖
 
2017年2月8日
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>todos</title>
    <link rel="stylesheet" type="text/css" href="css/base.css">
    <link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<style>
    [v-cloak] {
        display: none;
    }
</style>

<body>
    <section class="todoapp" id="app" v-cloak>
        <div>
            <header class="header">
                <h1>todos</h1>
                <input class="new-todo" placeholder="请输入内容" v-model="todoVal" @keyup.enter="addTodo" />
            </header>
            <section class="main" v-if="taskList.length">
                <input class="toggle-all" type="checkbox" v-model="isCheckedAll" />
                <ul class="todo-list">
                    <li :class="{completed : item.checked, editing : index === editIndex }" v-for="item,index of taskList">
                        <div class="view">
                            <input class="toggle" type="checkbox" v-model="item.checked" />
                            <label @dblclick="editTodo(index)">{{item.title}}</label>
                            <button class="destroy" @click="deleteTodo(index)"></button>
                        </div>
                        <input ref="editInp" class="edit" 
                            v-model="item.title" 
                            @keyup.enter="editDone($event,item)" 
                            @blur="editDone($event,item)" 
                            @keyup.esc="handleEscTodo(item)" 
                        />
                    </li>
                </ul>
            </section>
            <footer class="footer" v-if="taskList.length">
                <span class="todo-count">
                <strong>{{unCheckedLen}}</strong>
                <span>条未选中</span>
                </span>
                <ul class="filters">
                    <li><a href="#/all" class="selected">All</a></li>
                    <li><a href="#/active" class="">Active</a></li>
                    <li><a href="#/completed" class="">Completed</a></li>
                </ul>
            </footer>
        </div>
    </section>
</body>
<script src="js/vue.js"></script>
<script>
var off=true;
    new Vue({
        el: '#app',
        data: {
            todoVal: '',
            editIndex: -1,
            beforeEidt: '',
            taskList: []
        },
        methods: {
            addTodo() {
                this.taskList.push({
                    title: this.todoVal,
                    id: Date.now() + Math.random(),
                    checked: false
                })
                this.todoVal = '';
            },
            deleteTodo(index) {
                this.taskList.splice(index, 1);
            },
            editTodo(index) {
                this.beforeEidt = this.taskList[index].title;
                this.editIndex = index;
                this.$nextTick(() => {
                    this.$refs['editInp'][index].focus();
                })
            },
            editDone(e,item){
				if(e.type=='keyup'){//判断是键盘
					e.target.blur();
					return;
				}
				if( item.title === '' ){
					let posIndex = this.taskList.findIndex( option => option === item );
					this.deleteTodo(posIndex)
				}
				this.editIndex = -1;
            },
            handleEscTodo(item) {
                item.title = this.beforeEidt;
                this.editIndex = -1;
            }
        },
        computed: {
            isCheckedAll: {
                get() {
                    return this.taskList.every(item => {
                        return item.checked;
                    })
                },
                set(value) {
                    this.taskList.forEach(item => {
                        item.checked = value;
                    })
                }
            },
            unCheckedLen(){
                return this.taskList.filter( item => item.checked === false ).length;
            }
        }
    });
</script>
</html>

 

2018-09-14 09:53  回复本帖
路遥知马力

2017年2月8日 2018-09-14 09:53发表的内容:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>todos</title>
    <link rel="stylesheet" type="text/css" href="css/base.css">
    <link rel="stylesheet" type="text/css" href="css/index.css">
</head>
<style>
    [v-cloak] {
        display: none;
    }
</style>

<body>
    <section class="todoapp" id="app" v-cloak>
        <div>
            <header class="header">
                <h1>todos</h1>
                <input class="new-todo" placeholder="请输入内容" v-model="todoVal" @keyup.enter="addTodo" />
            </header>
            <section class="main" v-if="taskList.length">
                <input class="toggle-all" type="checkbox" v-model="isCheckedAll" />
                <ul class="todo-list">
                    <li :class="{completed : item.checked, editing : index === editIndex }" v-for="item,index of taskList">
                        <div class="view">
                            <input class="toggle" type="checkbox" v-model="item.checked" />
                            <label @dblclick="editTodo(index)">{{item.title}}</label>
                            <button class="destroy" @click="deleteTodo(index)"></button>
                        </div>
                        <input ref="editInp" class="edit" 
                            v-model="item.title" 
                            @keyup.enter="editDone($event,item)" 
                            @blur="editDone($event,item)" 
                            @keyup.esc="handleEscTodo(item)" 
                        />
                    </li>
                </ul>
            </section>
            <footer class="footer" v-if="taskList.length">
                <span class="todo-count">
                <strong>{{unCheckedLen}}</strong>
                <span>条未选中</span>
                </span>
                <ul class="filters">
                    <li><a href="#/all" class="selected">All</a></li>
                    <li><a href="#/active" class="">Active</a></li>
                    <li><a href="#/completed" class="">Completed</a></li>
                </ul>
            </footer>
        </div>
    </section>
</body>
<script src="js/vue.js"></script>
<script>
var off=true;
    new Vue({
        el: '#app',
        data: {
            todoVal: '',
            editIndex: -1,
            beforeEidt: '',
            taskList: []
        },
        methods: {
            addTodo() {
                this.taskList.push({
                    title: this.todoVal,
                    id: Date.now() + Math.random(),
                    checked: false
                })
                this.todoVal = '';
            },
            deleteTodo(index) {
                this.taskList.splice(index, 1);
            },
            editTodo(index) {
                this.beforeEidt = this.taskList[index].title;
                this.editIndex = index;
                this.$nextTick(() => {
                    this.$refs['editInp'][index].focus();
                })
            },
            editDone(e,item){
				if(e.type=='keyup'){//判断是键盘
					e.target.blur();
					return;
				}
				if( item.title === '' ){
					let posIndex = this.taskList.findIndex( option => option === item );
					this.deleteTodo(posIndex)
				}
				this.editIndex = -1;
            },
            handleEscTodo(item) {
                item.title = this.beforeEidt;
                this.editIndex = -1;
            }
        },
        computed: {
            isCheckedAll: {
                get() {
                    return this.taskList.every(item => {
                        return item.checked;
                    })
                },
                set(value) {
                    this.taskList.forEach(item => {
                        item.checked = value;
                    })
                }
            },
            unCheckedLen(){
                return this.taskList.filter( item => item.checked === false ).length;
            }
        }
    });
</script>
</html>

 

忙了两天,刚看到回帖,亲测有效,多谢大佬!不过,ev.target操作的话,这不就操作到dom了吗?
2018-09-18 09:45  回复本帖
 
2017年2月8日

路遥知马力 2018-09-18 09:45发表的内容:

忙了两天,刚看到回帖,亲测有效,多谢大佬!不过,ev.target操作的话,这不就操作到dom了吗?
改操作DOM还得操作,我常常把vue和jquery一起用。
2018-09-18 09:48  回复本帖
登录 后才可以发表回复