待办事项网页实现-勾选

125 阅读1分钟

将网页中勾选与vc中的done进行绑定

image.png

不能使用v-model,因为props只可读不可改

image.png

获取勾选或者取消勾选事情的id

有以下两种方法:

方法一:@click()

先在UserItem中绑定一个点击事件,获取todo上id
image.png

勾选上洗碗,就会在控制台输出它的id
image.png

方法二:@change()

将刚才的@click事件改为@change事件也是可以的
image.png

通使勾选框发生改变,触发change事件,如:取消勾选打代码事情,就可以看到控制台输出了它的id
image.png

通过id来改它的done

一般通过方法改数据,方法都是和数据在同一个文件上,所以我们要在app组件上加一个方法
image.png

然后我们要把这个方法传给UserItem,就是说我们要先把方法从app传给UserList,
image.png

在UserList用props接收,再从UserList传给UserItem
image.png

在UserItem用props接收,并且在handleCheck方法调用checkTodo方法
image.png

效果实现如下
image.png

勾选洗碗后vc的done也跟着变成true了
image.png

本结主要代码如下: UserList.vue

<template>
  <ul class="todo-main">
    <UserItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj" :checkTodo="checkTodo" />
  </ul>
</template>

<script>
// 引入组件
import UserItem from "./UserItem.vue";

export default {
  name: "UserList",
  components: { UserItem },
  props: ["todos", "checkTodo"],
  data() {
    return {};
  },
};
</script>

<style scoped>
/* main */
.todo-main {
  /* background-color: aqua; */
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0;
}

.todo-empty {
  height: 40px;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding-left: 5px;
  margin-top: 10px;
}
</style>
UserItem.vue
<template>
  <li>
    <label>
       <input type="checkbox" :checked='todo.done' @change="handleCheck(todo.id)" />
       <span>{{todo.title}}</span>
    </label>
    <button class="btn btn-danger" style="display: none">删除</button>
  </li>
</template>

<script>
// 组件交互相关的代码(数据、方法等等)
export default {
  name: "UserItem",
   props: ["todo","checkTodo"],
   methods: {
    handleCheck(id) {
      this.checkTodo(id)
    },
  }
};
</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 input {
  vertical-align: middle;
  margin-right: 6px;
  position: relative;
  top: -1px;
  cursor: pointer;
}

li button {
  float: right;
  display: none;
  margin-top: 3px;
}

li:before {
  content: initial;
} 

li:last-child {
  border-bottom: none;
}
</style>
App.vue
<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-wrap">
        <UserHeader :AddTodoObj="AddTodoObj" />
        <UserList :todos="todos" :checkTodo="checkTodo" />
        <UserFooter />
      </div>
    </div>
  </div>
</template>

<script>
// 引入组件
import UserHeader from "./components/UserHeader.vue";
import UserList from "./components/UserList.vue";
import UserFooter from "./components/UserFooter.vue";

export default {
  name: "App",
  components: { UserHeader, UserList, UserFooter },
  data() {
    return {
      todos: [
        { id: "001", title: "打代码", done: true },
        { id: "002", title: "看电视剧", done: true },
        { id: "003", title: "洗碗", done: false },
      ],
    };
  },
  methods: {
    // 添加一个todo
    AddTodoObj(todoObj) {
      this.todos.unshift(todoObj);
      
      // console.log("我是App组件,我收到了数据", x);
    },
    // 勾选or取消勾选一个todo
    checkTodo(id) {
      this.todos.forEach((todo) => {
        if (todo.id === id) todo.done = !todo.done;
      });
    },
  },
};
</script>

<style>
/* base */
body {
  background-color: #fff;
  /* margin: 0; */
}

.todo-container {
  width: 600px;
  margin: 0 auto;
  /* background-color: antiquewhite; */
}

.todo-container .todo-wrap {
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 5px;
}

.btn {
  display: inline-block;
  padding: 4px 12px;
  /* margin-bottom: 0; */
  font-size: 14px;
  /* line-height: 20px; */
  /* text-align: center; */
  /* vertical-align 用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐      方式 */
  vertical-align: middle;
  cursor: pointer;
  box-shadow: inset 0 1px 0px rgba(255, 255, 255, 0.2),
    0 1px 2px rgba(0, 0, 0, 0.05);
  border-radius: 4px;
}

.btn:focus {
  /* outline: none; */
}

.btn-danger {
  color: #fff;
  background-color: #da4f49;
  border: 1px solid #bd362f;
}

.btn-danger:hover {
  color: #fff;
  background-color: #bd362f;
}
</style>