理系公務員のプログラミング日記

Vue3でTwitterクローンを作る その2

タグ:
vue3
授業課題の解説

ツイートの部分のデザインを整えて、いいねボタンを追加する

それぞれのツイートに、ユーザー名@ユーザーIDの表示を追加し、さらにいいねボタンを追加します。

ハートマークはBootstrap Iconsから引っ張ってきています。

ハートマークのsvgタグにv-on:clickでクリックイベントを追加しました。

ハートマークをクリックすると、likeCountが増えていきます。

Tweets.vue

<template> <div class="card"> <div class="card-header bg-white"> {{ Tweet.tweet_user.user_name }}@{{ TweetObj.tweet_user.user_id }} </div> <div class="card-body"> <div class="card-text">{{ Tweet.tweet_body }}</div> </div> <div class="card-footer bg-white"> <div> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart m-2" viewBox="0 0 16 16" v-on:click="doCount" > <path d="m8 2.748-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z" /> </svg> {{ like }} </div> </div> </div> </template> <script> export default { name: "Tweet", props: { TweetObj: Object, }, data() { return { likeCount: 0, }; }, methods: { doCount() { this.likeCount++; }, }, }; </script>

twittervue4

ユーザーを切り替える

ユーザーを切り替えてつぶやきを投稿できるようにします。

App.vueに追加していくとごちゃごちゃするので、新しくselectUserコンポーネントを作り、そこにセレクトボックスでユーザーを選択できるようにします。

(もちろん、実際はログインフォームのコンポーネントを作り、そこからユーザー情報を渡していきます。)

セレクトボックスの実装には、tweet_usersというリストをdata()に持たせて、それをv-forを使って分解して、optionタグにデータを渡します。

調べたら良い実装があったので参考にしました:Vue.js入門その7〜セレクトボックスを動的に変更してみる〜

セレクトボックスでユーザを選択してボタンをクリックすると、そのイベントによって親のApp.vueにtweet_userオブジェクトを送信します。

selectUser.vue

<template> <div class="menu"> <h5 class="text-success">ユーザーの切り替え</h5> <select class="form-select" v-model="selectedUser"> <option v-for="tweet_user in tweet_users" v-bind:value="tweet_user" v-bind:key="tweet_user.user_id" > {{ tweet_user.user_name }} </option> </select> <button class="text-white bg-primary p-2 m-2 rounded" v-on:click="changeUser">切り替え</button> </div> </template> <script> export default { name: "SelectUser", data() { return { tweet_users: [ { user_id: "test_a", user_name: "Aさん" }, { user_id: "test_b", user_name: "Bさん" }, { user_id: "test_c", user_name: "Cさん" }, ], selectedUser: { user_id: "test_a", user_name: "Aさん" }, }; }, methods: { changeUser(){ this.$emit('selectUser-event',this.selectedUser) } }, }; </script> <style> .menu { margin: 5px; font-size:large; width: 20%; margin: 30px; } </style>

親のAppコンポーネントでは、受け取ったtweet_userオブジェクトを入力フォームに渡します。

App.vue

<template> <div> <div class="wrapper"> <!-- ユーザー情報を渡すイベント --> <SelectUser v-on:selectUser-event="selectUser" /> <div class="tweet-contents"> <h2 class="text-success">Twitter-Vue3</h2> <div class="content"> <!-- ユーザー情報をpropsで受け取る --> <Form v-on:tweet-event="tweetAction" v-bind:user="tweet_user" /> <div style="margin-top:20px"> <Tweet v-for="Tweet in AllTweet" v-bind:TweetObj="Tweet" v-bind:key="Tweet.tweet_id" /> </div> </div> </div> </div> </div> </template> <script> import Form from "./components/Form.vue"; import Tweet from "./components/Tweet.vue"; import SelectUser from "./components/SelectUser.vue"; export default { name: "App", components: { Form, Tweet, SelectUser, }, data() { return { AllTweet: Array.of( // 初回表示用のダミーデータ { tweet_id: 0, tweet_user: { user_id: "TestId", user_name: "ユーザー", }, tweet_body: "はじめてのツイート", } ), // 初回ロード時にForm.vueにpropsとして渡し、selectUser()で上書きするためのデータ tweet_user: { user_id: "TestId", user_name: "ユーザー", }, }; }, methods: { tweetAction(TweetObj) { this.AllTweet.push(TweetObj); }, selectUser(user) { console.log(user); this.tweet_user = user; }, }, }; </script>

Formコンポーネンでは、tweet_userオブジェクトをpropsで受け取り、data()内のTweetObj.tweet_userを上書きします。

Form.vue

<template> <div class="form form-group"> <textarea name="form" id="" class="form-control" cols="60" rows="5" placeholder="いまなにしてる?" v-model="TweetObj.tweet_body" ></textarea> <br /> <button class="text-white bg-success p-2 m-2 rounded" v-on:click="doTweet"> ツイートする </button> </div> </template> <script> export default { name: "Form", data() { return { TweetObj: { tweet_id: 0, tweet_user: { user_id: "TestId", user_name: "ユーザー", }, tweet_body: "", }, }; }, props:{ user:Object, }, methods: { doTweet() { // propsで受け取ったuser情報でTweetObj.tweet_userを上書き this.TweetObj.tweet_user = this.user; // 値渡しするために、新しいオブジェクトを定義する const tweet = Object.assign({}, this.TweetObj); this.$emit("tweet-event", tweet); }, }, }; </script>

twittervue5

続きます