0

I have 3 .vue here: App.vue (default), Todos.vue and Todoitem.vue. I am following the tutorial from https://www.youtube.com/watch?v=Wy9q22isx3U&t=2458. May I know why the author in TodoItem.vue emit id two level up to App.vue to perform the method to delete? Is it best practice or better coding style? Is it easier to just go up one level for Todos.vue to do the same? Below is my one level up approach for any comment.

Below is my TodoItem.vue code

<template>
  <div class="todo-item" v-bind:class="{'is-complete':todoObj.completed}">
    <p>
      <input type="checkbox" v-on:change="markComplete" />
      {{todoObj.title}}
      <button @click="$emit('del-todo',todoObj.id)" class="del">x</button>
    </p>
  </div>
</template>

<script>
export default {
  name: "TodoItem",
  props: ["todoObj"], // todoObj is defined in the parent.
  methods: {
    markComplete() {
      this.todoObj.completed = !this.todoObj.completed;
    }
  }
};
</script>

<style scoped>
.todo-item {
  background: #f4f4f4;
  padding: 10px;
  border-bottom: 1px #ccc dotted;
}

.is-complete {
  text-decoration: line-through;
}

.del {
  background: #ff0000;
  color: #fff;
  border: none;
  padding: 5px 9px;
  border-radius: 50%;
  cursor: pointer;
  float: right;
}
</style>

Below is my Todo.vue code

<template>
  <div>
    <h1>Todo List2</h1>
    <!-- :key= and v-bind:key= are exactly the same. -->
    <!-- v-bind. Shorthand: : -->
    <div v-for="todo in ptodos" :key="todo.id">
      <!-- Define todoObj here which to be used in the child component, TodoItem -->
      <MyTodoItem v-bind:todoObj="todo" v-on:del-todo="deleteTodo" />
      <!-- del-todo is from the child. child goes up to parent and then to grandparent (App.vue) -->
    </div>
  </div>
</template>

<script>
import MyTodoItem from "./TodoItem.vue";

export default {
  name: "Todos",
  components: {
    MyTodoItem
  },
  props: ["ptodos"],

  methods: {
    deleteTodo(id) {
      this.ptodos = this.ptodos.filter(todo => todo.id !== id);
    }
  }
};
</script>

<style scoped>
</style>

Below is my App.vue code

<template>
  <MyToDos v-bind:ptodos="todos" />
</template>

<script>
import MyToDos from "./components/Todos";

export default {
  name: "App",
  components: { MyToDos },
  data() {
    return {
      todos: [
        {
          id: 1,
          title: "Todo One",
          completed: false
        },
        {
          id: 2,
          title: "Todo Two",
          completed: true
        },
        {
          id: 3,
          title: "Todo Three",
          completed: false
        }
      ]
    };
  }
};
</script>

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

body {
  font-family: Arial, Helvetica, sans-serif;
  line-height: 1.4;
}
</style>
Steve
  • 2,963
  • 15
  • 61
  • 133
  • 1
    Simple... you should not modify prop values. In fact, there should be a warning shown in your console – Phil Jun 01 '20 at 23:44

1 Answers1

1

If you can do it with one level up it's better. To have multiple props on each child can be a bad practice called prop drilling.

Vuex is a good alternative to avoid to get props nested.

Hans Felix Ramos
  • 4,264
  • 3
  • 16
  • 40
  • 2
    You say it's a _"bad practice"_ but link to an article with a section titled [_"Why is prop drilling good?"_](https://kentcdodds.com/blog/prop-drilling#why-is-prop-drilling-good) – Phil Jun 01 '20 at 23:50