Open ikegamir-sw opened 1 year ago
result.value = Math.floor( Math.random() * (items.length + min));
これに修正してもらってますが、これだと切り替わらない(消える)ことがある気がします。 https://github.com/sw-otay/app-development-training/commit/513dc1791981f1ddcf2fd903774bc49bbfca7f0f#diff-7a7a37b12ee1265d7e27577ec286120d2cbc0940908635e264a2be44ccb9a8a0R41
ということは、バグってますよね。 https://github.com/sw-otay/app-development-training/blob/513dc1791981f1ddcf2fd903774bc49bbfca7f0f/src/App.vue#L41 このコードで何が起こるか説明できますか?できれば直せると思います。
あと、この課題ではそんなに重要ではないんですが、コミットメッセージは「自分がコードに対して何をしたか」を書いたほうがいいです。他人が見るものだからです。 「指摘事項修正」は最悪のコミットメッセージのひとつです。他人には指摘事項がわからないからです。
result.value = Math.floor( Math.random() * (items.length + min));
のバグを修正しました。 0〜1の不動小数点を生成するMath.random()に最大値をかけて最大値の数分の数値の中からランダム値を生成する、minを足すのは0〜でなく最小値〜とするためだったのですが ()の位置がおかしくなってしまっていたためバグっていました。
結果表示のアプローチの改善案
内で、おみくじリストの中から条件に合う物を抽出するよう修正しました。
<script setup>
import { ref } from 'vue'
const items = ['大吉','中吉','小吉','吉','凶']
const resultNum = ref(0)
const resultVal = ref('')
function fortune() {
const min = 0 ;
resultNum.value = Math.floor( Math.random() * (items.length) + min);
resultVal.value = items[resultNum.value];
}
</script>
@sw-otay いい線いってますね:clap: もうちょっとよくできそうです。
一般論(Vueに限らず)として、書き換え可能なものはできるだけ少なくしたほうがいいです。
それを踏まえると……
今回のケースでは1の作戦で事足りるのですが、2の作戦だとスケールしやすいです。
算出プロパティ | Vue.js React だと useMemo が近いのですが、思想的にはちょっと違うので注意です。
0定義して足すの意味なくないですか? https://github.com/sw-otay/app-development-training/blob/dd20edb2a772f3b5452b7910ab391ace9a66ef8f/src/App.vue#L8-L9
description
というプロパティがあったので、「見出し + 段落」という構成に説得力があったのですが、なくなってしまったので、、、description
は、「金運: 5000兆円手に入るでしょう」みたいなのが書いてあることが期待される項目だと思います。以前の指摘は、そこに結果と同じ内容だけ書いてあるなら要らないよね、、という内容でした。コードブロックを書くときは、ちょんちょんちょんの横に言語の名前を書くとシンタックスハイライトが働きます。
<template>
<h1>す〜ぱ〜おみくじ</h1>
<button @click="fortune">おみくじをひく!</button>
<p>{{ resultVal }}</p>
</template>
リポジトリのコードを引用するときは、パーマリンクを使ったほうがいいです。
@ikegamir-sw ご確認ありがとうございます。 再度修正しました。
質問なのですが 算出プロパティ | Vue.js の書き方
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})
だと、ボタン押下1回目以降randomが変わらなくなってしまったのですが 今回は下記の書き方でも大丈夫でしょうか? https://github.com/sw-otay/app-development-training/blob/28e7810f3d848aa85a2b935dc8f865eef6f57b0c/src/App.vue#L7
@sw-otay
算出プロパティの書き方だと、ボタン押下1回目以降randomが変わらなくなってしまった
実際にどのように書いたのでしょうか? 動かなかったコードも併せて教えていただけると問題解決のお手伝いができるかもしれません。
今回は下記の書き方でも大丈夫でしょうか?
それは、太田さんが決めてください。太田さんがベスト(もしくはベター)だと思うコードを書くべきです。 わたしが行っているのは提案までで、指示ではありません。 ……という企画です。
@ikegamir-sw
このように書いたのですが、ボタン押下1回目以降randomが変わらなくなってしまいました。
function makeFortune() {
resultVal.value = items[randomize.value];
}
const randomize = computed(() => {
return Math.floor( Math.random() * (items.length))
})
算出プロパティは一度計算した値を持ち続けるとの事なので 今回は毎回値が変わってほしいのでこの書き方がベターかなと考えています。 https://github.com/sw-otay/app-development-training/blob/28e7810f3d848aa85a2b935dc8f865eef6f57b0c/src/App.vue#L7
@sw-otay 算出プロパティの使い方を間違っちゃってますね。。
算出プロパティのページには
リアクティブなデータを含む複雑なロジックには算出プロパティを使用すべき
と書いてあります。
「リアクティブなデータ」というのは、Vueから提供された、値の変更を追跡できるオブジェクトのことです。
リアクティブなデータの代表はref
ですね。ほかには computed
, reactive
, props
など。
ところで、
Math.floor( Math.random() * (items.length))
これには「リアクティブなデータ」が含まれていませんよね? 算出プロパティは
というものなので、提示された書き方では当然二度と変わらなくなってしまいます。
算出プロパティのイメージは以下です。
const 計算された値 = computed(リアクティブなデータを用いる、算出方法を表す関数)
「入力した値(リアクティブ)を5乗した値」がほしければ
const inputPowered5 = computed(() => Math.pow(input.value, 5))
「名簿の配列(リアクティブ)から東京都在住の人を抽出した配列」がほしければ
const liveInTokyo = computed(
() => listOfName.value.filter(
(item) => item.address.prefecture === "tokyo"
)
)
算出プロパティは一度計算した値を持ち続けるとの事なので 今回は毎回値が変わってほしいのでこの書き方がベターかなと考えています。
これは誤った知識に基づいた思考による結論かと思います。 算出プロパティについて(ある程度)正しい知識が得られたかと思いますので、改めて考えてみてください。 その上で、今と同じ結論になるかもしれません。それはOKです。
クリティカルシンキングでやったかもですが、思考の前提となる知識が間違ってると結論も間違います(偶然一致することはありますが)。
ドキュメントは理解できるまで読み込みましょう。わからない言葉はぐぐりましょう。 もしその上でわからない点があれば、周りの人に質問してみるのもいいかもしれません。
@ikegamir-sw レビューありがとうございます。
改めて算出プロパティの使い方を考えてみましたのでご確認お願いいたします。 https://github.com/sw-otay/app-development-training/blob/75c921eac0bfe8de40b1c1bf189a93ca9af0676a/src/App.vue#L12
@sw-otay
computed
単体の書き方はよさそうですね:clap:
computed
はリアクティブcomputed は ref と同じく「リアクティブ」です。 そもそもリアクティブがなんで必要か、考えたことはありますか?
ReactにしろVueにしろ、画面に出してる値が変わったら画面を更新してほしい という要求があります。 自分で「値を更新したときに画面を更新する命令」を書くんじゃなくって、値を更新したときに React や Vue がそれを検知して、勝手に画面を更新してくれるのです。前者はとても大変ですからね。 これが、Vue において 「宣言的レンダリング」とか「リアクティビティ」とか 言っているものです。
computed が (ref と同じく)「リアクティブ」ということは、 computed をそのまま画面 (Vueでは template の中) に書いてきちんと動くということです。
だから、こんなことせずに、 https://github.com/sw-otay/app-development-training/blob/75c921eac0bfe8de40b1c1bf189a93ca9af0676a/src/App.vue#L9
こう書けるわけです
<script setup>
import { ref, computed } from 'vue'
const items = ['大吉','中吉','小吉','吉','凶']
- const resultVal = ref('')
const resultNum = ref(0)
function makeFortune() {
resultNum.value = Math.floor( Math.random() * (items.length));
- resultVal.value = randomize.value;
}
const randomize = computed(() => {
return items[resultNum.value]
})
</script>
<template>
- <p>{{ resultVal }}</p>
+ <p>{{ randomize }}</p>
<button @click="makeFortune">おみくじ</button>
</template>
computed は、「計算された値」です。ですから、変数名は名詞にしましょう。
たとえば、 selectedFortune
とか。
今は randomize
という名前がついています。これは動詞ですね。
動詞を使った名前は関数(都度都度呼び出すもの)につけるものです。
ChatGPTに書かせたらほぼ完璧だったんですよね……これが数秒でできるんですよ!
以前のコメント の作戦1を使ってますが、今回はこれで十分です。
たぶん、今後「指示通りにコードを書く人」はAIに置換されていきます。 ただ、出力されたコードが正しいかどうか、設計や仕様が適切かどうかは、我々人間が見て、考えて、判断しないといけません。 そのために、しっかり考えて、しっかり勉強していかないといけないなぁと思った次第でした。
@ikegamir-sw レビューありがとうございます。 コメントを読んで不要な行を削除し、変数の名前を修正しました。
「リアクティブ」について理解が深まりました!
お疲れさまでした!ちゃんと動きそうですね:clap: ただし、正直言って実装はかなり微妙です。。ちょっとずつおべんつよしていきましょう。
指摘
コード上すぐ直せること
いかなる理由があろうともvarを使うのはやめましょう。基本的にconst、どうしても再代入が必要なケースではletを使ってください。 https://github.com/sw-otay/app-development-training/blob/4eaaea8077b9d54731640067f8deccf28bf8ac11/src/App.vue#L40-L41
この箇所にrefを使うのは不適切です。普通の配列でOKです。 https://github.com/sw-otay/app-development-training/blob/4eaaea8077b9d54731640067f8deccf28bf8ac11/src/App.vue#L3-L34
おみくじの結果のIDを入れる変数だと思いますが、
count
ではなくないですか? https://github.com/sw-otay/app-development-training/blob/4eaaea8077b9d54731640067f8deccf28bf8ac11/src/App.vue#L36ここのロジックがむずかしい書かれ方してますね https://github.com/sw-otay/app-development-training/blob/4eaaea8077b9d54731640067f8deccf28bf8ac11/src/App.vue#L42
max + 1 - min
って1足して1引いてるから意味ないのでは?items.length
)と同じですよね?将来おみくじの結果増やしたらこれもいちいち書き換えることになりますけど、面倒じゃないですか?設計の話
結果表示のアプローチについて
これで動くは動くんですが、かなり悪手です。 ということで、別の手段も考えてみましょう。複数浮かべば浮かぶだけ。issueにどういう方針で実現するか、日本語でコメントしてください。 https://github.com/sw-otay/app-development-training/blob/4eaaea8077b9d54731640067f8deccf28bf8ac11/src/App.vue#L48-L53
太田さんがとったアプローチ
微妙な点
ロジックが画面表示側に漏れている
「おみくじの結果(のオブジェクト)」はロジックが導き出すべきもの(=
<script/>
の中で作り出されるべきもの)です。これを今template側にロジックを書いてやらせています。 これでも動きますけど、ひとつの目的のことは複数箇所でやるより単一箇所でやったほうがよさそうですよね?
再利用性が低い
「おみくじの結果の表示は子コンポーネントに任せたいので、結果を子コンポーネントに渡してください」というケースを考えると、
を子コンポーネントに渡したいけど、今の書き方だと大幅改修が必要です。
不要な全件ループが行われている
今は5つしかないから全然大丈夫なんですが、もし結果が100万件とかある場合、毎回100万回ループすることになります。 シュッと書くと自然とスケーラブル(数字がでかくなってもちゃんと動く)になります。
プログラムに直接関係ない細かいこと
おみくじの結果って見出しなんですかね……?
(道具としての話)↓みたいに出されるの、わたしがユーザーだったら「見りゃわかるわ!」って思います。