Vue入门案例:TodoList

时光总嘲笑我的痴心妄想 提交于 2020-11-06 08:37:45

项目结构

1 参考todomvs,网站:http://todomvc.com/
2 模板仓库地址:https://github.com/tastejs/todomvc-app-template.git
3 git拉取:git clone https://github.com/tastejs/todomvc-app-template.git

在这里插入图片描述
4 拉取下来文件如图

在这里插入图片描述

.git git版本管理器
cssapp.css样式
jsapp.js书写效果
.editorconfig编辑器设置
.gitattributesgit的设置
.gitignoregit管理忽略的文件的配置
.app-readme.md可删除
index.htmlhtml主体
.package.json项目描述;使用命令行:npm i 下载项目依赖包
readme.md上传git展示的文档








项目功能

1 展开事项列表
2 添加事项
3 编辑事项
4 删除事项
5 切换单条事项状态
6 批量切换事项状态
7 清除已完成事项
8 同步未完成事项总数
9 显示/隐藏清除已完成按钮
10 切换不同事项的显示
11 数据同步到本地存储









实现效果

在这里插入图片描述

完整代码

一、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">

	</head>
	<body>
		<section class="todoapp">
			<header class="header">
				<h1>todos</h1>
				<!-- 变化1 -->
				<!-- 
					v-model.trim:实时获取去除前后空格的文本框输入的值;
					@keyup.enter:按下回车时执行add方法
				-->
				<input class="new-todo" placeholder="What needs to be done?" 
					autofocus 
					v-model.trim="newTask"
					@keyup.enter="add"
				>
			</header>
			<section class="main">
				<input id="toggle-all" class="toggle-all" type="checkbox">
				<!-- 变化2 -->
				<!-- 
					@click:绑定点击事件,当点击时执行toggleAll函数;
					v-show:当Shown值为true时让其显示,反之隐藏
				 -->
				<label for="toggle-all" @click="toggleAll" v-show="Shown">Mark all as complete</label>
				<ul class="todo-list">
					<!-- 变化3 -->
					<!-- 类名:completed改变事项的状态为已完成;类名:editing让文本框进入编辑状态-->
					<!-- 
						v-for:遍历数组tasks;
						:class:当task.completed传回的值为true时添加类名completed,当isEditing==task.id时添加类名editing
						v-if:获取completed状态
					 -->
					<li v-for="task in tasks" 
						:class="{completed:task.completed,editing:isEditing==task.id}"
						v-if="show(task.completed)"
					>
						<div class="view">
							<!-- 变化4 -->
							<!-- v-model:实时获取task.completed的值 -->
							<input class="toggle" type="checkbox" v-model="task.completed">
							<!-- 变化5 -->
							<!-- 
								@dblclick:双击isEditing=task.id的文本框,也就是让当前文本框进入编辑状态;
								v-text:更新task.title
							 -->
							<label
								@dblclick="isEditing=task.id"
								v-text="task.title"								
							></label>
							<!-- 变化6 -->
							<!-- @click:点击删除按钮时判断是否是当前的事项,是就删除 -->
							<button class="destroy" @click="remove(task.id)"></button>
						</div>
						<!-- 变化7 -->
						<!-- 
							v-todo-focus:如果isEditing==task.id为true,就让input自动聚焦;
							v-model:更新task.title;
							@keyup.enter:当按下回车键时让isEditing=-1;
							@blur:当焦点离开文本框时,让isEditing=-1
						 -->
						<input class="edit" 
							v-model="task.title"
							@keyup.enter="isEditing=-1"
							@blur="isEditing=-1"
							v-todo-focus="isEditing==task.id"							
						>
						
					</li>
				</ul>
			</section>
			<!-- 变化8 -->
			<!-- v-show:当Shown值为true时让其显示,反之隐藏 -->
			<footer class="footer" v-show="Shown">
				<span class="todo-count"><strong v-text="activeNum"></strong> item left</span>
				<ul class="filters">
					<li>
						<!-- 变化9 -->
						<!-- :class:当flag的路由全等于''时,添加类名selected -->
						<a :class="{selected:flag===''}" href="#/">All</a>
					</li>
					<li>
						<!-- 变化10 -->
						<!-- :class:当flag.completed全等于false时,添加类名selected -->
						<a :class="{selected:flag.completed===false}" href="#/active">Active</a>
					</li>
					<li>
						<!-- 变化11 -->
						<!-- :class:当flag.completed全等于true时,添加类名selected -->
						<a :class="{selected:flag.completed===true}" href="#/completed">Completed</a>
					</li>
				</ul>
				<!-- 变化12 -->
				<!-- 
					@click:点击清除按钮时执行函数clearAll;
					v-if:当有已完成事项时,返回true让其显示
				 -->
				<button class="clear-completed" @click="clearAll" v-if="isShow">Clear completed</button>
			</footer>
		</section>
		<script src="node_modules/todomvc-common/base.js"></script>
		<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
		<script src="js/app.js"></script>
	</body>
