Vue.js 3をCodePenでサクッと試す

# 始めに
Vue.js 3がリリースされましたが、一々ローカルで試すのは面倒だと思います。vue-cliで簡単に環境が作れると言ってもローカルにファイルが増えるのがあまり嬉しく無いですし、動作確認すると時に毎回タスクランナーを実行するのは手間だと思います。
そこでCodePenでVue.js 3のやる方法についてまとめました。

# CodePenでVue.js 3を動かす設定
## HTML, CSS, JS領域の設定
CodePenを開いたらJSの領域の歯車アイコンをクリックします。
https://codepen.io/pen/
![スクリーンショット 2021-01-02 11.08.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/fd9d70ca-c6e0-8a0a-bd65-ef82fffd5ac1.png)

`Add External Scripts/Pens`に以下のURLを入力してVue.js 3のCDNを読み込むようにします。
入力したら右下の`Save & Close`を押します。
https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.4/vue.global.js
![スクリーンショット 2021-01-02 11.09.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/2dc18dfb-7930-8b92-432e-fff8cb762e48.png)

ついでにHTMLやCSSについてもプロセッサーの変更をします。
HTMLはpug, CSSはSCSSに変更してSaveします。

![スクリーンショット 2021-01-02 11.14.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/7b06558b-da49-32ae-ee94-63624c78ca31.png)
![スクリーンショット 2021-01-02 11.15.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/80ad47a5-0518-15a0-aec3-3165cd4e4763.png)

## HTML(Vue.jsのテンプレート部分）の記入
HTML領域に以下のコードを書きます。`#app`がマウント先になる要素で、scriptタグで書かれている部分はVue.jsのtemplate部分になります。JS側で直接templateを書いても良いですが、こちらの方がpugで書けてSFCっぽさも出るので僕はこのやり方を好んでいます。

```pug
//- エントリーポイント
#app

//- Vueアプリのテンプレート部分
script#vue-app(type="text/x-template")
  div
    div Hello, Vue.js 3!
    .counter
      button(@click="onMinusButtonClick") -
      span {{ count }}
      button(@click="onPlusButtonClick") + 
```

## JSの記入
CDNによってグローバルにVueが読み込まれているため、importせずに直接使います。ただしimportの書き方とできるだけ似せるために、分割代入で各メソッドを受け取っておくと他の記事で書かれているコードに近くなります。

```javascript
const { createApp, ref } = Vue;

const app = createApp({
  template: '#vue-app',
  setup() {
    const count = ref(0);
    
    const onMinusButtonClick = () => {
      count.value -= 1;
    };
    
    const onPlusButtonClick = () => {
      count.value += 1;
    };
    
    return {
      count,
      onMinusButtonClick,
      onPlusButtonClick,
    };
  },
});

app.mount('#app');
```

## サンプルコード
SCSSのコードも多少書いていますが、なくても動作に支障は無いため割愛します。
CodePenは以下に置きましたので、興味がある方は見てください。

<p class="codepen" data-height="349" data-theme-id="dark" data-default-tab="js,result" data-user="wintyo" data-slug-hash="RwGMwQP" style="height: 349px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Vue.js 3でカウンターの実装">
  <span>See the Pen <a href="https://codepen.io/wintyo/pen/RwGMwQP">
  Vue.js 3でカウンターの実装</a> by wintyo (<a href="https://codepen.io/wintyo">@wintyo</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

また、一々CDNの設定やpugの設定が面倒だと思いますので、このPenをForkしたらもっと気軽に試せると思います😄
Forkは意外と見つけづらくて、右下のところにあります。

![スクリーンショット 2021-01-02 11.32.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187768/da3bd6aa-2878-b58a-7ed1-cd27883e6b0b.png)

# オンラインエディタならではの違いと差分の吸収方法
以上はCodePenでVue.js 3を試す方法ですが、webpackでビルドするときと若干違うため他の記事でコードを見た時に混乱を招く事があると思います。その辺の違いと、できるだけその差をなくした方法についても書きたいと思います。

## SFCで書けない問題の対応
よくVue.jsではSFCでHTML, CSS, JSを1つのファイルにまとめて書きます。しかしそれはwebpackでビルドするからできる事で、CodePenではできません。Vue.jsにはx-templateという機能があるため、それでSFCっぽさを出します。

```vue:SFCで書く場合
<template lang="pug">
div
  .counter
    button(@click="onMinusButtonClick") -
    span {{ count }}
    button(@click="onPlusButtonClick") +
</template>

<script>
import { ref, defineComponent ) from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    
    const onMinusButtonClick = () => {
      count.value -= 1;
    };
    
    const onPlusButtonClick = () => {
      count.value += 1;
    };
    
    return {
      count,
      onMinusButtonClick,
      onPlusButtonClick,
    };
  },
});
</script>

<style lang="scss">
.counter {
  > span {
    padding: 0 5px;
  }
}
</style>
```

これをx-templateを使って分けると以下のようになります。

```pug:x-templateを使ってtemplate部分を外出しする(HTML側)
script#vue-app(type="text/x-template")
  div
    .counter
      button(@click="onMinusButtonClick") -
      span {{ count }}
      button(@click="onPlusButtonClick") + 
```

```javascript:x-templateを使ってtemplate部分を外出しする(JS側)
import { ref, defineComponent ) from 'vue';

export default defineComponent({
  template: '#vue-app', // pug側で定義したIDを指定する
  setup() {
    // 省略
  },
});
```

このようにする事で単純にコードがHTML側に移動しただけになるのでコードの移行がしやすくなります。

scoped CSSについてはどうしようもないのでグローバルCSSとして扱います。オンラインエディタは基本的に簡単なコードを書くと思うので、CSSのバッティングを気にするほどではないかなと思います。

## import文が書けない対応
webpackを使っている場合は`import { createApp } from 'vue';`のように書きますが、CDNでグローバルインストールした際は`Vue`に全てが入っているためimportする必要がなくなります。なので`Vue.createApp`と書いても問題なく動作します。
しかし毎回`Vue.`を書く手間と、他の記事ではそのような書き方はされないと思うため、分割代入をしてimportした時と同じ名前になっていた方がコードの修正が楽になると思います。

```javascript:importする際によく書かれる例
import { createApp } from 'vue';

const app = createApp({
  // 各種設定
});

app.mount('#app');
```

```javascript:グローバルインストールしてもできるだけimport文と合わせる
// import文だけ分割代入に書き換えれば動く
const { createApp } = Vue;

const app = createApp({
  // 各種設定
});

app.mount('#app');
```

# 終わりに
以上がCodePenでVue.js 3を試す方法でした。webpackでビルドするわけではないため多少書き方は変わってしまいますが、要所の部分は同じですので、上手く頭を切り替えられれば気軽に試せると思います。
Vue.js 3は結構改良されているので、まずはCodePenで軽く試してみるのはいかがでしょうか。