Vue.jsの勉強をしたのでそのまとめ
CODEPREPでVue.jsの勉強をしたのでそのまとめ。
Vue.jsとはなんぞや
UI を構築するためのライブラリ。
<script src="https://unpkg.com/vue"></script>
で読み込むことができる。JavaScript内のデータとHTMLを自動的に結びつけ、複雑なUIの実装も簡単にできるのが特徴。
プログレッシブフレームワークとも呼ばれる。小さな Web ページから大きなアプリケーションまで、柔軟に適用できるように設計されている。
双方向データバインディング:html内のinput要素に
v-model
という属性をつけることで、インスタンス上のデータとinput要素の入力値を同期できる。v-model
のように先頭にv-
が付いている属性はディレクティブと呼ばれ、通常のHTML属性とは異なった動作をする。
書き方は、(js側)
var vm = new Vue({ // Vueインスタンスをnewする el: '#app', // インスタンスを結びつけるhtmlの要素を指定する data: { message: 'Hello World!' } });
なんかこんな感じ。(html側)
<div id="app"> <p>{{ message }}</p> <!-- Mustache記法でデータを表示する --> <input type="text" v-model="message"> </div>
インスタンスを操作するオプション
methods
インスタンスメソッドを定義することができる。
computed
算出プロパティを定義することができる(算出プロパティとは、あるデータや別の算出プロパティから計算される新たなデータのこと)。 「プロパティ」と言っているけどメソッドに近いものというイメージを持った方が理解しやすそう…?
「特定の値を算出したい」という目的であれば、メソッドでなく算出プロパティで定義した方がいいのかしら、と思って公式ドキュメント見たら、算出プロパティは結果をキャッシュする性質があるらしい。ここら辺注意が必要そう。
watch
指定することで、データや算出プロパティの変更を監視することができる(ウォッチャー)。
オプションのキーに変更を監視したいプロパティ名を設定すると、そのデータが更新された時に値に渡した関数が実行される。
テンプレートで使用する属性(ディレクティブ)
- テンプレート = Vue.js のインスタンス上のデータを表示するためのHTMLファイル。
v-for
配列やオブジェクトなど、要素を繰り返し扱う。書き方は、
- 配列
<li v-for="(value, index) in array"> <span>({{ index }}){{ todo.text }}</span> </li>
- オブジェクト
<li v-for="(value, key, index) in object"> <span>({{ index }}){{ key }}:{{ value }}</span> </li>
こんな感じ。
index(オブジェクトに対しての書き方だったらkeyも)は省略可能で、その場合は括弧も書かなくてよい。
また、inはofに書き換え可能とのこと(英語的に書くことができるってことかな…)。
v-bind
v-bind:属性名=データ
で、データを属性に紐付けることができる。
省略して書くことも可能で、省略する場合は:属性名
のように属性名の頭にコロンをつければOK。
以下は、データ内の論理値(todos.completed)をチェックボックスに紐付けている例。
- js
var vm = new Vue({ el: "#app", data: { todos: [ { completed: true, text: 'register' }, { completed: false, text: 'login' } ] } });
- html
<div id="app"> <ul> <li v-for="todo in todos"> <input type="checkbox" :checked="todo.completed"> <!--省略せずに書くなら下記--> <!--<input type="checkbox" v-bind:checked="todo.completed">--> <span>{{ todo.text }}</span> </li> </ul> </div>
class、styleに対するv-bind
classやstyleの付与を、v-bindを通して行うことができる。
<!-- fooがtrueであれば、classにsome-classを付与する --> <div :class="{ 'some-class': foo }"></div> <!-- styleのcolorにfooを付与する --> <div :style="{ color: foo }"></div>
v-on
v-on:イベント名=メソッド/処理
で、あるイベントが発生した際に実行したい処理を指定できる。メソッドを指定することもできるし、処理内容をそのまま記述することもできる。
こちらも省略記法があり、@イベント名
のようにイベント名の前に@
をつければOK。
以下は、チェックボックスの状態が更新されたらそれをデータに反映させたい場合の例。
var vm = new Vue({ el: "#app", data: { todos: [ { completed: true, text: 'register' }, { completed: false, text: 'login' } ] } });
- html
v-on
内では$event
という特別な変数を通してイベントオブジェクトを操作することができる。
<div id="app"> <ul> <li v-for="todo in todos"> <input type="checkbox" v-bind:checked="todo.completed" v-on:change="todo.completed = $event.target.checked"> <!--上記はv-modelでの書き換えも可能--> <!--<input type="checkbox" v-model="todo.completed">--> <span>{{ todo.text }}</span> </li> </ul> </div>
v-onのイベント修飾子
イベント修飾子を使うことでpreventDefault()
等を実行することができる。
書き方はv-on:click.prevent
というように、イベント名の後にドットで修飾子をつなげればOK。
イベント修飾子の種類は下記。
v-showとv-if
v-show
で指定した値がfalseである場合、要素を非表示にすることができる。
v-if
でも、指定した値がfalseである場合、要素を非表示にすることができる。
この二つの違いとしては、v-show
でfalseであればdisplay: none;
でスタイル上で非表示とするが、v-if
はそもそも表示しないものとして扱うところ。
使い分けとしてはたとえば、falseであればそもそも読み込まなくていいよ〜(画像とか)という時なんかには、v-if
を使うといいらしい。なるほど〜。
<div id="app"> <ul> <li v-for="todo in todos"> <input type="checkbox" v-model="todo.completed"> <span>{{ todo.text }}</span> <!--todo.completedがfalseであれば--> <strong class="red" v-show="todo.completed"> done! </strong> </li> </ul> </div>
HTMLページ上に謎の記号もしくは豆腐が表示される
現象
(実ソース上では特に何か文字が混じってしまっている様子はないが)
HTMLページ上に謎の記号、もしくは豆腐(□)が現れている。
※ Macでは確認できず、WindowsのChromeで確認をお願いしたら表示されていた。ので、ブラウザにもよる?
原因と対応
この正体は「制御文字(制御コード)」というものらしいです(ちなみにこの現象に遭遇するの2回目)。
私はエディターはAtomを使っているんだけどAtom上では表示されない。からぱっと見わからない。
他のエディターで表示されるのないかなーと思い調べたらSublime Textだと表示されるらしく、インストールして問題のファイルを開いてみたらたしかにその制御文字が表示されていた。
(※この「VT」の箇所が、HTML上では豆腐になっていた)
ちなみに「VT」は垂直タブを意味する制御コードでした(VerticalのVか)。
なので、この該当のコードをサクッと削除すれば解決。
参考にさせていただきました
【読書メモ】パーフェクトPHP(3章 型と演算子)
文字列(p.60)
ヒアドキュメント
… 複数行にまたがる長い文字列を定義する一つの方法。Nowdoc
… 変数展開がされないヒアドキュメントのようなもの。
null(p.66)
「nullを代入した変数」と「unset()で割り当てを解除された変数」
本質的に2つの値は等価だが、挙動が異なってくる。
<?php $var = null; var_dump($var); // null。 unset($var); var_dump($var); // 値としてはnull。だがunsetによりE_NOTICE(Undefined variable)が発生する。
型変換(p.67)
文字列を数値型へ明示的にキャストする
文字列先頭の数字から、数字の終わりまでを値として返す。先頭が文字であれば0となる。
<?php echo (int)"15foo"; // 15 echo (int)"15.5foo"; // 15 echo (float)"15.5foo"; // 15.5 echo (int)"foo"; // 0 echo (int)"foo15"; // 0
文字列のキャスト
下記のコードを実行すると「"0.0"と"0"は等しい」と表示される。
<?php if ('0.0' == '0') { echo '"0.0"と"0"は等しい'; }
これは、二項演算を行う際に2つの項とも「数値らしき文字列」の場合、「整数型または浮動小数点数型へとキャストする」性質がPHPにあるため。
① '0.0' が浮動小数点数型の 0.0 にキャストされる。
② '0' が整数型の 0 にキャストされる。
③ 0.0 と 0 の比較により、0 が 浮動小数点数型の 0.0 にキャストされる。
④ 比較の結果trueになる。
というからくり。
こうした、自動キャストによる値の変換で思いもよらない結果が起こりえるため、基本的には===
or!==
で厳密に比較するべき。
PHPの演算子(p.70)
四則演算において0で割り算をした場合、
Warning: Division by zero
が発生する。この時の返り値は論理値のfalseになる。文字列演算子(ドット)で、整数を文字列として結合する場合はスペースを空ける必要がある(数値が浮動小数点数型とみなされエラーとなるため)。
<?php $tom = 'Tom is ' . 15 . ' years old.'; // Tom is 15 years old. $bob = 'Bob is ' .16. ' years old'; // PHP Parse error: syntax error, unexpected '.16' (T_DNUMBER)
型演算子
instanceof
。変数が、「特定のクラス」or「特定のインターフェースを実装したクラス」のインスタンスであるかどうかを判定し、論理値を返す。
<?php interface FooInterface {} class ParentFoo {} class Foo extends ParentFoo implements FooInterface {} class Bar {} $a = new Foo(); var_dump($a instanceof Foo); // bool(true) var_dump($a instanceof ParentFoo); // bool(true) var_dump($a instanceof FooInterface); // bool(true) var_dump($a instanceof Bar); // bool(false)
三項演算子(p.77)
三項演算子の結合規則
PHPの三項演算子は 左 辺 か ら 評 価 さ れ る。
前にハマったので覚えてる〜!!気をつけましょう。
その他の演算子(p.81)
エラー制御演算子
@
。その式で発生するエラーを制御し、エラーを表示させない。
<?php $var = @$_GET['foo'];
ここでfooパラメーターが取得できない等でエラーが発生しても、制御演算子を付けているためエラーが表示されない。
(この演算子なんであるんだろう…使う場面がイメージできない)
「SQLSTATE[HY000] [1045] Access denied for user 'test'@'localhost' (using password: YES)」のエラーが出る
現象
Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user 'test'@'localhost' (using password: YES)
というエラーが発生する。
原因と対応
testユーザーを作っていませんでしたはい。(というかMAMPのMySQL使ってるのつい忘れてユーザー作ったのにエラー解消されないな??みたいな同じこと前にもあった)
のでまずはユーザーを作る。
CREATE USER 'ユーザー名'@'ホスト名' IDENTIFIED BY 'パスワード'; CREATE USER 'test'@'localhost' IDENTIFIED BY 'password';
そして作ったユーザーに対して必要な権限を付与する。
GRANT 権限 ON DB名.テーブル名 TO 'ユーザー名'@'ホスト名'; GRANT ALL PRIVILEGES ON test.* TO 'test'@'localhost';
ここまでの対応でエラーが解消された。
補足
- ユーザー名やホスト、権限設定はmysql.userテーブルで確認することができる。
SELECT * FROM mysql.user WHERE user = 'test'¥G *************************** 1. row *************************** Host: localhost Db: test User: test Select_priv: Y Insert_priv: Y Update_priv: Y Delete_priv: Y Create_priv: Y Drop_priv: Y Grant_priv: N References_priv: Y Index_priv: Y Alter_priv: Y (以下略)
- 調べる中で「GRANTで権限付与したあと、FLUSH PRIVILEGES;
で設定の反映が必要」的な情報も見かけたけど、これは不要な様子。
INSERT を使用してアカウントを作成する場合は、FLUSH PRIVILEGES を使用して、付与テーブルを再ロードするようにサーバーに指示する必要があります。そうしなければ、サーバーを再起動するまで変更が認識されません。CREATE USER では、FLUSH PRIVILEGES が必要ありません。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 6.3.2 ユーザーアカウントの追加