<div id="app">
	<input type="text" v-model="text" @keyup.enter="add">
	<button v-on:click="add">新增</button>
	<todo-list v-bind:lists="lists" v-bind:active-class="activeClass"></todo-list>
</div>
<script type="text/x-template" id="todolistTemp">
	<div>
		<ul v-bind:class="activeClass">
			<li v-for="(list, index) in lists" :key="index">
				<template v-if="!list.isEdit">
					<span v-bind:class="{done: list.isDone}" v-on:dblclick.prevent="edit(index)">{{list.text}}</span>
					<a href="#" v-on:click="toggleDone(index)" v-if="!list.isDone">完成</a>
					<a href="#" v-on:click="toggleDone(index)" v-else>撤回</a>
					<a href="#" v-on:click="remove(index)">删除</a>
				</template>
				<template v-else>
					<input type="text" v-model="list.editText" @keyup.enter="editInput(index)" v-select>
					<button v-on:click="editInput(index)">修改</button>
				</template>
			</li>
		</ul>
		<div>当前一共有 {{lists.length}} 条 todo-list,{{undoLen}} 条未完成,{{lists.length - undoLen}} 条已完成</div>
	</div>
</script>
.active{
	font-size: 18px;
}
.done{
	text-decoration: line-through;
	color: #999;
}
Vue.component('todo-list', {
	// 选项
	props: ['lists', 'activeClass'],
	template: '#todolistTemp',
	// 注册局部指令
	directives: {
		select: {
			inserted: function(el){
				el.select();
			}
		}
	},
	computed: {
		undoLen: function(){
			var len = 0;
			this.lists.map(function(list){
				if(!list.isDone){
					len += 1;
				}
			});
			return len;
		}
	},
	// 事件
	methods: {
		edit: function(index){
			if(!this.lists[index].isDone){
				this.lists[index].editText = this.lists[index].text;
				this.lists[index].isEdit = true;
			}
		},
		editInput: function(index){
			this.lists[index].text = this.lists[index].editText;
			this.lists[index].isEdit = false;
		},
		remove: function(index){
			this.lists.splice(index, 1);
		},
		toggleDone: function(index){
			this.lists[index].isDone = this.lists[index].isDone ? false : true;
		}
	}
});

var data = {
	text: '',
	lists: [],
	activeClass: 'active'
};
var app = new Vue({
	el: '#app',
	data: data,
	methods: {
		add: function(){
			if(this.text != ''){
				var newList = {
					text: this.text,
					isDone: false,
					isEdit: false
				};
				this.lists.push(newList);
				this.text = '';
			}
		}
	}
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js