文章目录

  • 前言
  • 一、准备
  • 二、创建
    • 1.编写TodoMvc基本结构
    • 2.功能实现
  • 总结
  • 完整项目代码 TodoDemo.vue

前言

TodoMVC是一个示例项目,它使用目前流行的不同JavaScript框架的来实现同一个Demo,来帮助你熟悉和选择最合适的前端框架。学习框架最直接有效的方式就是上手练习,接下来我们将用Vue.js来完成TodoMVC的示例。
官网地址:https://todomvc.com/

一、准备

在 Vscode 软件在打开集成终端

  • 输入 vue cerate 项目名 创建项目
  • 输入cd 项目名 进入创建好的项目内
  • 输入 npm run serve启动项目
  • 创建 TodoDemo.vue
  • TodoDemo.vue引入 App.vue

二、创建

1.编写TodoMvc基本结构

代码如下(示例):

<template><div class="todo-demo"><h1>TODOS</h1><div class="todo-form"><input type="text"><button>添加</button></div><div class="todo-content"><ul><li> </li></ul></div><div class="todo-foot"><span>1 item left</span><div class="type-btns"><button>all</button><button>active</button><button>completde</button></div><button>clear completde</button></div></div>
</template><script>
export default {data(){return {todos: [{id:1,text:"律师函警告",done: false},{id:2,text:"喜欢唱,跳,rep,篮球",done: true},{id:3,text:"你干嘛,哎呀",done: false}]}}
}
</script><style>
.todo-demo {width: 400px;margin: 0 auto;
}
.todo-foot{display: flex;justify-content: space-between;
}
</style>

2.功能实现

  • 1) 使用 v-for 实现展示功能

代码如下:

 <div class="todo-content"><ul><li> <li v-for="todo in todos" :key="todo.id">{{todo.text}}</li></li></ul></div>


  • 2) 使用 @click 实现删除功能

代码如下:

<div class="todo-content"><ul><li v-for="todo in todos" :key="todo.id"><input type="checkbox">{{todo.text}}<span @click="del(todo.id)">×</span></li>  <!--点击 x 实现删除功能--></ul>
</div>export default {data(){...}},methods: {//删除功能del(id){this.todos = this.todos.filter(todo => todo.id !== id)}}
}


  • 3) 使用 v-model 实现复选框修改事件

代码如下:

<div class="todo-content"><ul><li v-for="todo in todos" :key="todo.id"><input type="checkbox"  v-model="todo.done">{{todo.text}}<span @click="del(todo.id)">×</span></li></ul>
</div>export default {data(){return {todos: [{id:1,text:"律师函警告",done: false},{id:2,text:"喜欢唱,跳,rep,篮球",done: true},{id:3,text:"你干嘛,哎呀",done: false}]}},methods: {del(id){this.todos = this.todos.filter(todo => todo.id !== id)}}
}


  • 3.1) 使用 :checked 和@change 实现复选框修改事件

代码如下:

<div class="todo-content"><ul><li v-for="todo in todos" :key="todo.id"><!-- <input type="checkbox"  v-model="todo.done"> --><input type="checkbox"  :checked="todo.done" @change="change">{{todo.text}} <span @click="del(todo.id)">×</span></li></ul>
</div>export default {data(){return {...},methods: {// 删除功能del(id){...},// 复选框的修改事件change(id){const currentTodo = this.todos.find(todo => todo.id === id)currentTodo.done = !currentTodo.done}}
}

  • 3.2)使用:class实现复选框选择状态下画横线

代码如下:

 <div class="todo-content"><ul><li v-for="todo in todos" :key="todo.id"><input type="checkbox"  v-model="todo.done"><!-- <input type="checkbox"  :checked="todo.done" @change="change"> --><span :class="{done: todo.done}">{{todo.text}} </span><!-- 复选框选择状态下,我们使用 :class 的绑定中的对象的写法来实现 --> <span @click="del(todo.id)">×</span></li></ul></div><style>
/* 选择状态的样式 */
.todo-content ul li span.done{text-decoration: line-through;color: #ccc;
}
</style>

  • 4)使用v-model.trim @click实现添加功能,@keyup.enter:使用键盘回车完成添加

代码如下:

