質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.79%

Nuxt.jsでコンポーネント間のデータのやり取りについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,222

score 13

フォームで入力した値をヘッダー側で参照したいのですが、上手く値が取れません。

ログアウト時に入力中のデータをDBに登録するため、ヘッダー内にあるログアウトボタンを押下時にフォームのデータを参照、受け取る必要があります。

どうぞご教授お願いいたします。

試したこと

propsを利用したりして、コンポーネント間のデータのやり取りを試したが書き方が悪いのかダメでした。

フロント開発が初めてでさらにvue.js、nuxt.jsも使うのが初めてで、すでにあるソースに変更を加える形になります。

どうぞご教授よろしくお願いいたします。

該当のソースコード

構成

index.vue(indexからheade、form、footerをimport)
    header.vue
    form.vue(formからinput、inputshort、selectをimport)
        input.vue
        select.vue
    footer.vue

index.vue

<template>
  <section class="Container">
    <div class="App">
      <Header :text="title" v-if="!isApp" v-model="postDT"></Header>
      <div>
        <Form v-model="postDT"></Form>
        <PageTop></PageTop>
        <Footer v-if="!isApp"></Footer>
      </div>
    </div>
  </section>
</template>

<script>
import Header from "@/components/AAAAA/Header";
import Form from "@/components/AAAAA/Form";
import PageTop from "@/components/AAAAA/PageTop";
import Footer from "@/components/AAAAA/Footer";

import Meta from "~/assets/mixins/metaDT";

export default {
  mixins: [Meta],
  components: {
    Header,
    Form,
    PageTop,
    Footer
  },
  data() {
    return {
      title: "",
      meta: {
        title: "",
        description: ""
      },
      postDT: {}
    };
  },
  asyncData({ store, route, userAgent }) {
    let isApp = false;
    if (userAgent.indexOf("") > -1) {
      isApp = true;
    } else {
      isApp = false;
    }
    return {
      isApp
    };
  }
};

header 

<template>
  <header class="Header" :class="XXXXX">
    <div class="Header-inner">
      <p class="Header-logo">
        <img src="*.svg" alt="XXXX" />
      </p>
      <span class="Text">{{text}}</span>
      <button class="Header-logout" @click="handleLogout">ログアウト</button>
    </div>
  </header>
</template>

<script>
export default {
  props: ["text", "postDT"],
  data() {
    return {
      cookieParams: ""
    };
  },
  methods: {
    handleLogout() {
      if (window.confirm("ログアウトしてもよろしいですか?")) {
        const cookies = document.cookie.split(";");
        const result = cookies.filter(x => x.indexOf("__xxxParams") > -1);
        if (result[0]) {
          this.cookieParams = result[0].split("=")[1];
        }
        this.$store.commit("XXXXX", true);
        この辺りでformのデータを取得する。

        this.$axios
          .post(
            `${this.$store.state.XXXXXXXXXX}/xxxxxLogout/`,
            {
              url: this.cookieParams,
              input_data: {
                  ここにフォームで入力したデータをセットする
              }
            },
            {
              headers: {
                accept: "application/json",
                "Content-Type": "application/json",
                token: this.$store.state.sessionId
              }
            }
          )
          .then(res => {
            this.$store.commit("XXXXX", false);
            this.$router.push(`/xxxxx/?p=${this.cookieParams}`);
          })
          .catch(err => {
            this.$store.commit("XXXXX", false);
            this.$router.push(`/xxxxx/?p=${this.cookieParams}`);
          });
      } else {
        return;
      }
    }
  }
};
</script>

Form.vue

