vue 综合案例todos----重要

html文件:
 

<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<title>Template • TodoMVC</title>
		<link rel="stylesheet" href="node_modules/todomvc-common/base.css">
		<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css">
		<!-- CSS overrides - remove if you don't need it -->
		<link rel="stylesheet" href="css/app.css">
	</head>
	<body>
		<section class="todoapp" id="app">
			<header class="header">
				<h1>todos</h1>
				<input class="new-todo" placeholder="What needs to be done?" autofocus v-on:keydown.enter="add" v-my-focus>
			</header>
			<!-- This section should be hidden by default and shown when there are todos -->
			<template v-if="todos.length">
				<section class="main">
			<!-- 	<input 
				id="toggle-all" 
				class="toggle-all" 
				type="checkbox" 
				v-on:change="handleToggleAllChange" 
				v-bind:checked="toggleAll"> -->
				
				<input 
				id="toggle-all" 
				class="toggle-all" 
				type="checkbox" 
				v-model="toggleAll">

				<label for="toggle-all">Mark all as complete</label>
				<ul class="todo-list">
					<!-- These are here just to show the structure of the list items -->
					<!-- List items should get the class `editing` when editing and `completed` when marked as completed -->

					<!-- 任务项有三种状态
					已完成 completed
					未完成 无样式
					编辑  edit -->

					<li v-bind:class="{completed: item.completed, editing: currentEditing === item ? true : false}" v-for="(item,index) in filterTodos()">
						<div class="view">
							<input class="toggle" type="checkbox" v-model="item.completed">
							<!-- 注册双击事件 dblclick-->
							<label v-on:dblclick="dblclick(item)">{{ item.title }}</label>
							<button class="destroy" v-on:click="remove(index)"></button>
						</div>
						<input class="edit" v-bind:value="item.title" v-on:keyup.enter="keyupSave(item, index, $event)" v-on:blur="keyupSave(item, index, $event)" v-on:keyup.esc="escDontSave(item)" v-todo-focus="currentEditing === item">
					</li>
				</ul>
				</section>
			<!-- This footer should hidden by default and shown when there are todos -->
			 	<footer class="footer">
				<!-- This should be `0 items left` by default -->
				<span class="todo-count"><strong>{{ count }}</strong> item left</span>
				<!-- Remove this if you don't implement routing -->
				<ul class="filters">
					<li>
						<a v-bind:class="{selected: todosText===''}" href="#/">All</a>
					</li>
					<li>
						<a v-bind:class="{selected: todosText==='active'}" href="#/active">Active</a>
					</li>
					<li>
						<a v-bind:class="{selected: todosText==='completed'}" href="#/completed">Completed</a>
					</li>
				</ul>
				<!-- Hidden if no completed items are left ↓ -->
				<!-- 只要有一个被选中就显示 -->
				<button class="clear-completed" v-if="todos.some(item => item.completed)" v-on:click="clearCompleted">Clear completed</button>
				</footer>
			</template>
		</section>
		<footer class="info">
			<p>Double-click to edit a todo</p>
			<!-- Remove the below line ↓ -->
			<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
			<!-- Change this out with your name and url ↓ -->
			<p>Created by <a href="http://todomvc.com">you</a></p>
			<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
		</footer>
		<!-- Scripts here. Don't remove ↓ -->
		<!-- // <script src="node_modules/todomvc-common/base.js"></script> -->
		<script src="node_modules/vue/dist/vue.js"></script>
		<script src="js/app.js"></script>
	</body>
</html>

app.js文件
 

