实战篇 TodoList (Vue2 前端 - 静态页面实现)

写在开头

这篇文章是结合Django后端实战篇搭配食用的

实战篇 TodoList (Django 后端)-CSDN博客文章浏览阅读7次。title = models.CharField(max_length=32, verbose_name='任务标题')completed = models.IntegerField(default=0, verbose_name='是否完成 1完成 0未完成')is_delete = models.IntegerField(default=0, verbose_name='删除标志位 1删除 0未删除')https://blog.csdn.net/m0_56825253/article/details/134694523?spm=1001.2014.3001.5502

这是我们最终要实现的效果

环境搭建

本地需要有node环境

Download | Node.jsNode.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.icon-default.png?t=N7T8https://nodejs.org/en/download还需要有Vue环境

创建Vue项目brower_vue2

vue create brower_vue2

选择默认的Vue 2模版即可。

写代码前的准备 

我认为思考的过程远远比codeing的过程重要

首先做前端,我们要知道页面大致长什么样,都需要设计哪些页面, 哪些可以抽离成为组件。

这是我绘制的草图,通过绘制草图过程,我知道可以写以下几个页面和组件

pages: todoPanel

components: todoList.vue todoItem.vue todoHeader.vue todoFooter.vue

知道了这些我们就可以进行下一步的coding了

统一配置

关闭EsLint检查

打开vue.config.js文件

const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave: false,
});

统一目录结构

按照这个目录建立文件,并清空App.vue到最干净的状态(如下), 删除HelloWorld.vue组件

<template>
  <div class="app-container">
    
 </div>
</template>

<script>
export default {
  data() { 
    return {

    }
  },
}
</script>

<style>

</style>

依赖包的安装

因为写样式我这里使用的是sass, 为什么要使用这个而不是css呢,它书写会有层次结构,比css的易读性更好,下面的代码中会大量的出现这样的样式代码

npm i -D sass sass-loader

之后写样式就只需要表明样式文件类型即可

<style scoped lang='scss'>

</style>

组件和页面的编写

todoList

这个是todoList.vue组件,

该组件需要接收一个todoList的props数据,类型为Array

组件内部,循环遍历todoItem.vue组件

<template>
  <div class="list-container">
    <div v-for="todo,index in todoList" :key="index">
      <todoItem :todo-item="todo"/>
    </div>
 </div>
</template>

<script>
import todoItem from './todoItem.vue';
export default {
  name: "todoList", 
  props: {
    todoList: {
      type: Array,
      default: () => []
    }
  },
  components: {
    todoItem
  },
  data() { 
    return {
      
    }
  },
}
</script>

<style scoped>
.list-container {
  flex: 1;
  width: 96%;
  margin: auto;
  overflow-y: auto;
}
</style>

todoItem

todoItem组件

这个组件接收一个todo对象,看过《实战篇 TodoList (Django 后端)》文章的就会知道,我们的todo对象都包含哪些数据

let todo = {
    id: 1,
    completed: 1,
    title: "Vue2"
}
<template>
  <div class="todo_item">
    <input type="checkbox" :checked="todoItem.completed==1">
    <div class="title" :class="{completed: todoItem.completed == 1} ">
        {{ todoItem.title }}
    </div>
    <button class="delete" >删除</button>
 </div>
</template>

<script>
export default {
  name: "todoItem",
  props: {
    todoItem: {
      type: Object,
      require: true,
      default: () => {}
    }
  },
}
</script>

<style scoped lang="scss">
.todo_item {
  display: flex;
  align-items: center;
  width: 100%;
  border: 1px solid rgb(92 96 241);
  border-radius: 20px;
  height: 60px;
  padding: 0 10px;
  margin-bottom: 8px;
  
  input {
    width: 50px;
  }
  div.title {
    flex: 1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    &.completed {
      color: #9d9d9d;
      text-decoration: line-through;
    }
  }
  
  
  button.delete {
    display: none;
    cursor: pointer;
    border: none;
    background-color: rgb(249, 119, 119);
    color: white;
    height: 30px;
    padding: 0 10px;
    border-radius: 10px;

    &:hover {
      background-color: rgb(249, 3, 3);
    }
  }

  &:hover button.delete {
    display: block;
  }
}
</style>

