个人的奋斗还是历史的进程?
本例全部是在一个HTML文件中完成的
参考: vue官网的TODO例子
效果图:

使用到的vue概念: 数据驱动,指令
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<!--通过第三方CDN引入vue.js-->
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<!--新增根节点,通过mustache模板语法展示newtodo的值-->
<div id="app"></div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var app = new Vue({
//使用el属性传入css选择器绑定根节点
el: '#app',
//使用data属性传入对象,对象内自定义属性newtodo传入待办内容
data: {
newtodo: '我系渣渣辉'
}
});
</script>
</body>
</html>
这个时候就可以通过修改data中newtodo的值改变页面的展现 注意:可能因为jeklly本身的缘故,div#app中的mustache模板语法没有正常显示,后同
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<br/>
<!--通过v-model属性绑定newtodo-->
<input type="text" v-model="newtodo">
</div>
<!--通过第三方CDN引入vue.js-->
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var app = new Vue({
//使用el属性传入css选择器绑定element节点
el: '#app',
//使用data属性传入对象,对象内自定义属性newtodo传入待办内容
data: {
newtodo: '我系渣渣辉'
}
});
</script>
</body>
</html>
这时候可以通过页面的input框修改newtodo值,data中的值和页面上引用的值都会同步变化(数据双向绑定)
TODO应用需要一个列表展示所有的待办已办事项
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<br/>
<!--通过v-model属性绑定newtodo-->
<input type="text" v-model="newtodo">
<ul>
<!--使用v-for属性循环展示todolist中的项目-->
<li v-for="item in todolist"></li>
</ul>
</div>
<!--通过第三方CDN引入vue.js-->
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var app = new Vue({
//使用el属性传入css选择器绑定element节点
el: '#app',
//使用data属性传入对象,对象内自定义属性newtodo传入待办内容
data: {
newtodo: '我系渣渣辉',
//新增todolist数组用来保存待办项目
todolist: ['渣渣辉', '陈秀春', '古天乐']
}
});
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<br/>
<!--给input标签新增v-on属性绑定键盘回车事件,回调函数名称为addTodo-->
<input type="text" v-model="newtodo" v-on:keyup.enter="addTodo">
<ul>
<li v-for="item in todolist"></li>
</ul>
</div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
newtodo: '我系渣渣辉',
todolist: ['渣渣辉', '陈秀春', '古天乐']
},
//使用methods属性保存自定义的addTodo方法
methods: {
addTodo: function() {
//将newtodo插入todolist数组
this.todolist.push(this.newtodo);
//置空输入框
this.newtodo = '';
}
}
});
</script>
</body>
</html>
现在可以通过敲击回车将input框中的内容保存到todolist列表
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<br/>
<input type="text" v-model="newtodo" v-on:keyup.enter="addTodo">
<ul>
<!--在列表项末尾增加删除按钮,使用click事件绑定delTodo方法,参数是item-->
<li v-for="item in todolist"><button v-on:click="delTodo(item)">X</button></li>
</ul>
</div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
newtodo: '我系渣渣辉',
todolist: ['渣渣辉', '陈秀春', '古天乐']
},
methods: {
addTodo: function() {
this.todolist.push(this.newtodo);
this.newtodo = '';
},
delTodo: function(item) {
//从todolist中删除item
this.todolist.splice(this.todolist.indexOf(item), 1);
}
}
});
</script>
</body>
</html>
现在可以通过点击列表项末尾的删除按钮删除当前列表项
目前为止我们进行的所有操作都是前台操作,数据并没有保存到数据库,实际开发中需要通过ajax与后台进行数据同步,但是例子里面为了演示方便,使用了localStorage代替ajax操作
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
</head>
<body>
<div id="app">
<br/>
<input type="text" v-model="newtodo" v-on:keyup.enter="addTodo">
<ul>
<li v-for="item in todolist"><button v-on:click="delTodo(item)">X</button></li>
</ul>
</div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
//定义一个全局的todoStorage对象进行存取操作
var todoStorage = {
fetch: function() {
var list = JSON.parse(localStorage.getItem('todolist')) || [];
return list;
},
save: function(list) {
localStorage.setItem('todolist', JSON.stringify(list));
}
};
var app = new Vue({
el: '#app',
data: {
newtodo: '我系渣渣辉',
//使用todoStorage对象的方法获取todolist
todolist: todoStorage.fetch()
},
methods: {
addTodo: function() {
this.todolist.push(this.newtodo);
this.newtodo = '';
},
delTodo: function(item) {
this.todolist.splice(this.todolist.indexOf(item), 1);
}
},
//使用watch属性监听todolist的变化,一旦有变化就触发保存方法进行持久化
watch: {
todolist: function(todolist) {
todoStorage.save(todolist);
}
}
});
</script>
</body>
</html>
这步我们需要通过多选框和样式对已办项目进行标记,首先必须修改一下数据结构,把原来原始的字符串事项修改为对象,如下
var todo = {
name: '某某某',
completed: false
};
使用completed属性标记是否已办
接下来需要稍微修改一下原来的代码——只修改addTodo方法即可应用新的数据结构,然后就可以添加已办功能的相关代码
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
<!--在内部样式表定义completed样式类-->
<style>
.completed {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<br/>
<input type="text" v-model="newtodo" v-on:keyup.enter="addTodo">
<ul>
<!--第二步:增加多选框和已办样式类的绑定,展现的内容相应地修改为item.name,添加一个completed样式类,这个类是否起作用取决于item.completed,多选框同样绑定到itme.completed-->
<li v-for="item in todolist"><input type="checkbox" v-model="item.completed"><span v-bind:class="{completed:item.completed}"></span><button v-on:click="delTodo(item)">X</button></li>
</ul>
</div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var todoStorage = {
fetch: function() {
var list = JSON.parse(localStorage.getItem('todolist')) || [];
return list;
},
save: function(list) {
localStorage.setItem('todolist', JSON.stringify(list));
}
};
var app = new Vue({
el: '#app',
data: {
newtodo: '我系渣渣辉',
todolist: todoStorage.fetch()
},
methods: {
addTodo: function() {
//第一步:push新的todo事项对象
this.todolist.push({
name: this.newtodo,
completed: false
});
this.newtodo = '';
},
delTodo: function(item) {
this.todolist.splice(this.todolist.indexOf(item), 1);
}
},
watch: {
todolist: function(todolist) {
todoStorage.save(todolist);
}
}
});
</script>
</body>
</html>
现在就可以通过点击多选框改变事项的已办待办状态
实现全部、已办事项、待办事项的分类展示
<!doctype html>
<html>
<head>
<title>TODO MVC</title>
<meta charset="utf-8">
<style>
.completed {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<br/>
<input type="text" v-model="newtodo" v-on:keyup.enter="addTodo">
<ul>
<!--第四步:将todolist修改为filteredList-->
<li v-for="item in todolist"><input type="checkbox" v-model="item.completed"><span v-bind:class="{completed:item.completed}"></span><button v-on:click="delTodo(item)">X</button></li>
</ul>
<!--第二步:新增三个按钮分别绑定click事件修改filter的值,@click属性是v-on:click的简写-->
<button @click="filter='all'">all</button>
<button @click="filter='active'">active</button>
<button @click="filter='completed'">completed</button>
</div>
<script src="http://cdn.bootcss.com/vue/2.2.6/vue.js"></script>
<script>
var todoStorage = {
fetch: function() {
var list = JSON.parse(localStorage.getItem('todolist')) || [];
return list;
},
save: function(list) {
localStorage.setItem('todolist', JSON.stringify(list));
}
};
var app = new Vue({
el: '#app',
data: {
newtodo: '我系渣渣辉',
todolist: todoStorage.fetch(),
//第一步:新增filter标识位,默认为all,可选active、completed
filter: 'all'
},
//第三步:添加计算属性,声明filteredList,这个值由data中的值计算得来,在这个例子里面依赖filter的值
computed: {
filteredList: function() {
switch (this.filter) {
case 'all':
return this.todolist;
case 'active':
return this.todolist.filter(function(item, i, a) {
return item.completed === false;
});
case 'completed':
return this.todolist.filter(function(item, i, arr) {
return item.completed === true;
});
}
}
},
methods: {
addTodo: function() {
this.todolist.push({
name: this.newtodo,
completed: false
});
this.newtodo = '';
},
delTodo: function(item) {
this.todolist.splice(this.todolist.indexOf(item), 1);
}
},
watch: {
todolist: function(todolist) {
todoStorage.save(todolist);
}
}
});
</script>
</body>
</html>
现在就可以通过点击按钮切换分类了
一个简单的TODO应用就完成了