</html>

二、JS

(function (window) {
   
   
	'use strict';
	// 里面的变量都是局部变量,除非绑定在window上
	// 书写本地存储的存取方法
	window.storage = {
   
   
		getStorage(){
   
   
			// 获取本地存储,并转换成json对象
			return JSON.parse(window.localStorage.getItem('todos')||'[]');
		},
		setStorage(json){
   
   
			// 把传入的json对象转成json字符串,存入本地存储
			window.localStorage.setItem('todos',JSON.stringify(json));
		}
	}

	// 创建一个vue实例
	window.app = new Vue({
   
   
		el:".todoapp",
		data:{
   
   
			tasks:window.storage.getStorage(),
			newTask:"",
			isEditing:-1,
			status:true,
			count:0,
			flag:location.hash=="#/active"?({
   
   completed:false}):(location.hash=="#/completed"?({
   
   completed:true}):"")
		},
		directives:{
   
   
			"todo-focus":function(el,binding){
   
   
				if(binding.value){
   
   
					el.focus()
				}
			}
		},		
		computed:{
   
   	
			activeNum(){
   
   
				this.count = 0;
				this.tasks.forEach((task)=>{
   
   
					if(!task.completed){
   
   
						this.count++;
					}
				})
				return this.count;
			},
			isShow(){
   
   
				for(var i=0;i<this.tasks.length;i++){
   
   
					if(this.tasks[i].completed){
   
   
						return true;
					}
				}
				return false;
			},
			Shown(){
   
   
				if(this.tasks.length>0){
   
   
					return true;
				}
			}
		},
		methods:{
   
   
			show(i){
   
   
				if(this.flag===""){
   
   
					return true;
				}else if(this.flag.completed===i){
   
   
					return true;
				}
				window.storage.setStorage(this.tasks);
			},
			clearAll(){
   
   
				this.tasks = this.tasks.filter(task=>!task.completed);
				window.storage.setStorage(this.tasks);
			},
			toggleAll(){
   
   
 				this.tasks.forEach((task)=>{
   
   
					task.completed = this.status
				});
				this.status = !this.status;
				// 同步到本地存储中
				window.storage.setStorage(this.tasks);
			},
			remove(id){
   
   
				this.tasks = this.tasks.filter(task=>{
   
   
					return task.id!=id
				})
				// 同步到本地存储中
				window.storage.setStorage(this.tasks);
			},
			add(){
   
   
				var task = {
   
   
					title:this.newTask,
					completed:false,
					id:Date.now()
				}
				if(task.title!=''){
   
   
					this.tasks.push(task);
				}
				// 输入完成后,清空文本框
				this.newTask = ""
				// 同步到本地存储中
				window.storage.setStorage(this.tasks);
			}
		}
	})

	// 监控路由的变化
	window.onhashchange = function(){
   
   
		console.log(location.hash);
		// 专门在vue实例里面声明一个变量由于标识当前是在哪个路由
		if(location.hash=="#/active"){
   
   
			window.app.flag = {
   
   completed:false}; //active就是要显示未完成任务,flag最好有意义
			return;
		}else if(location.hash=="#/completed"){
   
   
			window.app.flag = {
   
   completed:true}; //completed就是要显示已完成任务,flag最好有意义
			return;
		}else{
   
   
			// 如果是其他路由,都显示全部任务
			window.app.flag = "";
			return;
		}
	}
})(window);

结束语

你那么可爱,肯定会点赞,一起加油!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!