<template>
    <div class="Form">
      <div class="Form-wrap" v-show="!$store.state.postFlg">
        <section-heading headingName="セクションタイトル"></section-heading>
        <div class="Form-inner">
          <div class="Form-content">
              <FormLabel labelName="GGGGG" isRequired="true"></FormLabel>
            <div class="Select-wrap">
              <select-boxA
                ID="GGGGG"
                labelRequire="true"
                @xxxxx-code="xxxxx"
                v-model="postDT.corporateGenre">
              </select-boxA>
            </div>
          </div>
          <div class="Form-content">
            <FormLabel labelName="YYYYY" isRequired="true"></FormLabel>
            <div class="Select-wrap">
              <selec-boxB
                  ID="HHHHH"
                  labelRequire="true"
                  @FFFFF-code="FFFFF"
              </select-boxB>
            </div>
          </div>
          <div class="Form-content">
            <FormLabel labelName="ID" isRequired="true"></FormLabel>
            <input-field
                ID="id"
                labelRequire="true"
                class="is-short"
                textFiledType="number"
                textFiledSize="default"
                maxLength=8
                v-model="postDT.id">
            </input-field>
          </div>
          <div class="Form-content">
            <FormLabel labelName="名称" isRequired="true"></FormLabel>
            <input-field
                ID="name"
                labelRequire="true"
                class="is-short"
                textFiledType="text"
                textFiledSize="default"
                maxLength=8
                v-model="postDT.name">
            </input-field>
          </div>
        </div>
      </div>
    </div>
</template>

selectA

<template>
  <div class="Selectbox" :class="{isError: confirmError}">
    <select :id="ID" :class="{isSelected: selected}" v-model="selected" @change="handleSelected">
      <option disabled value>選択してください</option>
      <option
        v-for="xxxxx in xxxxxs"
        :key="xxxxx.code"
        :value="`${xxxxx.name}`"
      >{{xxxxx.name}}</option>
    </select>
  </div>
</template>

<script>
import { xxx } from "~/assets/data/xxx.json";

export default {
  props: ["ID", "value", "confirmError"],
  data() {
    return {
      selected: "",
      prefectures
    };
  },
  methods: {
    handleSelected() {
      this.$emit("input", this.selected);
      this.xxxxxCode();
    },
   xxxxxCode() {
      const xxxxx = this.xxxxx.filter(
        xxxxx => xxxxx.name === this.selected
      );
      this.$emit("xxx-code", xxx);
    }
  },
  mounted() {
    setTimeout(() => {
      this.selected = this.$props.value;
      this.xxxxxCode();
    }, 1500);
  }
};
</script>

inputbox.vue

<template>
    <div class="FormItem" :class="textFiledSize">
        <FormLabel v-if="labelTitle" :labelName="labelTitle" :isRequired="labelRequire"></FormLabel>
        <input
            :id="ID"
            class="TextField"
            :value="value"
            type="text"
            pattern="\d*"
            :maxlength=maxLength
            v-on:input="$emit('input', $event.target.value)">
    </div>
</template>

<script>
import FormLabel from '@/components/XXXXX/FormLabel'

export default {
    props: ['ID','labelTitle', 'labelRequire', 'textFiledType', 'placeholderText', 'textFiledSize', 'value', 'confirmError' ,'noneMessege' , 'maxLength', 'min'],
    components: {
        FormLabel
    },
    computed: {
        textExist() {
            return this.$props.value.length
        },
        textSize() {
            return this.$props.textFiledSize
        }
    }
}
</script>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

実現されたいことについて、Prop, Emitでのパターンを簡単に書いてみました。
https://codepen.io/yuhigash/pen/dybKJNb?&editable=true&editors=101

設計によりますが、Vuexでの実装パターンも考えられます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/09/13 20:34

    このサンプルコードは、実現されたいことをProp、Emitで実装する場合の簡単なサンプルです。
    index.vue、header.vue、form.vueについて最小限で切り出して書きました。
    各コンポーネント間の値の渡し方についてイメージを掴んでもらえればと思います。

    キャンセル

  • 2019/09/13 20:39

    headerコンポーネントでEmitを使わずに実装する場合は、
    ・vuexを使う (下記はvuexを使う場合の1例です)
     ・formの内容をvuex storeで管理する
     ・formの各input要素の値が変わったタイミングでstoreを書き換える
     ・logoutボタンを押したタイミングでstoreからformの内容を取り出す
    ・headerコンポーネントにformをpropとして渡す
    が考えられると思います。

    キャンセル

  • 2019/09/20 08:54

    ありがとうございました。
    無事に解決できました。
    formでstoreに書き込み、ログアウト時にstoreから取り出す方法で解決できました。

    ご教授ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.79%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る