Vue.js经典项目:TodoMvc

4 篇文章 0 订阅
2 篇文章 0 订阅

1、github拉取只含静态页面的项目

2、app.js文件

(function (Vue) {
	const STORAGE_KEY='todo-items';
	const itemStorage={
		//获取数据
		fetch:function(key){
			return JSON.parse(localStorage.getItem(key)||'[]'); //json字符串转数组返回
		},
		//保存数据
		save:function(key,items){
			localStorage.setItem(key,JSON.stringify(items)); //json字符串
		}
	};
	const items = [
		{
			id: 1,
			content: "C#",
			isCompleted: false
		}, {
			id: 2,
			content: "Java",
			isCompleted: false
		}, {
			id: 3,
			content: "Python",
			isCompleted: false
		}];

	//注册全局指令
	Vue.directive('input-focus', {
		inserted(el, binding) {
			el.focus();
		},
		update(el, binding) {
			if (binding.value) {
				el.focus();
			}
		}
	});
	var vm = new Vue({
		el: "#todoapp",
		data: {
			title: 'todos',
			//items, //ES6对象属性的简写 items:items
			items:itemStorage.fetch(STORAGE_KEY),
			currentItem: null,
			filterStatus: 'all'
		},
		//侦听器
		watch:{
			//items:function(newItems,oldItems){};//数组监听
			//深度监听 监听数组中对象属性是否发生变化 deep:true
			items:{
				deep:true,
				handler:function(newItems,oldItems){//处理函数
					itemStorage.save(STORAGE_KEY,newItems);//监听到变化则保存到本地
				}
			}

		},
		//计算属性
		computed: {
			filterItems() {
				switch (this.filterStatus) {
					case 'active':
						return this.items.filter(item => !item.isCompleted);
						break;
					case 'completed':
						return this.items.filter(item => item.isCompleted);
						break;
					default:
						return this.items;
						break;
				}
			},
			toggleAll: {
				get() { //必须有返回值
					return this.remaining === 0;
				},
				set(newStatus) {
					this.items.forEach(item => item.isCompleted = newStatus);
				}
			},
			//剩余未完成的数量
			remaining() { //remaining:function()简写
				//const unCompletedItems=this.items.filter(function(item){
				//	return !item.isCompleted;
				//});
				//return unCompletedItems.length;
				return this.items.filter(item => !item.isCompleted).length;
			},
			itemOrItems() {
				if (this.remaining === 1) {
					return 'Item';
				}
				else {
					return 'Items';
				}
			},
			hasCompletedItem() {
				return this.items.some(item => item.isCompleted);
			}
		},
		methods: {
			toEdit(item) {
				this.currentItem = item;
			},
			cancleEdit() {
				this.currentItem = null;
			},
			finishedEdit(item, index, event) {
				const newContent = event.target.value;
				if (!newContent) {
					this.removeItem(index);
				}
				item.content = newContent;
				this.currentItem = null;
			},
			addItem(event) {
				const content = event.target.value.trim();
				let maxId = Math.max.apply(Math, this.items.map(item => item.id));//对象组id最大值
				if (content.length > 0) {
					this.items.push(
						{
							id: maxId + 1,
							content,
							isCompleted: false
						}
					);
					event.target.value = "";
				}
			},
			removeItem(index) {
				this.items.splice(index, 1);
			},
			clearAll() {
				this.toggleAll = false;
			},
			addClass(e) {
				let element = e.currentTarget;
				if (!element.classList.contains('editing')) {
					element.classList.toggle('editing');
				}
			}
		}
	});

	//路由hash值改变时调用
	window.onhashchange = () => {
		const hash = window.location.hash.substr(2) || 'all';
		vm.filterStatus = hash;
	};

	//刷新页面的时候调用
	window.onhashchange();
})(Vue);

3、index.html页面vuejs绑定

<!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="todoapp">
		<header class="header">
			<h1>{{title}}</h1>
			<!--回车监听-->
			<input v-on:keyup.enter="addItem" class="new-todo" placeholder="What needs to be done?" v-input-focus>
		</header>
		<!-- This section should be hidden by default and shown when there are todos -->
		<template v-if="items.length">
			<section class="main">
				<input v-model="toggleAll" id="toggle-all" class="toggle-all" type="checkbox">
				<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 -->
					<li v-for="(item,index) in filterItems"  @dblclick="toEdit(item)" 
					v-bind:class="{completed:item.isCompleted,editing:item===currentItem}">
						<div class="view">
							<input class="toggle" type="checkbox" v-model="item.isCompleted">
							<label>{{item.content}}</label>
							<button class="destroy" v-bind:value="item.id" @click="removeItem(index)"></button>
						</div>
						<input v-input-focus="item===currentItem" class="edit" v-bind:value="item.content" @keyup.esc="cancleEdit" 
						@keyup.enter="finishedEdit(item,index,$event)" @blur="finishedEdit(item,index,$event)">
					</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>{{remaining}}</strong> {{itemOrItems}} left
				</span>
				<!-- Remove this if you don't implement routing -->
				<ul class="filters">
					<li>
						<a :class="{selected:filterStatus==='all'}" href="#/">All</a> 
					</li>
					<li>
						<a :class="{selected:filterStatus==='active'}" href="#/active">Active</a>
					</li>
					<li>
						<a :class="{selected:filterStatus==='completed'}" href="#/completed">Completed</a>
					</li>
				</ul>
				<!-- Hidden if no completed items are left ↓ -->
				<button v-show="hasCompletedItem" @click="clearAll" class="clear-completed">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/vue/dist/vue.js"></script>
	<script src="node_modules/todomvc-common/base.js"></script>
	<script src="js/app.js"></script>
</body>

</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值