Vue.jsを1から勉強する話(読書録独り言)
Python: チョットワカル, フロントエンド: 未知
筆者について
初めまして!株式会社PantaRhei代表取締役CEOのかずです!
弊社ではAIを用いた営業のアウトバウンドリスト最適化を行なっています。
私個人はデータサイエンティスト/AIエンジニアで、データ分析やAI作成、データ基盤構築などを生業としています。
最近はChatGPTなどの大規模言語モデル(LLM)の登場でAI環境が荒れまくりです。余波というか本波が直撃してます。AI周りは一部LLMにお任せしていきたいところです。
自分はAIやデータ周り以外もできちゃうエンジニアになっちゃおう。
こうして、フロントエンドも勉強していく運びになりました。
フロントエンド最初の一歩は、Vue.jsに決めました。
弊社で開発しているプロダクトにVue.js(以下Vue)が採用されていることもありこれを初手にしました。Vue頑張るぞ!
学ぶ本&筆者スキル感
今回Vueの学習に用いる書籍は
たった1日で基本が身に付く! Vue.js 超入門
です!!!!
1日で身についちゃうの!まじかよ!
有楽町の三省堂にある数多のVue関連書籍の中で、一際輝くキャッチーな言葉に魅了され気が付いたら購入していました。Vue頑張るぞ!
筆者スキル感
- pythonは割とできる
jupyterもpyもクラスの継承も環境管理もバッチリだ!
- Java scriptはhello worldも書けない
すなわちfor文とか基本は皆無
- 仕事は大体PythonかSQLを使う、GCPなどインフラ周りも
GCP(VM/CloudSQL/BigQueryとかデータ周りばっか)
- Webに関する知識はほとんどない
認証?モーダル?stylesheet?DOM…?…?
- htmlはスクレイピングの時に勉強
要素のパースはSelectorではなくXPath派
結論
めちゃくちゃ良かった。初学者に1日はきつい。
学びフローとしては
環境構築→Vueの要素(dataとかmethodsとか)→v-if/v-forなど→バインディング全般→todoアプリ作成→画像ビューアーアプリ作成
という感じ。アプリを作る上で本当に基礎的な内容を網羅的にかつ分かりやすい導線で書いてくれていて、大変勉強しやすかった。すごい。
ただ、1日はキツくないか?笑
想定時間である8時間以上はかかったと思う。
JS初学者かつ他言語習得者で3日くらいなボリューム。私はダラダラやったので4日かかった。
単純に私の理解力が薄い可能性大なので一般的な聡明さがあれば1日でも終わるかもしれない。
血肉になる感じはめちゃくちゃする。Pythonを忘れた。
読書録
(ここからは、私が読みながら実装していると同時に書き散らした独り言を、note向けに推敲したものです!)(多分本を読みながらじゃないと意味不明なのでここはappendixです。)
第1章
プログレッシブフレームワークってなんだ?
→規模によって段階的に導入できる柔軟で漸進的なフレームワーク
コンポーネント指向開発ってなんだ?
→フロントエンドの各要素をまとめて再利用できる感じ(オブジェクト指向っぽい)
cdnを使って開発
便利すぎないか?!これ?!
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
をhtmlの一部にそっと入れるだけで、急にVueが動き始めるの凄すぎる。大体こういう技術系入門書籍の環境構築って最初詰まりがちなんだけど(個人の感想)、これをするだけでVueが動くのは偉大すぎる。すごい。
第2章
以下のコード、表示されますって書いてあるけどどこに表示されるの?
(console.log(car.bodyType))
どこに? ターミナルで実行するのか、ipynbみたいなインタラクティブな仕組みがあるのかわからん。
→後でわかった。devtoolのconsoleで確認すれば良いのか。
javascriptには変数を宣言するときにvarとletとconstがあるのか!そしてvarは関数内定義してもグローバルになるという使いにくい仕様になっているのね。
Vueに用いられるプロパティは(python使いとしてははキーって言いたい)、el、computed、data、method、components、などがある、らしい。
data() {}はdata: function() {}の省略形
{{ text }}のように{{}}に囲むやり方はマスタッシュ構文という、これをHTMLに書くと、Vueのdata関数が返すオブジェクトのプロパティと紐づく。
data関数にはdataオブジェクトの書き方もある。
const app = new Vue({
el: '#app',
data() {
return {
text: 'hello Vue.js'
};
}
};
の関数は
const app = new Vue({
el: '#app'
data: {
const: 0,
text: 'hello'
}
}};
と書くこともできる。これはdataを関数ではなく、オブジェクトとして捉えているんだ。そうだ。なるほど。ただし、多数のコンポーネントになるとオブジェクト指定では不具合が生じるらしい。なんか分かる。
テンプレートがdata()に紐付いていて、dataの変更がテンプレートに即座に反映されるようなものをバインディングと呼ぶ。バインディングはデータバインディングの略。
差分レンダリングとは、HTMLの一部分の要素が変更されたとき、HTML全てでなく、データ変更該当部分だけをレンダリングする技術。パフォーマンス上がる。
DOMはDocument Object Modelのことで、HTMLの要素をオブジェクトの集まりとして表現する仕組み。仮想DOMとはリアルDOMと対応したオブジェクトの集まりのことで、更新に必要な部分を検出するために使われる。仮想DOMで差分検出、それをリアルDOMに反映。差分レンダリング。
chromeを用いたコード検証にはvueという拡張機能があり、それが便利。
→実際methodsやdataを追いかけられて便利でした!!(読後談)
const $text = の「$」ってなんだ
→「$emit」でも出てきたので読後に学習
→これを参考にしたけど間違ってないか不安
第3章
()があれば関数、なければメソッド?
v-on:click="changehoge"
は
onclick="changehoge"
のVueバージョン。またv-onは@に置き換えることも可能。
@:(onを除いたJavaScriptのイベントハンドラ名)="huga"
イベントハンドラはメソッドを実行する。メソッドとはオブジェクトに結び付けられた関数のこと。
メソッドの定義は
プロパティ: function(){
処理}とする。
function(){}はおそらくpythonで言う無名関数lambdaのことだと思う。
→違った。本当の無名関数lambdaはarrow関数(読後談)
javascriptのthisはpythonで言うselfだと認識(あってる?)
methodsプロパティの中に書くメソッドを用意する。
methods: {
changeHoge: function() {
処理
}
}
これを省略して
methods: {
changeHoge(){
処理
}
}
としても良い。
本記事とは関係ないが、VSCodeでVueと入力すると、VTTCueという謎のクラスが予測変換で出てきて毎回工夫しないとこの予測入力を回避できずストレスが溜まった。
devtoolのVueのRootという部分を見てVueの概観が理解できそう。
→RootはRootコンポーネントということだった。
Vueのデータの流れにはViewとActionとStateがあるらしい。
View…ブラウザに表示される部分
Action…Vueインスタンスのmethodsに当たる部分
State…Vueインスタンスのdata関数に当たる部分
この考えはReactやAngularにも用いられている。
第4章
条件付きレンダリングの章。
html内にv-ifやv-elseを用いるとできるらしい。
<p v-if="count >= 60">合格!</p>
<p v-else>不合格</p>
上記コードはv-ifをhtmlに記載したが、可読性を保つには分岐はjavascript側に書くべきです。だそう。
算出プロパティで条件分岐を考えるのが最適。だそう。
v-if='isPass'として、算出プロパティ(computed)の値を記載すると条件ができる。
v-idとは全く同じでv-showが存在する。要素の表示・非表示をjavascriptではなく、cssのdisplay:noneで行う。
v-elseやv-else-ifのような分岐は行えない。
v-showはcssで表示非表示を切り替えるのでレンダリング負荷が小さくなる。
Vueで複数の条件分岐はv-else-ifを使う。
双方向バインディング(v-model)があると、ユーザーの入力でdata()側が変更され、さらにそれがテンプレート側に変更される。
バリデーションとは、入力された内容が、要件と一致するかを検査すること
メールアドレス入力なのに@がないのはダメ的なやつ。
v-modelを用いなくても双方向バインディングが可能。
イベントハンドラとメソッドを用いる。
→個人的にはイベントハンドラにメソッドを紐づけてdataの内容を書き換える方が分かりやすい。
第5章
リストレンダリングの章。v-forで繰り返しを学ぶ。
v-for="(変数1, 変数2) in 配列の変数"でタグが繰り返し錬成できるらしい。
pythonのfor 変数1, 変数2 in enumerate(配列の変数)って感じかな。
:keyはv-bind:keyの短縮系らしい
v-on:clickの短縮系が@clickでv-bind:の短縮系が:なのは理解し難い。
慣れるしかない。→慣れた。(読後談)
v-bindはkey以外にもclassやhref、valueなど他のHTML属性にもデータを反映させることができるらしい。
とりあえず推奨されているのでやった方が良いらしい。確かにタグは一意に特定したい。
オブジェクトを繰り返し処理に指定した場合、プロパティが指定される。また、変数を2つ指定している場合は変数1にvalue、変数2にkeyが入る。(zip(dict(と逆)))、この場合idxは変数3に入る。
初めて日本語を表示したけど、すごいエラーが出た。
<head><meta charset="utf-8" /><head/>が必要だね。
第6章
v-bindを用いればスタイルもバインディングできる。
スタイルバインディングには文字列指定でのものとオブジェクト指定のものが2通りある。個人的には文字列指定のものがHTMLを荒らさなくて好み。
``(バッククォート)で囲まれた文字列はテンプレート文字列と言って、${}を用いて変数を埋め込める。pythonのf'{}'.format()的な感じか。
クラスバインディングはclassにデータをバインディングする機能のこと。
〇〇バインディングってHTMLのHTMLの〇〇属性にv-なんちゃらもしくは「:」で紐づけることなんだなぁと思ったり。
スタイルバインディングはスタイル情報をJSコードかテンプレート内に書かなければいけないのでCSSファイルに書いておくと合理的。それをセレクタでクラスに紐づけるのが有能。
<div v-bind:class="{ 'is-active': isActive}"><div/>
という風に、classのプロパティにクラス名、右にそのクラスが有効になる条件式を書くと、js側から処理できて可読性を損なわない。
:keyは何となくv-forの後の文字列に直接接続しなければいけないと思っていたが、その必要はないらしい。
第7章
ついにTodoアプリを作る!!!
=>という表現はarrow関数と呼ぶらしい。最初、filtter関数の文脈で出てきたので、allowかと思った(許可する的な)。Rの代入みたい。
if (!this.text) return;
というコードが。空文字列はFalse扱いで!はnotなのね。pythonと同じ。
Math.ceil(Math.random() * 1000);
でid振っているけど一意性が担保されてなくて気になった。
ID採番はめんどいはめんどいのでこれにしちゃうのも分かる。
(急に外部パッケージでuuidとか出てきたらめんどくさいし、流れ的にidをincrementでやるのは本質以外の実装が必要になるしなぁ。などと。)
以下、これってありなの!?と思ったやつ。
const todo = {
id, # 分かる
text, # 分かる
isDone: false # !?!?!?!?!?
}
なんだろう、急にdict出てくるのやめてもらっていいですか。pythonだとsetの実装!思いきや急にkey: value出てくるじゃん。dict。
→さすが本書。あとでこの謎を回収してくれています。(読後談)
doneTodo() {
return this.todos.filter( todo => todo.isDone === true);
},
はarrow関数を用いずに記述すると、
doneTodo() {
return this.todos.filter(function (todo) {
return todo.isDone === true;
});
}.
となる。function in function。なるほど。
理解すると下のコードは
todo.isDoneがTrueを返却する関数を実装し、その返却値によってfilterをしている。(同値を示すのは===なのか。イコール多いな。)
pythonのlambda関数と完全に一致。python使いの血がさわぐのでpython版を書くと、
def doneTodo(self):
return list(filter(lambda todo: todo.isDone == true, self.todos))
ですね。すごい理解した。
arrow関数では引数がない場合は()=>と書く必要がある。
リストオブジェクトにはいろんなメソッドがある。
リストオブジェクト.filter(条件式) => 条件に見合う要素を抽出
リストオブジェクト.splice(index, 1) => indexの要素を削除する
リストオブジェクト.push(⚪︎) => ⚪︎をリストに格納する(append)
リストオブジェクト[index] => リストのindex番目を取得
リストオブジェクトindexOf(text) => textがリストの中で何番目かを取得する
cssの設定でpxではなくvhというのがあった。horizontalとverticalかな。
cssセレクタで.wrapというものがあった。そんなタグあったかな。
cssのコメントアウトは/* */だそう。
イギリス英語で育ったので、centerはcentreの方が好き(プレミアリーグが好きなだけ)。
#fefefeというカラーコードが出てくるたび「ふぇふぇふぇ」と読んでしまう。
作者8の倍数もしくは4の倍数好きだな。分かる。(pxが全てそれで統一。)
→自由度高すぎると大変なので、あえて制限しているんだと思われ。
todoアプリできた!
スタイル指定を間違えた。正しくは以下。
「ADD TODO」に付与するはずだったスタイルを間違えてテキストボックスに付与してしまった結果に起きた出来事。
第8章
画像ビューワーを作るぞ!
コンポーネントの親子でのやり取りは propsとemitである。
propsはvue以外のフレームワークやライブラリでも使われる。(確かにAdobeAnalyticsでは一時変数をpropって言ってたな。)
emitはvue独自。子から親コンポーネントへのデータ継承。
子コンポーネントにはtemplateプロパティがある。ここにHTMLを書く。だんだんイメージ湧いてきた。ルートに使うコンポーネントをコンポーネントプロパティに書いておくと良いんだね。
propsにはrequiredオプション(必須orNot)、validator(検証関数自作)オプションがある。なるほど。
通常はコンポーネント毎にファイルを分けるらしい。確かにそっちの方が再利用性や保守性高そう。
サムネイルってThumbnailって書くの!?!?Sumnailとかかと…
data() 関数は子コンポーネントには用いないのかな?
imagesプロパティでパスをリストオブジェクトにするとき、パスを9個も使うのめんどくさかったのでできればimgにアクセスして全てのファイルを取得する的な実装が欲しかった。
emit側でクリックはclickimageだよとカスタムイベントハンドラ化している。
{}の中身、ほとんどkey: value形式なのにmodalだけそれしかなくて気持ち悪かった。プロパティと値が同じなら省略できるのね納得。
.vueファイルのstyle scoped便利!
SFCで完結できるのは素晴らしい。兎にも角にもできた!
画像をクリックするとモーダルが浮き出て画像が表示されるシンプルな仕組みだけど、JSの裏でこんな処理があったのかと感動。
最後に
TODOアプリや画像ビューアーを自分で実装してみて思ったのが、
「フロントエンドエンジニアの方すげぇぇぇぇ!!!!!!!!」。
正直(無論リスペクトは持っていましたが)Web系、特にフロントエンドは私のような日陰者視点では太陽のように陽キャ集団で「ウェイじゃん」と斜に構えていたのですが、難しすぎる(特にdata、methods、computed、スタイルシート周り、結論全部難しい)処理をささっと実装できてしまうなんて、、、こんなにできるってすごいなとなりました。
やっぱり食わず嫌いせずに勉強していかないとダメだな。視野狭くなるし。改めて、Vue頑張るぞ!