🥦

N予備校1章終えた人向けVue入門1

2022/12/11に公開

この記事はN予備校のプログラミング入門Webアプリコースの1章を終えた人に向けたVue入門記事です。
https://www.nnn.ed.nico/pages/programming/

別にN予備校の中の人ではないです。

では始めます。

Vueとはなにか?

Vueとは、ブラウザ上でhtmlcssjsを使って、スマホのアプリのようなリッチなUI体験を提供できるようにするために生まれたものです。Vueが生まれるまでは、主にjQueryと呼ばれるライブラリが使われていました。しかし、jQueryを使っても、中規模以上のアプリを作るには、jsとcssでは辛いものがありました。そこで、webコンポーネントという思想が生まれました。webコンポーネントとは、画面上の構成要素の一つ一つを部品(コンポーネント)として扱えるようにするという考え方です。webコンポーネントのメリットは、プログラマーが1度コンポーネントを作ってしまえば(例えばボタンコンポーネントなど)、あとはそのコンポーネントを再利用してアプリ内で使い回せることや、コンポーネント単位でcssを定義できる(グローバルcssを使わずに済む)ことです。N予備校1章の場合とwebコンポーネントを比較してみましょう。

N予備校1章の場合

  • 最初にhtmlタグを定義してidやclassをつける
  • jsでgetElementByIdで読み込み、innerHTMLなどで文章を変更したり、clickイベントを定義したりする。
  • 同じような機能を複数作りたいときは、その分 htmlとjsをコピペして記述

webコンポーネントの場合

  • 最初にコンポーネントの中にhtmlタグを定義してidやclassをつける
  • コンポーネントに対して、clickイベントを定義したりする
  • コンポーネントは使い回せるため、同じコードを2回書かなくてもよい

もちろんN予備校1章の方法でも、使い回せるように書くことはできますが、その分のスキルは必要になります。webコンポーネントの場合は一度コンポーネントを書けば、あとは積み木のように積み上げていくだけです。

現在のブラウザ上のwebアプリ開発(フロントエンド開発)においては、jQueryではなくwebコンポーネントの思想をくんだAngularReactVueが利用されることが多いです。

jsの辛さ

大規模なwebアプリをjsで作成するには、ある程度の技術(とルール)が必要になってきます。例えば、変数のスコープ管理、状態の管理をどうするか、どのファイルに何を記述するかなどです。また、そのためには即時関数などのテクニックが要求されたりします。うまく管理できなければ、複雑なコードができてしまい、誰もメンテナンスしたがらない、機能追加すればバグを生むwebアプリが出来上がります。そのため、そこらへんを軽減してくれる考え方やフレームワークが必要になってくるのです。

cssの辛さ

大規模なwebアプリをcssでスタリングするには、ある程度の技術(とルール)が必要になってきます。というのは、cssはグローバルに定義されてしまうからです。例えば、10種類くらいあるページで、.my-cardというcssをどこかで定義したとします。そのcssをいろんな場所で使っていたとします。もしある特定のページで.my-cardのスタイルを変えたいと思って修正した場合、他の9ページの.my-cardが適用されているスタイルに予期せぬ表示のズレが生じる可能性があります。さらに、cssはcssセレクタをつかって、子や孫要素にもスタイルを指定できるため、さらなる意図せぬ影響がでてくるかもしれません。これを防ぐためには、cssの命名規則にBEMを使うなどのテクニックを利用するか、もしくは何かしらのフレームワークを用いて、グローバルなcssを使わなくするしかありません。

jQueryとはなにか

N予備校1章で皆さんは、getEelementByIdinnerHTMLを使ってテキストを書き換えたりonclickに対して関数を代入して、クリックイベントリスナーを定義したりしました。では、文章をクリックごとに表示したり、非表示にしたりする挙動はどうすれば実現できるでしょうか(この文章を見ているということは「jQuery」とはなにかをクリックしましたね)?この挙動を簡単に実現してくれるライブラリが、まさにjQueryです。

なぜjQueryは流行ったのか

皆さんはあまり意識しないかもしれませんが、実はブラウザというものは各ブラウザごとに機能に違いがあります。ブラウザ上でwebアプリを提供する側は、この機能の差に気を使って作成しなければいけませんでした。Aブラウザはこの機能が使えるが、Bブラウザは使えないので、違うやり方で実現するなどです。これはかなりアプリ制作者にとってストレスでした。jQueryはこれらブラウザ間の差分をうまく吸収してくれました。アプリ制作者はブラウザごとの差を意識しなくてよくなったのです。これもjQueryが流行った一因でした。ただし、ブラウザ間の差も少なくなってきています。また、PostCSSと呼ばれる技術も出てきており、jQueryのブラウザ間の差分吸収といったメリットは薄くなってきています。

jQueryはオワコン(終わったコンテンツ)なのか

