重要源码
components\MyItem.vue
<template>
<li>
<label>
<!-- 默认勾选
<input type="checkbox" checked/>
-->
<!-- :checked="true" 表示 我们想给 input 添加一个 checked 选项,如果为true就勾选,否则不勾选。
:checked="todo.done" 初始化谁勾,谁不勾。
<input type="checkbox" :checked="todo.done" @click="handleCheck(todo.id)"/>
-->
<!-- 另外一种方法: 绑定 change事件-->
<input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)"/>
<!-- 如下代码也能实现功能,但是不推荐这种,Vue原则是:props 只能接收数据,不允许修改数据。因为如果修改了props,Vue没有监测到。
<input type="checkbox" v-model="todo.done"/>
-->
<!--span>xxxxx</span-->
<!-- 通过插值语法 展示 接收到的 todo对象-->
<span v-show="!todo.isEdit">{{ todo.title}}</span>
<!-- 089 结构也要准备好 @blur:绑定失去焦点-->
<input type="text"
v-show="todo.isEdit"
:value="todo.title"
@blur="handleBlur(todo,$event)"
ref="inputTitle"
>
</label>
<button class="btn btn-danger" @click="handDelete(todo.id)">删除</button>
<!-- 089 -->
<button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button>
</li>
</template>
<script>
//引入库
import PubSub from 'pubsub-js'
export default {
name:'MyItem',
//声明接收 todo 对象
//继续接收 MyList父组件 发来的数据checkTodo
//props:['todo', "checkTodo", "deleteTodo"],
//086
props:['todo'],
mounted(){
console.log(this.todo)
},
methods: {
//勾选or取消勾选
handleCheck(id) {
console.log(id)
//勾选的时候,传id
//通知 App.vue组件 将对应的 todo对象的 done值 取反
//数据todo对象在哪里? 答: 在 App.vue。 我们有一句总结:数据在哪里,操作数据的方法就在哪里!
//this.checkTodo(id) //把id传递给 父组件MyList,再间接给 爷组件App.vue
//086
this.$bus.$emit('checkTodo',id)
},
//删除
handDelete(id){
//弹窗 单击确定,就为真。单击取消就为假。
if(confirm('确定删除吗?')){
console.log(id)
//删除的时候,传id
//this.deleteTodo(id) //deleteTodo 此时叫 函数名
//086
//this.$bus.$emit('deleteTodo',id) //deleteTodo 此时叫 事件名
//088
PubSub.publish('deleteTodo', id) //deleteTodo 此时叫 消息名
}
},
//089
//编辑
handleEdit(todo){
//todo.isEdit = true
//由于 todo 原来没有 idEdit 元素,所以如果上面这样这样生硬的添加进去会出问题。
//需要调整为:
//如果 todo 身上有 isEdit
//if(todo.hasOwnProperty('isEdit')){
//ESLint规则提示错误,调整为:
if(Object.prototype.hasOwnProperty.call(todo, 'isEdit')){
console.log('todo身上已经有了 isEdit')
todo.isEdit = true //这句话执行完,Vue并没有立刻解析模板. 而是需要等当前 handleEdit() 全部执行完才会去解析模板。
} else {
console.log('todo身上此时还没有 isEdit')
//使用场景: todo身上原来没有isEdit,需要后来添加isEdit
this.$set(todo,'isEdit', true) //响应式添加
}
console.log('handEdit',todo)
//090 通过 ref 拿到 标签
//this.$refs.inputTitle.focus()
//顺序问题:如果之前被隐藏了,此时并不能获取焦点。
//官方解决该问题:
//.nextTick 指定回调函数,会在DOM节点更新完毕后再执行。
this.$nextTick(function(){
this.$refs.inputTitle.focus()
})
},
//失去焦点回调(真正执行修改逻辑)
handleBlur(todo,e){
todo.isEdit = false
console.log('updateTodo',todo.id,e.target.value)
//拿到最新的输入
if(!e.target.value.trim()) return alert('输入不能为空')
this.$bus.$emit('updateTodo',todo.id,e.target.value)
}
}
}
</script>
<style scoped>
/*item*/
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 中的 button */
li:hover button{
display: block;
}
</style>
