尤你 2022-06-23 17:38:57 阅读数:14
需求案例说明:
使用 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进行传递相关的数据或者函数来完成案例。
<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>
<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>
<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>
<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>
<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>
v-model 属性可实现DOM数据与Vue对象属性的双向绑定,但是v-model绑定的值不能是 props
传递过来的值,因为props
是不可以修改的。
props
传递到组件的值若是对象类型的值,那么修改对象中的属性时,Vue并不会报错,但不推荐这样使用。
这几天刚正式接触 Vue,毕竟是封装的框架,感觉比较容易上手,而且工程化的设计思想和后端设计思路类似,早知道之前就用这个框架做课设了,之前是用的JQuery,导致HTML、CSS和JavaScript三者之间关系比较混乱,现在用Vue的组件化编程,代码优雅许多。
版权声明:本文为[尤你]所创,转载请带上原文链接,感谢。 https://blog.csdn.net/Unirithe/article/details/125364107