jQueryはあまり使われなくなったから、jQueryはオワコン(終わったコンテンツ)みたいな話がありますが、そうではないです。単純に役割が変わったのです。LPサイトなどのページ数がすくなくデザインが主体のサイトの場合はjQueryは現役です。またwebコンポーネント思想のライブラリは学習コストが高いため、デザイナーにとってはjQueryのほうが好ましかったりします。

Vueに入門しよう

前置きが長くなりましたが、ここからは実際のVueに入っていきます。

こちらがVueの公式サイトです。ありがたいことに、日本語に翻訳されています。学習においてはVueの公式サイトは、ある程度フロントエンドがわかる人向けに書かれているので、説明文が初学者にとっては難しくなっています。

こちらが公式チュートリアルです。オンライン上でチュートリアルを進められるようになっています。こちらも、説明文章が難しいと思います。

そこで、この記事でチュートリアルの各ページの追加解説を行います。公式チュートリアルの横に並べて、一緒に読んでください。

Step1 はじめに

リンク
Vueは1ファイル1コンポーネントの構成担っています。ファイルの拡張子は.vueです。ここでのコンポーネントとは、とりあえずhtmlとjsとcssを画面上の部品単位(例えばヘッダーやボタンなど)で管理できるものと考えてください。Vueファイルの中身を見てみましょう。Vueファイルはhtmlのようなタグの構造になっています。

App.vue
<template>
  <h1>Hello World!</h1>
</template>

<style>
</style>

<script>
</script>

代表的なタグを3つ覚えてください。templatestylescriptです。これらはこの順番に記述する必要はないです。どの順番でも構いません。templateタグが最後でもいいのです。 また、チュートリアルにはstylescriptタグが無いことに気づくかもしれません。基本的にtemplateタグは必須ですが、他2つのタグは必要でなければ記述する必要はありません。

それぞれのタグの役割を説明してませんでした。templateタグにはhtmlを記述します。styleタグにはcssを記述します。scriptタグにはjsを記述します。1ファイルにすべての要素(表示、スタイル、動き)がまとまっていて、見やすいですね。

templateタグは、N予備校1章で扱ったhtmlそのものです。今回のチュートリアルの場合は、h1タグとテキスト(Hello World!)が入っているため、Hello Wolrd! というh1タイトルがプレビュー画面に表示されていることがわかります。

公式チュートリアルstep1

まずはここまで理解できればOKです。

課題: Hello Wolrd!の代わりに「こんにちは世界!」という文章を表示させましょう!↓答え
<template>
  <h1>こんにちは世界!</h1>
</template>

Step2 宣言的レンダリング

リンク

突然難しい言葉がでてきました。宣言的レンダリング!ナンノコッチャ!
とりあえずこのチュートリアルでは「宣言的レンダリング」は無視してください。理解しなくてもいけます。

チュートリアルの言葉を解説します。

エディターに表示されているのは、Vue の単一ファイルコンポーネント(SFC)です。SFC は再利用可能な自己完結型のコードブロックであり、一緒に属する HTML、CSS、JavaScript をカプセル化して .vue ファイル内に記述します。

Vueは1ファイルに1コンポーネントを定義します。それをSFCと呼んでいます。拡張子は.vueです。コンポーネント内のhtmlのタグ構造やcssのスタイルやjsの変数は、コンポーネントの外の世界には影響しません(グローバル変数じゃないよ)。

Vue の中核となる機能は宣言的レンダリングです。HTML を拡張したテンプレート構文を用いて、JavaScript の状態に基づいて HTML がどのように見えるかを記述することができます。状態が変更されると、HTML は自動的に更新されます。
変更されたときに更新のトリガーとなるような状態はリアクティブとみなされます。Vue では、リアクティブステートはコンポーネントに保持されます。

いまからこの文章の解説を始めますが、もし難しいと感じたら飛ばしましょう。
Vueの場合、データが変更されると、自動的に画面が更新されます。

例えば、フォームに入力されたら、入力した文章を下に表示するプログラムを書くときに、従来であれば、次のように書いていました。

従来のjsの書き方
    <input id="input-text" />
    <button id="submit-button">画面出力</button>

    <div id="display-input"></div>
    <script>
      function displayInput() {
        const inputForm = document.getElementById('input-text');
        const text = inputForm.value;
        console.log(text);
        const displayTag = document.getElementById('display-input');
        displayTag.innerHTML = text;
      }

      const button = document.getElementById('submit-button');
      button.onclick = displayInput;
    </script>

inputタグに文章を入れて、ボタンを押すと、displayInput関数が実行されます。この関数の中で、明示的にdisplay-inputIdのついてタグのテキストを更新しました。

それに対して、Vueの場合です。

<template>
  <div>
    <input id="input-text" />
    <button @click="displayInput">画面出力</button>
    <div>{{ inputText }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputText: '未入力',
    };
  },
  methods: {
    displayInput() {
      const inputForm = document.getElementById('input-text');
      // 注目!!! data()で定義したinputTextに代入している。
      this.inputText = inputForm.value;
    },
  },
};
</script>

ガラッとコードの書き方がかわりましたね。ボタンをクリックするとdisplayInput関数が発火します。displayInput関数の中では、先程同様にinputタグを取得してその値を取得しています。しかし、ここで次のコードに注目してください。

      // 注目!!! data()で定義したinputTextに代入している。
      this.inputText = inputForm.value;

これはここで定義しています。

  data() {
    return {
      inputText: '未入力',
    };
  },

実はVueはこのdata()の返り値で定義している変数に変更が加わると、そのたびにtemplateを描画し直すのです。templateをみてください。

<template>
  <div>
    <input id="input-text" />
    <button @click="displayInput">画面出力</button>
    <div>{{ inputText }}</div>
  </div>
</template>

{{ inputText }}という見たことのないhtmlっぽくないものがありますね。これはdata()で定義したinputTextです。templteにおいて、{{ }}のなかにdata()で定義した変数を入れ込むと、自動的に値を埋め込んでくれます。

まとめます。

  • Vueはdata()の返り値であるinputTextという変数を 監視 している。
  • Vueは監視しているinputTextに変更があるたびにtemplateを描画しなおす。
  • inputTextを変更するには、displayInputのように、クリックイベントなどに紐づく関数のなかで、this.inputText = ほげほげと代入するだけで良い。

長くなりましたが、これが宣言的レンダリングやリアクティブとよばれるものです。

ではチュートリアルをみてみましょう。次のようなVueファイルがあります。プレビューにはMake me dynamic!とだけ表示されています。

App.vue
<script>
export default {
  // ここにコンポーネントのいろんな設定をするよ
  // ここにdata()をつかって、変数を監視してみて。
}
</script>

<template>
  <h1>動的に描画してみて!</h1>
</template>

scriptexport default {}内部に、次のようにdata()関数を定義してみましょう。

  data() {
    return {
      message: 'Hello World!'
    }
  }

つぎに、templateタグのh1を次のように変更してみましょう。

<h1>{{ message }}</h1>

プレビューが変わったのがわかります。Hellow Worldというテキストを自分で変更してみましょう。変更するたびにレプビューの文字が変わるはずです。

また、{{}}内部は通常のjsと同じようにかけます。次のようにmessage変数の文字列を逆順にして表示してみましょう。

<h1>{{ message.split('').reverse().join('') }}</h1>

step2は以上です。

Step3 属性バインディング

いままで動的にhtmlのタグ(例えばclassタグ)を変更したいとき、どううしていたでしょうか?おそらくgetElementByIdでhtmlタグを取得して、.classList.add().classList.remove()を使っていたと思います。

<body>
	<div id="display-text" class="text">aaa</div>
	<button id="button">このテキストを隠す</button>
	<style>
		.text{
		  color: blue;
		  fontSize: 16px;
		}
		.hidden{
		  visibility: hidden;
		}
	</style>
	<script>
	  function hideText () {
	    const textElement = document.getElementById("display-text");	
			     
	    textElement.classList.add("hidden");
	  }

	  const buttonElement = document.getElementById("button");
		
	  buttonElement.onclick = hideText;
	</script>
</body>

Vueの場合はこのようにかけます。 :class="textClass"の部分に注目してください。属性名の前にコロン(:)をつけることで、値としてdata()で定義したリアクティブな値を指定できるようになります。つまり、textClassという変数が変わると、自動的にclass属性が変わってくれます。ただし、clickなどのイベントリスナーの場合は、コロン(:)は使えず、代わりにアットマーク(@)を使用する必要があります。これは次のステップで詳しく扱います。

<template>
	<div id="display-text" :class="textClass">aaa</div>
	<button @click="hideText">このテキストを隠す</button>
</template>

<style>
	.text{
	  color: blue;
	  fontSize: 16px;
	}
	.hidden{
	  visibility: hidden;
	}
</style>

<script>
export default {
  data(){
    return {
      textClass: 'text'
    }
  },
  methods: {
    hideText () {
      const textElement = document.getElementById("display-text");	

      textElement.classList.add("hidden");
    }
  }
}
</script>

ではチュートリアルの課題に挑戦してみましょう。

<h1> に titleClass のデータプロパティ を値として動的の属性バインディングを追加してみましょう。正しくバインドできたら、文字が赤くなります。

これはh1タグのclass属性とtitleClass変数を結びつけてください、という問題です。属性バインディングをつかってうまく結びつけてみてください。

step3は以上です。

ながくなったので、記事を分割します。

https://zenn.dev/dove/articles/c4073b6979de32

Discussion