<div class="todo-form"><!-- 事件修饰符 .enter  @keyup.enter:键盘上回车 完成添加--><input type="text" v-model.trim="todoText" @keyup.enter="submit"><button @click="submit">添加</button>
</div>data(){return {todos: [...],todoText: "",//默认为空}},methods: {// 添加功能submit(){const { todoText } = thisconsole.log(todoText)if(todoText){// Date().getTime() 确保添加完成后的 id 不同this.todos.push({ id: new Date().getTime(), text: todoText})this.todoText = '';// 添加完成后清空输入框}},}


  • 5)使用计算属性computed以箭头函数实现动态未完成事件的更新

代码如下:

<div class="todo-foot"><!-- 实现动态 item left的更新 --><span>{{activeTodoNums}}item left</span>
</div>export default {data(){return {todos: [... {... done: false}],todoText: "",//默认为空}},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums(){// 方法一:// return this.todos.reduce( function(res, todo){//   if(!todo.done){//     res ++//   }//   return res// },0)// 使用箭头函数 判断 done 为false有多少 !todo.done 如果为false 则 ++resreturn this.todos.reduce((res, todo) => (!todo.done ? ++res : res),0) }
}


  • 5.1)使用:class @click computed实现 all active completde 的选择,并且改变颜色

代码如下:

<div class="type-btns"><button :class="{'btn-active': type === 'all'}" @click="type = 'all'">all</button><button :class="{'btn-active': type === 'active'}" @click="type = 'active'">active</button><button :class="{'btn-active': type === 'completde'}" @click="type = 'completde'">completde</button>
</div>export default {data(){return {[...]todoText: "",//默认为空type: 'all',// 规定点击的的是 all | active | completde}},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums(){...},showTodos(){return []}},
}<style>
...
/* 点击效果 */
.btn-active {color: red;
}
</style>

  • 5.2)使用 computed 与 JavaScript中的 const实现 all active completde 的选择的展示

代码如下:

<div class="todo-content"><ul><li v-for="todo in showTodos" :key="todo.id"> <!--重新选择遍历对象为:showTodos-->...</li></ul>
</div>export default {data(){return {[...]todoText: "",//默认为空type: 'all',// 规定点击的的是 all | active | completde}},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums(){...},showTodos(){const {todos, type} = this// 使用箭头函数 对 type 的值 进行判断,判断它是为:all | active | completdereturn todos.filter(todo => type === 'all' ? true : type === 'active' ? !todo.done : todo.done)}},
}

  • 5.2)使用 @click实现 clear completde 清空已经完成的任务

代码如下:


```handlebars
<button @click="clear">clear completde</button>computed: {export default {data(){return {[...]todoText: "",//默认为空type: 'all',// 规定点击的的是 all | active | completde}},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums(){...},clear(){this.todos = this.todos.filter(todo => !todo.done)},
}

  • 6)使用 v-if v-elese @dblclick :value @blur v-model.lazy实现双击文字进行编辑功能

代码如下:

<div class="todo-content"><ul>...<!-- template 不会被渲染成所有类 --><template v-if="editId !== todo.id"><!-- 判断 editId 与 todo.id 是否相同 不相同展示内容,相同展示输入框 -->...</template><!-- 双击出输入框效果,且原文字内容展示到输入框 --><!-- @blur="changeTodoText" 失去交点的时候关闭输入框--><!-- v-model.lazy 失去交点的时候完成修改  --><input v-else type="text"  @blur="changeTodoText"  v-model.lazy="todo.text"/></li></ul></div><script>
export default {data() {return {todos: [...],todoText: "", //默认为空type: "all", // 规定点击的的是 all | active | completdeeditId:' ', // 定义一个可编辑 id,默认页面只能出现一个 id 当 id相同时则进行编辑};},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums() {...},showTodos() {...},},methods: {// 删除功能del(id) {... },// 复选框的修改事件// change(id){...},// 添加功能submit() {...},// 实现clear completde 清空已经完成的任务clear() {...},changeTodoText(){//  失去交点关闭输入框this.editId = 0}},
};
</script>

对于上代码:功能虽然已实现但仍然存在着功能缺陷

 <div class="todo-content"><ul>...<!-- 双击事件 --><span @dblclick="handleDblclick(todo.id)" :class="{ done: todo.done }">{{ todo.text }}</span>...</li></ul></div><script>
export default {...changeTodoText(){//  失去交点关闭输入框this.editId = 0},// 错误展示handleDblclick(id){this.editId = idconsole.log(this.$refs.editInp[0])this.$refs.editInp[0].focus()}},
};
</script>


错误分析:

  • 如果修改完了 马上让输入框获得焦点话, 会出报错,提示 focus of undefined
  • 因为 当双击的时候编辑 id 被修改, 输入框的出现, 所以获得焦点的方法和 输入框的出现起了冲突
  • 入框的出现和输入框获取焦点相当于同时执行的。获取焦点方法是无法生效的。
  • 可以使用 settimeout 做个延迟执行
  • vue 官方提供了 $nextTick

错误修改:

 <div class="todo-content"><ul>...<!-- 双击事件 --><span @dblclick="handleDblclick(todo.id)" :class="{ done: todo.done }">{{ todo.text }}</span>...</li></ul></div><script>
export default {...changeTodoText(){//  失去交点关闭输入框this.editId = 0},// 错误展示handleDblclick(id) {this.editId = id;// console.log(this.$refs.editInp[0])// 如果修改完了 马上让输入框获得焦点话, 会出报错,提示 focus of undefined// 因为 当双击的时候编辑 id 被修改, 输入框的出现, 所以获得焦点的方法和 输入框的出现起了冲突// 输入框的出现和输入框获取焦点相当于同时执行的。获取焦点方法是无法生效的。// 可以使用 settimeout 做个延迟执行// vue 官方提供了 $nextTick// 方法一://   setTimeout( () => {//     this.$refs.editInp[0].focus()//   },5)//   }// 方法二:// nextTick作用:在data更新后,马上想要对 data 相关的 dom 节点进行操作的话,可能会失败。可以使用:nextTick来解决this.$nextTick(() => {// 循环里面设置了 ref 的话 需要使用 [0] 获取// this.$resf.名// 当在 v-for 循环里面使用 ref的话需要注意 ref获取结果时会是一个数组,需要添加 [0] 获取// 当 ref定义的名字是相同的话,那么获取的结果会是一个数组  得到的是所有的 dom 节点this.$refs.editInp[0].focus();});},},
};
</script>

  • 7)使用 v-model computed实现点击的左时将所有任务设置成已完成

代码如下:

    <div class="todo-form">...<!-- 实现点击的左时将所有任务设置成已完成 --><input type="checkbox" v-model="isAllChecked">...</div><script>
export default {data() {...},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums() {...},showTodos() {...},// 点击的左时将所有任务设置成已完成isAllChecked: {get() {return this.todos.every( (todo) => todo.done);},set(val) {this.todos.forEach( todo => {todo.done = val});},}},methods: {...},
};
</script>

总结

  • 事件处理

    • 按键修饰符:键盘事件的修饰符 @keyup.enter

      • .enter
  • class 与 style 的绑定
    • class的绑定

      • 对象语法 : {a:true}
      • 数组语法 : {‘a’,'b'}
      • 数组对象语法 : {‘a’,{b:true}}
    • class的绑定
      • 对象 {width: '200px'}
  • 条件渲染
    • v-if v-else v-eles-if
    • v-show
  • 列表渲染: v-for
    • :key
    • 它可以在 template 上进行循环
  • 表单的输入绑定:v-model
    • 修饰符:

      • .trim 自动清除 v-model 后面的左右值
      • .lazy失去交点的时候才会发生改变
      • .number交 data 的值转换成 数学 使用:Number 转换
    • 它是 value 已经 input 事件的简化版本
  • 计算属性:computed
    • 当你想要的内容可以利用现有的 data 通过一些运算得到的话,那么我们就可以设置一个计算属性
  • ref
    • vue 提供了一种可以获取元素,真实 dom 节点的方法:this.$refs.名
    • 当在 v-for 循环里面使用 ref的话需要注意 ref获取结果时会是一个数组,需要添加 [0] 获取
    • 当 ref定义的名字是相同的话,那么获取的结果会是一个数组 得到的是所有的 dom 节点
  • nextTick作用:
    • 在data更新后,马上想要对 data 相关的 dom 节点进行操作的话,可能会失败。可以使用:nextTick来解决

完整项目代码 TodoDemo.vue

<template><div class="todo-demo"><h1>TODOS</h1><div class="todo-form"><!-- 事件修饰符 .enter --><!-- 实现点击的左时将所有任务设置成已完成 --><input type="checkbox" v-model="isAllChecked"><input type="text" v-model.trim="todoText" @keyup.enter="submit" /><button @click="submit">添加</button></div><div class="todo-content"><ul><li v-for="todo in showTodos" :key="todo.id"><!--重新选择遍历对象为:showTodos  --><!-- template 不会被渲染成所有类 --><template v-if="editId !== todo.id"><!-- 判断 editId 与 todo.id 是否相同 不相同展示内容,相同展示输入框 --><input type="checkbox" v-model="todo.done" /><!-- <input type="checkbox"  :checked="todo.done" @change="change"> --><!-- 双击事件 --><span@dblclick="handleDblclick(todo.id)":class="{ done: todo.done }">{{ todo.text }}</span><!-- 复选框选择状态下,我们使用 :class 的绑定中的对象的写法来实现 --><span @click="del(todo.id)">×</span></template><!-- 双击出输入框效果,且原文字内容展示到输入框 --><!-- @blur="changeTodoText" 失去交点的时候关闭输入框--><!-- v-model.lazy 失去交点的时候完成修改  --><!-- 输入框自动 或得 交点的话 1. autofocus 属性  2. 使用原生 dom.focus() --><inputv-elsetype="text"@blur="changeTodoText"v-model.lazy="todo.text"ref="editInp"/></li></ul></div><div class="todo-foot"><!-- 实现动态 item left的更新 --><span>{{ activeTodoNums }}item left</span><div class="type-btns"><button :class="{ 'btn-active': type === 'all' }" @click="type = 'all'">all</button><button:class="{ 'btn-active': type === 'active' }"@click="type = 'active'">active</button><button:class="{ 'btn-active': type === 'completde' }"@click="type = 'completde'">completde</button></div><button @click="clear">clear completde</button></div></div>
</template><script>
export default {data() {return {todos: [{id: 1,text: "律师函警告",done: false,},{id: 2,text: "喜欢唱,跳,rep,篮球",done: true,},{id: 3,text: "你干嘛,哎呀",done: false,},],todoText: "", //默认为空type: "all", // 规定点击的的是 all | active | completdeeditId: 0, // 定义一个可编辑 id,默认页面只能出现一个 id 当 id相同时则进行编辑};},// 使用计算属性:computed 实现动态的未完成事件computed: {activeTodoNums() {// 老方法// return this.todos.reduce( function(res, todo){//   if(!todo.done){//     res ++//   }//   return res// },0)// 使用箭头函数 判断 done 为false有多少 !todo.done 如果为false 则 ++resreturn this.todos.reduce((res, todo) => (!todo.done ? ++res : res), 0);},showTodos() {const { todos, type } = this;// 使用箭头函数 对 type 的值 进行判断,判断它是为:all | active | completdereturn todos.filter((todo) =>type === "all" ? true : type === "active" ? !todo.done : todo.done);},// 点击的左时将所有任务设置成已完成isAllChecked: {get() {return this.todos.every( (todo) => todo.done);},set(val) {this.todos.forEach( todo => {todo.done = val});},}},methods: {// 删除功能del(id) {this.todos = this.todos.filter((todo) => todo.id !== id);},// 复选框的修改事件// change(id){//   const currentTodo = this.todos.find(todo => todo.id === id)//   currentTodo.done = !currentTodo.done// },// 添加功能submit() {const { todoText } = this;console.log(todoText);if (todoText) {// Date().getTime() 确保添加完成后的 id 不同this.todos.push({ id: new Date().getTime(), text: todoText });this.todoText = ""; // 添加完成后清空输入框}},// 实现clear completde 清空已经完成的任务clear() {this.todos = this.todos.filter((todo) => !todo.done);},changeTodoText() {//  失去交点关闭输入框this.editId = 0;},handleDblclick(id) {this.editId = id;// console.log(this.$refs.editInp[0])// 如果修改完了 马上让输入框获得焦点话, 会出报错,提示 focus of undefined// 因为 当双击的时候编辑 id 被修改, 输入框的出现, 所以获得焦点的方法和 输入框的出现起了冲突// 输入框的出现和输入框获取焦点相当于同时执行的。获取焦点方法是无法生效的。// 可以使用 settimeout 做个延迟执行// vue 官方提供了 $nextTick//   setTimeout( () => {//     this.$refs.editInp[0].focus()//   },5)//   }this.$nextTick(() => {// 循环里面设置了 ref 的话 需要使用 [0] 获取this.$refs.editInp[0].focus();});},},
};
</script><style>
.todo-demo {width: 400px;margin: 0 auto;
}
.todo-foot {display: flex;justify-content: space-between;
}
.todo-content ul {list-style: none;padding-left: 0;
}
.todo-content ul li {display: flex;
}
.todo-content ul li span {user-select: none;
}
/* 复选框选择状态的样式 */
.todo-content ul li span.done {text-decoration: line-through;color: #ccc;
}
/* 点击效果 */
.btn-active {color: red;
}
</style>

使用 Vue 框架 实现经典例子:TodoMVC相关推荐

  1. Vue.js框架入门经典项目TodoMVC

    1. 介绍 项目地址:http://todomvc.com/ github模板下载地址:https://github.com/tastejs/todomvc-app-template 可通过git和n ...

  2. 前端可视化组件库-Apache ECharts简单介绍vue框架使用eCharts例子

    eCharts是一个基于 JavaScript 的开源可视化图表库. 实现集成了前端可视化的多种手段. 官网链接:ECharts官网 初学者建议去官网看看起步的内容,另外博主也是今天刚学的噢,写得不好 ...

  3. vue插槽面试题_关于前端Vue框架的面试题,面试官可能会问到哪些。?

    这年头,程序员面试都讲究坐姿,姿势不对,努力白费. 参照下图,请同学们对号入座. 回想一下,自己平时面试的坐姿,你在面试官眼里,大概是什么形象,可能是工程师,也可能是键盘侠,或者找麻烦的. 当然了,想 ...

  4. 后端 学习 前端 Vue 框架基础知识

    文章目录 一.Vue 基础语法学习 1.Vue 语法指令 2.Vue 实例属性 (1)el (2)data (3)methods (4)computed 3.事件修饰符 4.按键修饰符 5.Vue实例 ...

  5. Vue框架的入门基础学习

    当创建新的vue项目时,遇到无法加载文件 E:\node\node_global\vue.ps1,因为在此系统上禁止运行脚本的错误,以下为解决办法. vue中文文档 菜鸟教程:Vue.js 该笔记只是 ...

  6. Vue框架Vue-cli脚手架引入图片报错

    Vue框架Vue-cli脚手架引入图片报错 一.import导入图片方法 第一步:在.vue文件中import edit from 'path'(path是图片与.vue的相对路径) 第二步:在dat ...

  7. 前端三大框架Vue框架详解

    Vue框架诞生于2014年,其作者为中国人--尤雨溪,也是新人最容易入手的框架之一,不同于React和Angular,其中文文档也便于大家阅读和学习.Vue用于构建交互式的Web界面的库,是一个构建数 ...

  8. 十分钟带你了解Vue框架

    Vue 框架诞生于2014年,其作者为中国人--尤雨溪. Vue用于构建交互式的Web界面的库,是一个构建数据驱动的Web界面渐进式框架,该框架遵循CMD规范,并且提供的设计模式为MVVM模式. (M ...

  9. Vue框架的学习与使用

    文章目录 VUE简介 前端为主的MV时代 双向绑定 787原则 Vue的7种属性 Vue的8种方法 Vue的7种指令 条件与循环 元素绑定 绑定事件 Vue组件 与自定义元素的关系 Vue的生命周期 ...

最新文章

  1. 在.net中使用强类型来读取配置信息
  2. Flutter Exception降到万分之几的秘密
  3. 解决xcode升级插件失效
  4. 三分钟掌握数据中心“容灾和备份的区别”
  5. 遇到了urlrewriter的:无法使用前导.. 在顶级目录上退出问题
  6. 如何制作U盘启动菜单
  7. 开源个.NetCore写的 - 并发请求工具PressureTool
  8. 字符串反序输出字符串
  9. 案例 TreeView动态控制节点 c# 1614264758
  10. Python学习笔记之列表切片(六)
  11. oracle with as用法_as的用法那么多,你知道多少?
  12. 神经网络是怎样理解图片的?谷歌大脑研究员详解特征可视化
  13. bzoj2437 [Noi2011]兔兔与蛋蛋
  14. spring中bean的自动装配(详细)
  15. 清理autodesk产品注册表_AUTODESK 卸载工具,完美彻底卸载清除干净autodesk各种软件残留注册表和文件...
  16. matlab中进行太阳能电池模型,基于Matlab的光伏发电系统仿真研究
  17. async、await其实是generator和promise的语法糖
  18. 佐治亚理工学计算机硕士,佐治亚理工学院电子与计算机工程硕士专业
  19. GitHub 上排名前 100 的 IOS 开源库介绍
  20. 精确率/召回率/准确率

热门文章

  1. 康先生和哥德尔数配置——哥德尔读后之二十三
  2. win10桌面图标在扩展显示屏后的显示异常问题(桌面图标跑到外接显示屏去了)
  3. 2020考研第一步:基本信息须知
  4. B站频繁暂停并弹出登录框
  5. IDEA 注释模板这样搞
  6. 禁止浏览器自动下载favicon.ico
  7. 树莓派4b无线连接服务器代码,树莓派4B Ubuntu Server 18.04 连接无线 5G WIFI
  8. transformerXL
  9. 美医学博士: 互联网并未实质性地改变医疗行业
  10. 全国马术三项赛锦标赛