todoHeader

这个组件只需要将任务标题输入即可,至于之后的如何发布一个新的todo,会在下一篇文章中详细讲解

<template>
  <div class="todo-header">
    <input placeholder="请输入任务标题" v-model="title" /> 
    <button>添加</button>
 </div>
</template>

<script>
export default {
  name: "todoHeader", 
  data() { 
    return {
      title: ''
    }
  },
}
</script>

<style scoped lang="scss">
.todo-header {
  width: 100%;
  height: 80px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid #9e9e9e;
  padding: 0 10px;
  input {
    height: 80%;
    width: 80%;
    outline: none;
    background-color: transparent;
    border: none;
    padding: 0 10px;
    font-size: 20px;
    color: #646363;
    flex: 1;
  }
  button {
    border: none;
    background-color: rgb(92 96 241);
    height: 50px;
    color: white;
    width: 60px;
    border-radius: 12px;
    cursor: pointer;
    font-size: 15px;

    &:hover {
      background-color: rgb(128, 132, 236);
    }
  }
}

</style>

todoFooter

这个组件只需要统计两个数据即可, 分别是当前完成任务量和任务量总数

<template>
  <div class="todo-footer">
    <div> 任务进度:<span>{{ current }}</span> / <span>{{ total }}</span> </div>
    <div class="clear_all">清空已完成任务</div>
 </div>
</template>

<script>

export default {
  props: {
    total: {
      type: Number,
      default: 0
    },
    current: {
      type: Number,
      default: 0
    },
  },
  name: "todoFooter", 
}
</script>

<style scoped lang="scss">
.todo-footer {
  display: flex;
  width: 95%;
  align-items: center;
  justify-content: space-between;

  div.clear_all {
    user-select: none;
    cursor: pointer;

    &:hover {
      color: rgb(92 96 241);
    }
  }
}
</style>

todoPanel

引入上面建立好的todoHeader, todoFooter, todoList组件, 并且todoList的数据在这个组件中定义

并且使用计算属性计算出total和current两个值分别是多少

<template>
  <div class="todoPanel">
    <todo-header />
    <todoList :todo-list="todoList"/>
    <todo-footer :total="total" :current="current" />
 </div>
</template>

<script>
import todoList from '@/components/todoList'
import todoHeader from '@/components/todoHeader'
import todoFooter from '@/components/todoFooter'

export default {
  name: "todoPanel", 
  components: {
    todoList, todoHeader, todoFooter
  },
  data() {
    return {
      todoList: [
        
      ]
    }
  },
  computed: {
    total() {
      return this.todoList.length;
    },
    current() {
      return this.todoList.filter(e => e.completed == 1).length
    }
  }
}
</script>

<style scoped>
.todoPanel {
  width: 500px;
  height: 700px;
  border: 2px solid;
  display: flex;
  flex-direction: column;
  align-items: center;
  border-radius: 15px;
}
</style>

 

页面呈现

做完以上步骤之后,还记得App.vue这个空空荡荡的文件吗?

这是我们项目的入口文件,所以将todoPanel再此引入并展示即可

<template>
  <div class="app-container">
    <todoPanel />
 </div>
</template>

<script>
import todoPanel from '@/views/todoPanel'
export default {
  components: {
    todoPanel
  },
  data() { 
    return {

    }
  },

}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
</style>

<style scoped>
.app-container {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
</style>

 终于做完了,此时你欣喜若狂, npm run serve运行项目一看,居然页面长这样,我的数据呢?

 

对啊,数据呢, 还记得我们前面说数据定义在哪里了吗? —— todoPanel中

才发现我们定义的是空数据,添加几条数据试试吧

todoList: [
  {
    id: 1,
    title: "Vue2",
    completed: 1
  },
  {
    id: 2,
    title: "Vue 3",
    completed: 0
  },
  {
    id: 3,
    title: "Django",
    completed: 0
  },
  {
    id: 4,
    title: "Django Rest FrameWork",
    completed: 1
  },
]

 

结尾🎉 

到此为止,静态页面算是大功告成了

但是到这里为止,所有的页面交互都是行不通的

写在最后

下一篇文章: 我会详细介绍如何与我们之前写好的接口配合使用

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值