;(function () {

	var todos = [
		{
			id: 1,
			ttle: '吃饭'
		},
		{
			id: 2,
			ttle: '睡觉'
		},
		{
			id: 3,
			ttle: '打豆豆'
		}
	]
	// 自定义指令实现刷新自动聚焦
	// 自定义聚焦指令不能放在bind钩子函数里,不会执行
	Vue.directive('my-focus', {
		// bind (el) {
		// 	el.focus()
		// },
		inserted (el) {
			el.focus()
		}
	})
	// 自定义指令实现双机自动聚焦
	Vue.directive('todo-focus', {
		update (el) {
			el.focus()
		},
		
	})

	//var的形式在web端是不能访问的,需要挂载到window上
	window.app = new Vue({
		el: '#app',
		data: {
			todos: JSON.parse(window.localStorage.getItem('todos') || '[]'),
			/*message: 'jj'*/
			currentEditing: '',
			todosText: ''
		},
		watch: {
			//监视data里面某个数据的变化,只要一变化就执行,变化时做业务定制处理
			//引用类型只能监视一层,无法监视内部成员的变化
			todos: {
				//当监视到todos改变的时候会自动调用handler方法
				//监视的谁val就是谁
				//oldVal是变化之后的值
				handler (val, oldVal) {
					window.localStorage.setItem('todos', JSON.stringify(val))
				},
				//深度监视,只有这样才能监视到对象里面属性的变化
				deep: true,
				//无论变化与否,上来就执行一次
				immediate: true
			}
		},
		methods: {
			add: function (e) {
				//不用双向绑定,这个回车事件是由input表单绑定的,事件对象指向表单
				//事件对象指向绑定这个事件的对象
				//e.target.value指向表单输入的内容
				console.log(e.target.value)
				// 0、注册按下回车事件
				// 1、获取文本框内容
				var value = e.target.value.trim()
				// 2、数据校验
				if (!value) {
					return false 
				}
				// 3、添加到todos里面
				var member = {
					id: this.todos.length ? this.todos[this.todos.length - 1].id + 1 : 1,
					title: value,
					completed: true
				}
				this.todos.push(member)	
				e.target.value = ''
			},
			handleToggleAllChange: function (e) {
				var change = e.target.checked
				this.todos.forEach(function (item, i) {
					item.completed = change
				})
			},
			remove: function (id) {
				this.todos.splice(id, 1)
			},

			dblclick: function (item) {
				this.currentEditing = item
			},

			keyupSave: function (item, index, e) {
				var value = e.target.value.trim()
				if (!value.length) {
					//当文本框中的内容为空,敲回车时删除这个文本框
					this.todos.splice(index, 1)	
				} else {
					// 当文本框不为空按enter键时,保存修改的值,并且清除这个文本框
					item.title = value
					this.currentEditing = null
				}
			},

			escDontSave: function (item) {
				console.log('111')
				this.currentEditing = null
			},

			clearCompleted: function () {
				// for循环实现
				// for(var i = 0; i < this.todos.length; i++) {
				// 	if (this.todos[i].completed) {
				// 		console.log(1)
				// 		this.todos.splice(i, 1)
				// 		//前面的被删了,后面的所有元素索引要减1,因为前面的被删了,后面的索引都变了
				// 		i--
				// 	}
				// }


				// 错误方法,不能再foreach里面删除数组元素,因为删除一个后面的索引变了
				// this.todos.forEach(function (item, i) {
				// 	if (item.completed) {
				// 		todos.splice(i, 1)
				// 	}	
				// })


				// 简单粗暴的方法,数筛选,给todos重新赋值,把符合条件的放进去
				this.todos = this.todos.filter(item => !item.completed)	
			},

			// 通过hash的值来改变要渲染的内容
			filterTodos: function () {
				switch(this.todosText) {
					case 'active' :
						return this.todos.filter(t => !t.completed)
						break;
					case 'completed' :
						return this.todos.filter(t => t.completed)
						break;
					default:
						return this.todos
						break
				}
			}
		},

		//computed为计算行为的属性,这里面的方法不管调用几次,都只会执行一次
		//因为执行一次过后结果被存储起来了
		//本质上是方法,但是只能当属性来调用,就像data里面参数调用的方法一样
		computed: {
			//一个函数作为get方法,被调用时默认执行get方法
			//简写方式
			// count () {
			// 	return this.todos.filter(item => !item.completed).length
			// }


			// 两个方法的方式
			//app.count 执行get方法
			//app.count = 124 执行set方法,但用get方法访问时,它的值没变
			count: {
				get () {
					return this.todos.filter(item => !item.completed).length
				},
				set () {
					console.log('set方法被调了!')
				}
			},
			// toggleAll: {
			// 	get () {
			// 		return todos.every(t => t.completed)
			// 	}
			// }


			// 在computed里面实现全部选项的选中和不选中
			toggleAll: {
				//计算属性知道它依赖了todos,当todos发生变化时,计算属性会自动重新计算
				get () {
					return todos.every(t => t.completed)
				},

				// 在set里面访问this.toggleAll会调用这个方法的get方法
				set () {
					var checked = !this.toggleAll
					// 有一个没选中,点击时就让它全中,如果已经全中了,点击就让它全不中
					this.todos.forEach(item => {
					item.completed = checked
					}
				)
				}
			}
		}
	}) 

	window.onhashchange = function () {
		app.todosText = window.location.hash.substr(2)
	}
	onhashchange()

})()

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值