Vue3の基本1(CDNからscriptファイルを読み込んでhtmlファイル内でVueアプリケーションを作成)

目次

(参考資料)
・Vue3 日本語ドキュメント
 https://v3.ja.vuejs.org/
・Vue.js3超入門(掌田津耶乃著)秀和システム

1.Vueの動作環境
(1)動作環境
 ・Windows 10 Pro
 ・XAMPP Control Panel v3.2.4
(2)Node.jsのインストール
 Node.jsはJavaScript実行環境でパッケージ管理ツールnpm(Node Package Manager)が組み込まれています。
下記のサイトにアクセスしてダウンロードします。https://nodejs.org/ja/

Node.jsのバージョンは偶数が長期サポートの安定版。
任意のバージョンをダウンロードしたいときは下記のページ。
https://nodejs.org/ja/download/releases/

Version16.13.0 LTSをダウンロード
・ファイル名:node-v16.13.0-x64.msiを実行

ネイティブモジュール用ツールオプションはデフォルトのままチェックOFF

・動作を確認します
 > node –version

・VueCLIのインストール
 VueCLIはVue開発のためのコマンドツールです。
 > npm i -g @vue/cli-service-global

(3)プロトタイプアプリケーションの作成
・フォルダを作ります。
 C:\Users\・・・\Desktop\vue_work
・ app.vueファイルを作成します。
 app.vue

<template>
  <div id="app">
    <h1>Hello!</h1>
    <p>This is message...</p>
  </div>
</template>

・app.vueファイルを置いたフォルダに移動して次のコマンドを実行します。
 > vue serve
 またはファイルを指定して
 > vue serve app.vue

・ブラウザでアクセス

・Webサーバの停止
 Ctrl+C

2.プロジェクトの作成
(1)VueCLIコマンドを使ったプロジェクトの作成
 > vue create (プロジェクト名)

 > vue create hello_app
 Default(Vue3)・・・を選択

パッケージマネージャー NPMを選択

(2)プロジェクトの実行
 > cd hello_app
 > npm run serve

(3)プロジェクトフォルダの内容

(4)プロジェクトのビルド
 > npm run build

distフォルダが作成され、この中に公開するファイルが一式まとめられている

XAMPPのApatchサーバを起動し、distフォルダ内のファイル、フォルダをhtdocs配下に置く。

ブラウザでhttp://localhost:80にアクセスする

3.Vue3の基本
3.1 Vue3のオブジェクトからの{{プロパティ}}の表示
 Vueオブジェクトがマウントされたタグ内にある{{プロパティ}}にはVueオブジェクトで定義されたプロパティの値が入ります。またこの値はオブジェクト内の値がリアルタイムにチェックされ、値が更新されると、自動的に{{}}の表示も更新されます。

sample1
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <h1>Vue3</h1>
  <div id="app">
  {{ message }}
  </div>

  <script>
  const appdata = {
    data() {
      return {
        message: 'Hello Vue!'
      }
    }
  }

  Vue.createApp(appdata).mount('#app')
  </script>
</body>
</html>

3.2 v-htmlによるHTML要素の出力
 タグの中にv-html属性を使うことで、Vueオブジェクト側で用意したHTMLのコードで画面に表示できます。
 タグには、<div v-html=”変数名”></div>とし、
Vueオブジェクトのdataプロパティの中で”変数名”にテンプレートリテラルを設定します。
 テンプレートリテラルはプレースホルダー(${変数名}と書き、予め用意した変数をはめ込める)が使えます。

