Netlify Formsで簡易的お問い合わせフォーム機能 in Veu.js

# 簡単にお問い合わせフォームをVueで実装したい！　
(プログラミングはまだまだ勉強中の身でして、内容に誤りがあるかもしれません。コメントでご教授頂けるとありがたいです...)
Vue.jsでWebサイトを作成してる中で、ポートフォリオ用などに、
サーバーレスで簡易的にフォーム機能を実装したいと思い、今回は、NetlifyのNetlifyFormsとういう機能を使用しました。

__Netlifyとは？__
静的ウェブサイトのためのホスティングサービスとサーバーレスのバックエンドサービスを提供。
GitHubとの連携で、自動デプロイも行ってくれる便利なWebサービスです。

## 前提
今回は、送信ボタンを押しても、バリデーションチェックのみ走り、実際にはどこにもデータが送信されない状態のcontact-formを使用しています。

* Vue.jsでサイト(Form)を作成済み
* contact-formにバリデーション機能を実装済み
* Vue Routerはインストール済み(Vue CLI使用)
* Netlifyでデプロイ設定済み　
[Vue.js＋Netlifyで自動デプロイの方法](https://cr-vue.mio3io.com/tutorials/netlify.html#netlify-%E3%81%A8%E3%81%AF%EF%BC%9F)

## 手順
###1, HTMLのフォームを作成 (NetlifyFormsはHTMLのフォームを認識し、作動する為)

```html:public/index.html
 <body ontouchstart="">
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
　　　//追記
    <form
      name="contact"
      data-netlify="true"
      data-netlify-honeypot="bot-field"
      hidden>
   
      <input type="text" name="name" />
      <input type="email" name="email" />
      <textarea name="message"></textarea>
    </form>
　　//ここまで

    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
```

### 2,Vue.jsのフォームに追加設定

__! formの属性にname, method, data-netlify, data-netlify-honeypot, 
そして hidden input field を設定__

* data-netlify-honeypotとhidden inputはスパム防止の設定です。
* hidden inputタグのnameは必ず”form-name”にして、そのvalue = formタグのname
(ここでは”contact”)になるようにします。
* @submit.preventはデフォルトの更新機能をなくします。[参考](https://qiita.com/yuta-38/items/33845020453b0af6ebde)

```vue:Contact.vue
     <form  
        class="contact-form"
        @submit.prevent="handleSubmit"
        novalidate="true"
        name="contact"
        method="POST"
        data-netlify="true"
        data-netlify-honeypot="bot-field"
      >
        <input type="hidden" name="form-name" value="contact" />

        <div class="errors" v-if="errors.length">
          <ul>
            <li v-for="error in errors" v-bind:key="error">{{ error }}</li>
          </ul>
        </div>

        <div class="flex-row">
          <input
            type="text"
            name="name"
            placeholder="お名前"
            v-model="form.name"
          />
        </div>
        <div class="flex-row">
          <input
            type="email"
            name="email"
            placeholder="メールアドレス"
            v-model="form.email"
          />

        </div>
        <div class="flex-row">
          <textarea
            type="text"
            name="message"
            placeholder="本文"
            v-model="form.message"
          ></textarea>
        </div>
        <button class="btn">送信</button>
      </form>
```

### 3, ローカルdataの設定
後にformをスプレッド構文で展開した配列をフォームの内容として渡す。

```javascript

data() {
    return {
      errors: [],
      form: {
        name: null,
        email: null,
        message: null,
      },
    };
  },
```

### 4, メソッドの設定
javascriptオブジェクトであるformをencod( )で、HTTPリクエストに沿った形式に変換してからPOSTリクエストで送信

```javascript
encode(data) {
      return Object.keys(data)
        .map(
          (key) => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`
        )
        .join("&");
    },

handleSubmit() {
      this.checkForm(); //別にバリデーション関数を用意
      fetch("/", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: this.encode({
          "form-name": "contact",
          ...this.form, //name, email, messageが入っている
        }),
      })
        .then(() => {
          this.$router.push("thanks");//成功時
        })
        .catch(() => {
          this.$router.push("404");//失敗時
        });
    },
```

### 5, Routerと成功時、失敗時のそれぞれの遷移先のページを用意
コードは省略します。

### 6, Netlifyのマイページより、送信されたお問い合わせフォームを確認
サイト内の設定のForm notificationsから管理者宛の通知(emailやslackなど)を設定できます。
## 参考
https://www.netlify.com/blog/2018/09/07/how-to-integrate-netlify-forms-in-a-vue-app/

https://gurutaka-log.com/netlify-nuxt-contact-form

https://www.youtube.com/watch?v=omoYqKfvdfQ

https://notes.sharesl.net/articles/1711/