Vue学习笔记(一)基于Vue2的TodoList待办事项增删查案例 | 基于Node.js 使用Vue-CLI脚手架构建项目

尤你 2022-06-23 17:38:57 阅读数:14

学习vue笔记vue2

一、参考资料


二、运行环境


  • Windows11
  • Visual Studio Code v2022
  • Node.js v16.5.01
  • Vue/cli v5.0.6

需求案例说明:

使用 Vue2模块化编程方式来实现下图的案例(样式是参照教程随便写的,这里以熟悉Vue2为主)

在这里插入图片描述

项目结构:

在这里插入图片描述

说明:

Vue2支持模块化编程,一个 Vue后缀的文件表示一个Vue组件,其中通常包括 :

1) HTML 代码,即<template> 标签,
2) JS代码,即<script>标签 ,通常是返回 Key-Value 形式的对象,表示一些关于Vue组件的参数,包括变量和函数。
3)CSS样式代码,即<style> 标签,通常使用 scoped 限制样式只在当前组件内有效。

三、根据需求进行分模块开发

在这里插入图片描述
根据界面可将这个Todo案例分为三个模块,分别是 Header、Body和Footer,其中Body中由多个待办事项组成,所以Body还可以分成多个TodoItem,所以共有4个模块。

需要注意的是,在Vue2工程中,App.vue类似于 SpringBoot里的启动类,是主要导入在HTML的组件,所以关于数据的存储和修改都将放在App.vue中,而其他的组件则需要通过App进行传递相关的数据或者函数来完成案例。

四、代码实现

App.vue

<template>
<div id="app">
<h1><img src="./assets/logo.png">基于Vue2的TodoList案例</h1>
<TodoHeader :fnAddTodo="fnAddTodo" ></TodoHeader>
<TodoBody :todoList="todoList" :fnCheckTodo="fnCheckTodo" :fnDeleteTodo="fnDeleteTodo"></TodoBody>
<TodoFooter :todoList="todoList" :fnUpdateTodo="fnUpdateTodo" :fnClearFinishedTodo="fnClearFinishedTodo"></TodoFooter>
</div>
</template>
<script> import TodoHeader from './components/TodoHeader.vue' import TodoBody from './components/TodoBody.vue' import TodoFooter from './components/TodoFooter.vue' export default {
 name: 'App', data(){
 return {
 todoList: [ {
id: '001', title: '吃饭', done: true}, {
id: '002', title: '睡觉', done: false}, {
id: '003', title: '玩', done:false} ], } }, methods: {
 // 函数: 添加新的待办事项 fnAddTodo(todoObj){
 this.todoList.unshift(todoObj) }, // 函数: 切换待办事项的状态 fnCheckTodo(id){
 this.todoList.forEach((todoObj) => {
 if(id === todoObj.id) todoObj.done = !todoObj.done }) }, // 函数: 删除待办事项 fnDeleteTodo(id){
 this.todoList = this.todoList.filter(todoObj => todoObj.id !== id) }, // 函数: 批量操作待办事项的状态 fnUpdateTodo(done){
 this.todoList.forEach((todoObj) => todoObj.done = done) }, // 函数: 清除已完成的待办事项 fnClearFinishedTodo(){
 if(confirm('确认要删除吗?')) this.todoList = this.todoList.filter((todoObj) => !todoObj.done) } }, components: {
TodoHeader, TodoBody, TodoFooter} } </script>
<style scoped> h1{
 text-align: center;} img{
 width: 50px; height: 50px;} #app{
 width: 600px; margin: 0 auto; } </style>

TodoHeader.vue

<template>
<div>
<label for="add">待办事项</label>
<input id="add" v-model="title" @keydown.enter="add" placeholder="请输入任务标题, 敲回车确认">
<button @click="add">添加</button>
</div>
</template>
<script> // 第三方库 npm i nanoid import {
nanoid} from 'nanoid' export default {
 name: 'TodoHeader', data() {
 return {
 title: '' } }, methods: {
 // 添加Todo add(){
 if(!this.title.trim()) return alert('提示:输入的待办事项不能为空!') // 封装 Todo 对象 const todoObj = {
 id: nanoid(), title: this.title, done: false } // 调用回调函数 this.fnAddTodo(todoObj) // 清空 this.title = '' } }, // 引入上层App的方法 props: ['fnAddTodo'] } </script>
<style scoped> div{
 background: gray; padding: 20px; font-size: 1.2em; } button, input{
 font-size: 1.1em; } button{
 float: right; } </style>

TodoBody.vue

<template>
<div>
<ul>
<li v-for="todoObj in todoList" :key="todoObj.id">
<TodoItem :todoObj="todoObj" :fnCheckTodo="fnCheckTodo" :fnDeleteTodo="fnDeleteTodo"></TodoItem>
</li>
</ul>
</div>
</template>
<script> import TodoItem from './TodoItem.vue' export default {
 name: 'TodoBody', components: {
TodoItem}, props: ['todoList', 'fnCheckTodo', 'fnDeleteTodo'] } </script>
<style scoped> div{
 background: pink; padding: 20px; font-size: 1.1em; } ul{
 list-style: none; padding-left: 0px; } </style>

TodoItem.vue

<template>
<nav>
<input type="checkbox" :checked="todoObj.done" @change="handlerCheckTodo(todoObj.id)">
<span>{
{ todoObj.title }}</span>
<button @click="handlerDeleteTodo(todoObj.id)">删除</button>
</nav>
</template>
<script> export default {
 name: 'TodoItem', methods: {
 handlerCheckTodo(id){
 this.fnCheckTodo(id) }, handlerDeleteTodo(id){
 if(confirm('确认要删除Id为 [' + id + '] 的待办事项吗?')) this.fnDeleteTodo(id) } }, // 引入Body传来的todoObj 和 App传来的 fnCheckTodo方法 props: ['todoObj', 'fnCheckTodo', 'fnDeleteTodo'], } </script>
<style scoped> nav{
 background: rgb(196, 100, 100); padding: 20px; font-size: 1.1em; } button{
 float:right; font-size: 1.1em; display: none; } input{
 width:1.5em; height:1.5em } nav:hover{
 background: rgb(31, 101, 167); } nav:hover button{
 display: block; } </style>

<template>
<nav>
<input type="checkbox" :checked="todoObj.done" @change="handlerCheckTodo(todoObj.id)">
<span>{
{ todoObj.title }}</span>
<button @click="handlerDeleteTodo(todoObj.id)">删除</button>
</nav>
</template>
<script> export default {
 name: 'TodoItem', methods: {
 handlerCheckTodo(id){
 this.fnCheckTodo(id) }, handlerDeleteTodo(id){
 if(confirm('确认要删除Id为 [' + id + '] 的待办事项吗?')) this.fnDeleteTodo(id) } }, // 引入Body传来的todoObj 和 App传来的 fnCheckTodo方法 props: ['todoObj', 'fnCheckTodo', 'fnDeleteTodo'], } </script>
<style scoped> nav{
 background: rgb(196, 100, 100); padding: 20px; font-size: 1.1em; } button{
 float:right; font-size: 1.1em; display: none; } input{
 width:1.5em; height:1.5em } nav:hover{
 background: rgb(31, 101, 167); } nav:hover button{
 display: block; } </style>

TodoFooter.vue

<template>
<nav v-show="totalTodoList">
<input type="checkbox" v-model="isAll">
已完成 {
{ totalFinishedTodo }} / 全部 {
{ totalTodoList }}
<button @click="fnClearFinishedTodo">清除已完成</button>
</nav>
</template>
<script> export default {
 name: 'TodoFooter', props: ['todoList', 'fnUpdateTodo', 'fnClearFinishedTodo'], // 计算属性 computed:{
 // 计算已完成的待办事项 totalFinishedTodo(){
 return this.todoList.reduce((pre, todoObj) => pre + (todoObj.done ? 1 : 0), 0) }, // 所有的待办事项 totalTodoList(){
 return this.todoList.length }, isAll: {
 // 全选按钮默认的勾选条件: 所有待办事项都已经完成 get(){
 return this.totalTodoList > 0 && this.totalFinishedTodo == this.totalTodoList }, set(value){
 return this.fnUpdateTodo(value) } } } } </script>
<style scoped> nav{
 background: greenyellow; padding: 20px; font-size: 1.1em; } input{
 height: 1.5em; width: 1.5em; } button{
 float:right; font-size: 1.1em; } </style>

五、要点总结

5.1 Vue2组件化编码流程

  1. 拆分静态组件:组件要按照功能要点拆分,命名不要和Html元素冲突
  2. 实现动态组件:考虑好数据的存放位置,数据是单个组件在用还是多个组件在用。
  • 单个组件在用:放在组件本身即可
  • 多个组件在用:放在他们之间的共同上层组件上(高内聚,低耦合)
  1. 实现交互:从绑定事件开始

5.2 props适用场景

  1. 父组件 ==> 子组件 进行数据通信
  2. 子组件 ==> 父组件 通信(要求父组件先给子组件一个函数)

5.3 慎用v-model

v-model 属性可实现DOM数据与Vue对象属性的双向绑定,但是v-model绑定的值不能是 props 传递过来的值,因为props是不可以修改的。

5.4 props

props 传递到组件的值若是对象类型的值,那么修改对象中的属性时,Vue并不会报错,但不推荐这样使用。

5.5 个人总结

这几天刚正式接触 Vue,毕竟是封装的框架,感觉比较容易上手,而且工程化的设计思想和后端设计思路类似,早知道之前就用这个框架做课设了,之前是用的JQuery,导致HTML、CSS和JavaScript三者之间关系比较混乱,现在用Vue的组件化编程,代码优雅许多。

版权声明:本文为[尤你]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/Unirithe/article/details/125364107