Vue第一阶段的练习
MyFlooter.vue 文件中的代码:
<template>
<div class="todo-footer" v-show="totalNumber">
<label>
<input type="checkbox" :checked="isAll" @change="checkAll"/>
<!-- 下面这种方式也可以实现 -->
<!-- <input type="checkbox" v-model="isAll2"/> -->
</label>
<span>
<span>已完成{{doneTotalNumber}}</span> / 全部 {{totalNumber}}
</span>
<button class="btn btn-danger" @click="clearAll">清楚已完成任务</button>
</div>
</template>
<script>
export default {
name:'MyFooter',
props:['todos','checkAllTodo','clearAllTodo'],
computed:{
totalNumber(){
return this.todos.length
},
doneTotalNumber(){
//第一种取数据
// let num = 0
// this.todos.forEach((todo1) => {
// if(todo1.done) num++
// })
// return num
//第二种取数据
// const x = this.todos.reduce((pre,currnet)=>{
// return pre + (currnet.done ? 1 : 0)
// },0)
// return x
//第三种方法,简写第二种方法
//return this.todos.reduce((pre,current)=> pre + (todo.current ? 1 : 0),0)
return this.todos.reduce((pre,todo)=> pre + (todo.done ? 1 : 0),0)
},
isAll(){
return this.doneTotalNumber === this.totalNumber && this.totalNumber>0
},
// isAll2:{
// get(){
// return this.doneTotalNumber === this.totalNumber && this.totalNumber>0
// },
// set(value){
// this.checkAllTodo(value)
// }
// }
},
methods:{
checkAll(e){
this.checkAllTodo(e.target.checked)
},
clearAll(){
this.clearAllTodo()
}
}
}
</script>
<style>
.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;
margin-right: 5px;
}
.todo-footer button {
float: right;
margin-top: 5px;
}
</style>
Top.vue中的代码:
<template>
<div class="todo-header">
<input type="text" v-model="title" @keyup.enter="add" placeholder="请输入你的任务名称,按回车键确认"/>
</div>
</template>
<script>
//引入nanoid
import {nanoid} from 'nanoid'
export default {
name:'Top',
props:['addTodo'],
data(){//使用v-model双向绑定
return {
title:''
}
},
methods:{
add(){
//校验数据
if(!this.title.trim()) return alert('输入不能为空')
//将用户的输入封装成一个todo对象
const todoObj = {id:nanoid(),title:this.title,done:false}
//利用App中的addTodo函数回传一个todoObj对象
this.addTodo(todoObj)
//请空输入
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;
}
.todo-header input:focus {
outline: none;
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
</style>
MyList.vue中的代码:
<template>
<ul class="todo-main">
<MyItem
v-for="todoObj in todos"
:key="todoObj.id"
:todos="todoObj"
:checkTodo="checkTodo"
:deleteTodo='deleteTodo'
/>
</ul>
</template>
<script>
import MyItem from './MyItem.vue'
export default {
name:'MyList',
components:{
MyItem
},
props:['todos','checkTodo','deleteTodo','checkAllTodo']
}
</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>
MyItem.vue中的代码:
<template>
<li>
<label>
<!--这里可以使用三种方式-->
<!--<input type="checkbox" :checked="todos.done" @click="handlerCheck(todos.id)"/>-->
<input type="checkbox" :checked="todos.done" @change="handlerCheck(todos.id)"/>
<!-- 如下代码也能够实现,但是不建议使用,因为修改了props -->
<!-- <input type="checkbox" v-model="todos.done"/> -->
<span>{{todos.title}}</span>
</label>
<button class="btn btn-danger" @click="handlerDelete(todos.id)">删除</button>
</li>
</template>
<script>
export default {
name:'MyItem',
//声明接收todo对象
props:['todos','checkTodo','deleteTodo'],
methods:{
handlerCheck(id){
this.checkTodo(id)
},
handlerDelete(id){
if(confirm('确定删除吗?')){
this.deleteTodo(id)
}
}
}
}
</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 {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover{
background-color: #ddd;
}
li:hover button{
display: block;
}
</style>
main.js中的代码:
//引入残缺版的vue
import Vue from 'vue'
//引入完整版的vue
//import Vue from 'vue/dist/vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
// new Vue({
// el:'#app',
// render: h => h(App)
// })
App.vue中的代码:
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<Top :addTodo="addTodo"/>
<MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
<MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
</div>
</div>
</div>
</template>
<script>
//引入组件
import Top from './components/Top.vue'
import MyList from './components/MyList.vue'
import MyFooter from './components/MyFooter.vue'
export default {
name:'App',
data(){
return {
todos:[
{
id:'001',
title:'睡觉',
done:false
},
{
id:'002',
title:'抽烟',
done:false
},
{
id:'003',
title:'喝酒',
done:false
},
{
id:'004',
title:'烫头',
done:true
}
]
}
},
components:{
Top,
MyList,
MyFooter
},
methods:{
//接收函数--添加一个
addTodo(todoObj){
this.todos.unshift(todoObj)
},
//勾选或者取消勾选
checkTodo(id){
this.todos.forEach((todos1)=>{
if(todos1.id === id) todos1.done = !todos1.done
})
},
//删除一个todo
deleteTodo(id){
this.todos = this.todos.filter((todo1)=>{
return todo1.id !== id
})
},
//全选
checkAllTodo(done){
this.todos.forEach((todo4)=>{
todo4.done = done
})
},
//删除所有已选的项
clearAllTodo(){
this.todos = this.todos.filter((todo4)=>{
return !todo4.done
})
}
}
}
</script>
<style>
body {
background-color: #fff;
}
.btn {
display: inline-block;
padding: 4px 12px;
margin-bottom:0 ;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset 0 1px rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.btn-danger{
color: #fff;
background-color: #da4f49;
border:1px solid #bd362f;
}
.btn-danger:hover {
color: #fff;
background-color:#bd362f;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border:1px solid #ddd;
border-radius:5px;
}
</style>
index.html中的代码:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<!--针对IE浏览器的一个特殊配置,让IE浏览器以最高的渲染级别渲染页面-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!---开启移动端的理想视口-->
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<!--配置页签的图标-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!--配置网页的标题-->
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
项目部分目录结构: