📓

Vue.jsの練習②(公式チュートリアルstep-6~step-10)

2024/05/05に公開

Vue.jsの練習①の続き
https://zenn.dev/matcha22/articles/3bbac6ff5a426a

今回は、step-6からstep-10まで(if/else等のディレクティブの説明が中心)
https://vuejs.org/tutorial/

step-6 条件付きレンダリング(v-if,v-else)

<script type="module">
import { createApp } from 'vue'

createApp({
  data() {
    return {
      flg: true
    }
  },
  methods: {
    toggle() {
      this.flg = !this.flg
    }
  }
}).mount('#app')
</script>

<div id="app">
  <button @click="toggle">toggle</button>
  <!-- <button v-on:click="toggle">toggle</button> 上行と同義-->
  <h1 v-if="flg">Vue is awesome!</h1>
  <h1 v-else>Vue is not awesome!</h1>
</div>

v-onは専用の短縮構文(@)がある

  <button @click="toggle">toggle</button>

上行と同義

  <button v-on:click="toggle">toggle</button>

step-7 リストのレンダリング

v-forディレクティブを使用して、配列に基づいて要素をレンダリング

リストに追加

this.todos.push(newTodo)

リストの置き換え
削除したい指定したTodoと異なるもの(削除しないTodo)のtodosリストに置き換える

removeTodo(todo) {
  this.todos = this.todos.filter((t) => t !== todo)
}
<script type="module">
import { createApp } from 'vue'

let id = 0

createApp({
  data() {
    return {
      newTodo: '',
      todos: [
        { id: id++, text: 'Learn HTML' },
        { id: id++, text: 'Learn JavaScript' },
        { id: id++, text: 'Learn Vue' }
      ]
    }
  },
  methods: {
    addTodo() {
      this.todos.push({ id: id++, text: this.newTodo })
      this.newTodo = ''
    },
    removeTodo(todo) {
      this.todos = this.todos.filter((t) => t !== todo)
    }
  }
}).mount('#app')
</script>

<div id="app">
  <form @submit.prevent="addTodo">
    <input v-model="newTodo" required placeholder="new todo">
    <button>Add Todo</button>
  </form>
  <ul>
    <li v-for="todo in todos" :key="todo.id">
      {{ todo.text }}
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
</div>

ref 配列はソース配列と同じ順序を保証しないことに要注意。

step-8 Computed Property(step-7の続き)

Computedを追加する
computed propertyは、値が変わるとその値に依存しているすべてのバインディングが更新される。
参考
https://qiita.com/kaorina/items/bb261a119b9f02e02c2d

<script type="module">
import { createApp } from 'vue'

let id = 0

createApp({
  data() {
    return {
      newTodo: '',
      hideCompleted: false,
      todos: [
        <!-- doneの追加 -->
        { id: id++, text: 'Learn HTML', done: true },  
        { id: id++, text: 'Learn JavaScript', done: true },
        { id: id++, text: 'Learn Vue', done: false }
      ]
    }
  },
  computed: {
    filteredTodos() {
      return this.hideCompleted
        ? this.todos.filter((t) => !t.done)
        : this.todos
    }
  },
  methods: {
<!-- 追加メソッド -->
    addTodo() {
      this.todos.push({ id: id++, text: this.newTodo, done: false })
      this.newTodo = ''
    },
<!-- 削除メソッド -->
    removeTodo(todo) {
      this.todos = this.todos.filter((t) => t !== todo)
    }
  }
}).mount('#app')
</script>

<div id="app">
  <form @submit.prevent="addTodo">
    <input v-model="newTodo" required placeholder="new todo">
    <button>Add Todo</button>
  </form>
  <ul>
    <li v-for="todo in filteredTodos" :key="todo.id">
      <input type="checkbox" v-model="todo.done">
      <span :class="{ done: todo.done }">{{ todo.text }}</span>
      <button @click="removeTodo(todo)">X</button>
    </li>
  </ul>
  <button @click="hideCompleted = !hideCompleted">
    {{ hideCompleted ? 'Show all' : 'Hide completed' }}
  </button>
</div>

参考ページ
https://v2.ja.vuejs.org/v2/guide/computed#算出プロパティ-vs-メソッド

step-9 ライフサイクルとテンプレートの参照

特別な属性を使用して、テンプレート参照、つまりテンプレート内の要素への参照をリクエストできる。その際、コンポーネントがマウントされた後にのみアクセス可能である点に注意が必要である。

<script type="module">
import { createApp } from 'vue'

createApp({
  mounted() {
    this.$refs.pElementRef.textContent = 'mounted!'
  }
}).mount('#app')
</script>

<div id="app">
  <p ref="pElementRef">hello</p>
</div>

関連ページ
https://vuejs.org/guide/essentials/lifecycle.html#lifecycle-diagram

step-10 ウォッチャー

<script type="module">
import { createApp } from 'vue'

createApp({
  data() {
    return {
      todoId: 1,
      todoData: null
    }
  },
  methods: {
    async fetchData() {
      this.todoData = null
      const res = await fetch(
        `https://jsonplaceholder.typicode.com/todos/${this.todoId}`
      )
      this.todoData = await res.json()
    }
  },
  mounted() {
    this.fetchData()
  },
  watch: {
    todoId() {
      this.fetchData()
    }
  }
}).mount('#app')
</script>

<div id="app">
  <p>Todo id: {{ todoId }}</p>
  <button @click="todoId++" :disabled="!todoData">Fetch next todo</button>
  <p v-if="!todoData">Loading...</p>
  <pre v-else>{{ todoData }}</pre>
</div>

関連ページ
https://vuejs.org/guide/essentials/watchers.html

methods:単純な関数の処理に使用
computed:単純な計算やフィルタリングなどの処理に使用
watch:非同期処理やAPIリクエストの発行処理に使用

一言感想

compute,method,watchの使いわけの理解が曖昧だったため、この機会に勉強しておいてよかったなと思う。

Discussion