sample2
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <h1>Vue3</h1>
  <div id="app">
    <div v-html="message"></div>
  </div>
  
  <script>
  const list = ['One', 'Two', 'Three']
  const appdata = {
    data() {
      return {
        message: `<ul>
          <li>${list[0]}</li>
          <li>${list[1]}</li>
          <li>${list[2]}</li>
        </ul>`
      }
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

3.3 v属性によるタグの属性の設定
 タグの中に「v-bind:属性名=”設定する値”」を記述することで、Vueオブジェクトからタグの属性を設定することができます。
(1)Vueオブジェクトからのスタイルの設定
タグの中で「v-bind:style=”変数”」で設定します。または「v-bind:style=”オブジェクト名”」としてVueインスタンスにdataプロパティの中にオブジェクトを用意しておくこともできます。
sample3
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>

  <div id="app">
    <p v-bind:style="style">{{ message }}</p>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : null,
        style:'font-size:32pt; color:red;'
      }
    },
    mounted() {
      this.message = 'This is sample page.'
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

(2)Vueオブジェクトからのクラスの設定
タグの中で「v-bind:class={クラス名:”変数”}」で設定します。または「v-bind:class=”オブジェクト名”」としてVueインスタンスにdataプロパティの中にオブジェクトを用意しておくこともできます。
sample4
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <style>
  .red {
      color:red;
  }
  .blue {
      color:blue;
  }
  </style>
  <div id="app">
    <p v-bind:class="{red:isRed, blue:isBlue}">
      {{ message }}
    </p>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : null,
        isRed: true,
        isBlue: false
      }
    },
    mounted() {
      this.message = 'This is sample page.'
      setInterval(()=>{
        this.isBlue = !this.isBlue
        this.isRed = !this.isRed
      },1000)
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

1秒毎に文字色が赤、青交互に変わります。

(3)v-ifによる条件付きレンダリング
タグの中で「v-if=”条件”」で設定します。
sample5
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <style>
  .red {
      color:red;
  }
  .blue {
      color:blue;
  }
  </style>
  <div id="app">
    <p v-if="isRed" class="red">
       {{ message }}
    <p v-else class="blue">
       {{ message }}
    </p>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : null,
        isRed: true,
        isBlue: false
      }
    },
    mounted() {
      this.message = 'This is sample page.'
      setInterval(()=>{
        this.isBlue = !this.isBlue
        this.isRed = !this.isRed
      },1000)
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

<タグ v-if=”条件”>・・・</タグ>
<タグ v-else>・・・</タグ>
のとき、条件のtrue/falseでどちらかのタグが表示されます。
 1秒毎にclass属性を変えて、文字色が赤、青交互に変わるようにしています。

(4)HTMLのタグを<template>タグでまとめる
 複数のタグを<template>タグでまとめることで、v-ifの条件によって、複数のタグを切り替えることができます。<template>タグは表示されません。

sample6
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="app">
    <template v-if="isRed">
     <p v-bind:style="style1">{{ message }}</p>
    </template>   
    <template v-else>
     <p v-bind:style="style2">{{ message }}</p>
    </template>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : null,
        style1:'font-size:32pt; color:red;',
        style2:'font-size:48pt; color:blue;',
        isRed: true,
        isBlue: false
      }
    },
    mounted() {
      this.message = 'This is sample page.'
      setInterval(()=>{
        this.isBlue = !this.isBlue
        this.isRed = !this.isRed
      },1000)
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

1秒毎に<template>タグの条件を変えて、文字スタイルが交互に変わるようにしています。

(5)v-forによる配列データのレンダリング
<タグ v-for=”変数” in 配列> ・・・表示内容・・・</タグ>
の形で記述します。

sample7
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
    <table class="table">
        <tr>
          <th>Name</th>
          <th>Mail</th>
          <th>Tel</th>
        </tr>
        <tr v-for="item in items">
        <td>{{item.name}}</td>
        <td>{{item.mail}}</td>
        <td>{{item.tel}}</td>
      </tr>
    </table>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message :"データの一覧表示",
        items:[
          {name:'Suzuki', mail:'suzuki@com', tel:'123-456'},
          {name:'Yamasita', mail:'yamasita@com', tel:'456-789'},
          {name:'Tanaka', mail:'tanaka@com', tel:'789-123'},
        ]
      }
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

v-forは配列から要素を取り出し
<タグ v-for=”取り出した要素を入れる変数,インデックス” in 配列>・・・表示内容・・・</タグ>
の形で記述することで第2引数として配列のインデックスを取り出せます。

sample8
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
    <table class="table">
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Mail</th>
          <th>Tel</th>
        </tr>
        <tr v-for="(item,id) in items">
        <td>{{id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.mail}}</td>
        <td>{{item.tel}}</td>
      </tr>
    </table>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message :"データの一覧表示",
        items:[
          {name:'Suzuki', mail:'suzuki@com', tel:'123-456'},
          {name:'Yamasita', mail:'yamasita@com', tel:'456-789'},
          {name:'Tanaka', mail:'tanaka@com', tel:'789-123'},
        ]
      }
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

(6)v-forによるオブジェクトデータのレンダリング
 <タグ v-for=”(値,キー)” in オブジェクト>・・・表示内容・・・</タグ>の形で記述します。

sample9
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
    <table class="table">
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Mail</th>
          <th>Tel</th>
        </tr>
        <tr v-for="(item,key) in items">
        <td>{{key}}</td>
        <td>{{item.name}}</td>
        <td>{{item.mail}}</td>
        <td>{{item.tel}}</td>
      </tr>
    </table>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message :"データの一覧表示",
        items:{
          Suzuki:{mail:'suzuki@com', tel:'123-456'},
          Yamasita:{mail:'yamasita@com', tel:'456-789'},
          Tanaka:{mail:'tanaka@com', tel:'789-123'},
        }
      }
    }
  }

  let app = Vue.createApp(appdata)
  app.mount('#app')
  </script>
</body>
</html>

4.コンポーネントの基本
4.1 コンポーネントの作成と利用
 コンポーネントは、JavaScript側とHTML側(テンプレート)をひとまとめにして部品化して再利用できるようにしたものです。
 コンポーネントの作成は、Vueアプリケーション.component(名前,{設定情報})
 HTMLの中で使うときは、コンポーネントの名前のタグを記述します。
 <コンポーネント />

sample10
「Hello component!」を表示するコンポーネントを作成します。下記の順番で実装します。
①Vueアプリケーション(オブジェクト)を作成する
let app = Vue.createApp(appdata)
②アプリケーションにコンポーネントを組み込む
app.component(‘hello’, {
 template:'<p>Hello component! </p>’
 })
