用vue写一个todo的简单例子

要求:实现基本的增删查改

第一步:新建一个项目

成功创建的样子:

项目目录如图所示:

运行效果如下所示:(该有的功能都实现了,视频暂时传不上来

 

 footer代码:

<template>
    <div class="todo-footer">
        <label>
          <input type="checkbox" v-model="isCheck"/>
        </label>
        <span>
          <span>已完成{{finishedCount}}件</span> / 总计{{todos.length}}件
        </span>
        <button class="btn btn-warning" @click="delFinishedTodos">清除已完成任务</button>
    </div>
</template>

<script>
export default{
    name:"Footer",
    props:{
        todos:Array,
        selectedAll:Function,
        delFinishedTodos:Function
    },
    computed:{
        finishedCount(){
            return this.todos.reduce((total,todo)=>total + (todo.finished ? 1 : 0),0)
        },
        isCheck:{
            get(){
                return this.finishedCount === this.todos.length && this.todos.length > 0
            },
            set(value){
                this.selectedAll(value)
            }
        }
    }
}
</script>


<style scoped>
    /*尾部*/
.todo-footer {
  height: 40px;
  line-height: 40px;
  padding-left: 6px;
  margin-top: 5px;
}

.todo-footer label {
  display: inline-block;
  margin-right: 20px;
  cursor: pointer;
}

.todo-footer label input {
  position: relative;
  top: -1px;
  vertical-align: middle;
}

.todo-footer button {
  float: right;
  margin-top: 5px;
}

</style>

header代码:

 

<template>
    <div class="todo-header">
        <input 
        type="text" 
        placeholder="请输入今天的任务清单,按回车键确认"
        v-model="title"
        @keyup.enter="addItem"
        />
    </div>
</template>

<script>
export default{
    name:"Header",
    props:{
        addTodo:Function
    },
    data(){
        return{
            title:''
        }
    },
    methods:{
        addItem(){
            //1,1判断是否合理
            const title = this.title.trim();
            if(!title){
                alert('输入内容不能为空');
                return;
            }
            //1,2生成一个todo对象
            const todo = {title,finished:false};
            //1.3调用方法
            this.addTodo(todo);
            //1.4清空输入框
            this.title = ''
        }
    }
}
</script>
 
<style scoped>
    /*头部*/
    .todo-header input{
        width: 560px;
        height: 28px;
        font-size: 14px;
        border: 1px solid #ccc;
        border-radius: 4px;
        padding: 4px 7px;
        outline: none;
    }
    .todo-header input:focus{
        outline: none;
        border-color: rgba(255,0,0,0.8);
        box-shadow: inset 0 1px 1px rgba(255, 0, 0, 0.075),0 0 8px rgba(255, 0, 0, 0.6);
    }
</style>

 Item代码:

<template>
    <li 
    @mouseenter="dealShow(true)" 
    @mouseleave="dealShow(false)"
    :style="{background:bgColor}"
    >
          <label>
            <input type="checkbox" v-model="todo.finished"/>
            <span>{{todo.title}}</span>
          </label>
          <button v-show="isShowDelButton" @click="delItem">删除</button>
        </li>
        
</template>

<script>
export default{
    name:"Item",
    props:{
        todo:Object,
        index:Number,
        delTodo:Function
    },
    data(){
        return {
            bgColor:'#fff',
            isShowDelButton:false
        }
    },
    methods:{
        dealShow(flag){
            this.bgColor = flag ? '#ddd' : '#fff';
            this.isShowDelButton = flag;
        },
        delItem(){
            if(window.confirm(`确定删除${this.todo.title}吗?`)){
                this.delTodo(this.index)
            }
        }
    }
}
</script>


<style scoped>
     /*列表选项*/
li {
  list-style: none;
  height: 36px;
  line-height: 36px;
  padding: 0 5px;
  border-bottom: 1px solid #ddd;
}

li label {
  float: left;
  cursor: pointer;
}

li label li input {
  vertical-align: middle;
  margin-right: 6px;
  position: relative;
  top: -1px;
}

li button {
  background-color: orangered;
  padding: 4px 10px;
  border-radius: 5px;
  color: #fff;
  border: none;
  float: right;
  margin-top: 3px;
  outline: none;
  cursor: pointer;
}

li:before {
  content: initial;
}

li:last-child {
  border-bottom: none;
}
</style>

 List代码:

<template>
     <ul class="todo-main">
        <Item
            v-for="(todo,index) in todos"
            :key="index"
            :index="index"
            :todo="todo"
            :delTodo="delTodo"
        />
      </ul>
</template>

<script>
//1,引入
import Item from './Item'
export default{
    name: "List",
    props:{
        todos:Array,
        delTodo:Function
    },
    components:{
        Item
    }
}
</script>

<style scoped>


/*列表*/
.todo-main {
  margin-left: 0px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0px;
}

.todo-empty {
  height: 40px;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding-left: 5px;
  margin-top: 10px;
}
   

</style>

 App.vue代码:

<template>
  <div id="app">
    <div class="todo-container">
    <div class="todo-wrap">
      <Header :addTodo="addTodo"/>
      <List :todos="todos" :delTodo="delTodo"/>
      <Footer :todos="todos" :selectedAll = "selectedAll" :delFinishedTodos="delFinishedTodos"/>
     
      
    </div>
  </div>
  </div>
</template>

<script>
//1,引入
import Header from './components/Header'
import Footer from './components/Footer'
import List from './components/List'


export default{
  name: "App",
  data(){
    return{
      todos:[
        {title:'学爵士', finished:false},
        {title:'发SCI',  finished:false},
        {title:'蓝桥杯',  finished:true},
      ]
    }
  },
  //2,映射
  components:{
    Header,
    Footer,
    List
    
    
  },
  methods:{
    //插入一条记录
    addTodo(todo){
      this.todos.unshift(todo);
    },
    //删除一条记录
    delTodo(index){
      // debugger;
      this.todos.splice(index,1);
    },
    //选中所有计划
    selectedAll(isCheck){
      this.todos.forEach(todo=>{
        todo.finished = isCheck
      })
    },
    delFinishedTodos(){
      this.todos = this.todos.filter(todo => !todo.finished)
    }
  }
}
</script>

<style scoped>
/*主面板*/
.todo-container {
  width: 600px;
  margin: 0 auto;
}
.todo-container .todo-wrap {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

</style>

main.js代码:

// // The Vue build version to load with the `import` command
// // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
// import Vue from 'vue'
// import App from './App'

// Vue.config.productionTip = false

// /* eslint-disable no-new */
// new Vue({
//   el: '#app',
//   components: { App },
//   template: '<App/>'
// })


import Vue from 'vue'
import App from './App'
import './assets/css/base.css'

new Vue({
  el:'#app',
  components:{
    App
  },
  template:'<App/>'
});

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值