③HTMLにアプリケーションを組み込む
app.mount(‘#app’)

index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
    <hello/>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
    template: '<p> Hello component! </p>'
  })

  app.mount('#app')
  </script>
</body>
</html>

4.2 変数をコンポーネントに渡す
 コンポーネントのdataプロパティに変数を定義することでコンポーネントに変数をわたすことができ、テンプレートの外で変数の値を設定できます。
 
sample11
index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{ message }}</p>
    <hello/>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
    data:function(){     //短縮形 data(){
      return {
        message : 'helloコンポーネント'
      }
    },
    template: '<p> {{message}} </p>'
    })

  app.mount('#app')
  </script>
</body>
</html>

4.3 コンポーネントのタグに属性をもたせる
 コンポーネントのタグに属性を設定してテンプレートで使えるようにするためには、コンポーネントに”props”プロパティを用意します。
 props:[名前1,名前2,・・・]

sample12
 コンポーネントのタグの属性に設定した文字列をテンプレートに表示します。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello name="Suzuki" />
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      props:['name'],
      template: '<p> Hello component! {{name}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

sample13
 props:[‘name’]の配列は、変数の型や初期値を指定したいときは、オブジェクトとして
 props:{
  name:{
   type:String,
   default:”}
  },
 }
とすることもできます。

index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello name="Suzuki" />
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      props:{
         name:{
            type:String,
            default:''
         }
      },
  
      template: '<p> Hello component! {{name}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

4.4 コンポーネントのタグの属性の設定
 前述のようにVueオブジェクトにマウントされたHTMLのタグにv-bindで属性の設定ができたように、コンポーネントでもv-bindで属性の設定ができます。
(1)コンポーネントのタグにv-bindによる属性の設定
 sample14
 配列から取り出したデータをv-bindでname属性に設定し、
テンプレートに表示します。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello v-for="item in data" v-bind:name="item" />
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します',
        data:['Suzuki','Yamasita','Yamamoto']
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      props:['name'],
      template: '<p> Hello component! {{name}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

(2)inputタグにv-modelの設定
 inputタグに設定されたv-model属性は、入力された値をVueオブジェクトの変数にバインドする働きをします。
 sample15
 index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <div><hello v-bind:name="name" /></div>
    <div><input type="text" v-model="name" ></div>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します',
        name:"suzuki"
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      props:['name'],
      template: '<p> Hello component! {{name}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

(3)コンポーネントのタグにv-onの設定
 v-on属性を使うことでイベントに値をバインドして、Vueオブジェクトで扱うことができます。
 sample16
 ボタンを押す毎に数字をインクリメントして、カウンタ表示します。
 index.html

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello/>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します',
        name:""
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      data(){
        return{
          counter:0,
        }
      },
      template: '<p v-on:click="counter++"> counter! {{counter}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

(4)イベント処理をメソッドにまとめる
 上記(3)では 「v-on:click=”counter++”」として直接、値(式)を記述しましたが、ここではこの式をメソッドから呼ぶようにします。 
 sample17
 ボタンを押す毎に数字をインクリメントして、カウンタ表示します。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello/>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します',
        name:""
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.component('hello', {
      data(){
        return{
          counter:0,
        }
      },
      methods:{
        countup(){
          this.counter++;
        }
      },
      template: '<p v-on:click="countup"> counter! {{counter}} </p>'
  })
  
  app.mount('#app')
  </script>
</body>
</html>

・メソッドで変数を扱うとき、このオブジェクトの変数であることを示すため「this.counter++;」のようにthisを付けます。

4.5 算術プロパティ
 methodsプロパティとcomputedプロパティ(算術プロパティ)には関数式を定義できますが、算術プロパティは依存する値が更新された時に実行されます。
 上記ではイベントでメソッドを呼び出して値を更新しましたが、算術プロパティにcountup()を定義したときはカウントアップしません。

4.6 ローカルコンポーネント
 上記では、
(アプリケーション).component(‘hello’,{ data、method、templateなどのプロパティの定義})で定義したグローバルコンポーネントは全て読み込まれます。これに対してローカルコンポーネントで定義することで、必要なコンポーネントのみ読み込んで使うことができます。

sample18
 sample17をローカルコンポーネントとして書き換えたコードです。
 sample17では、app.component(‘hello’・・・)でVueオブジェクトに組み込んでいた(グローバルコンポーネント)をアプリケーション変数にcomponentsプロパティで登録してローカルコンポーネントとして登録します。

<!DOCTYPE html>
<html>
<head>
  <title>My first Vue app</title>
  <script src="https://unpkg.com/vue@next"></script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
  <div id="app">
    <p>{{message}}</p>
    <hello/>
  </div>
  
  <script>
  const appdata = {
    data() {
      return {
        message : 'コンポーネントを表示します',
        name:""
      }
    },
    components:{
      hello:{
        data(){
          return{
            counter:0,
          }
        },
        methods:{
          countup(){
            this.counter++;
          }
        },
        template: '<p v-on:click="countup"> counter! {{counter}} </p>'
      }
    }
  }

  let app = Vue.createApp(appdata)

  app.mount('#app')
  </script>
</body>
</html>

The end