LoginSignup
0
2

More than 3 years have passed since last update.

Vueの 親子孫双方向バインディング 

Last updated at Posted at 2020-02-13

作成物の説明

atomics設計を参考にしています。
atoms→molecules→organisms→templates→pages
(孫)   (子)  (親)  今回のコンポーネントはこの対応で進めています。

うまくいかないとき

(孫)


<template>
  <v-menu
    v-model="calendar"
    :close-on-content-click="false"
    :nudge-right="40"
    transition="scale-transition"
    offset-y
    min-width="200px"
  >
    <template v-slot:activator="{ on }">
      <v-text-field
        :value="date"
        v-on="on"
        :label="label"
        prepend-inner-icon="mdi-calendar-range"
        readonly
        crearable
      />
    </template>
    <v-date-picker
      v-model="date"
      @input="calendar = false"
      @change="$emit('input', $event)"
    />
  </v-menu>
</template>

<script>
export default {
  props: {
    label: {
      type: String,
      default: 'Not Defined'
    },
    value: {
      type: String,
      default: ''
    }
  },
  data: () => ({
    // date: new Date().toISOString().substr(0, 10),
    date: '',
    menu: false,
    modal: false,
    calendar: false
  }),
  watch: {
    value (val) {
      this.date = val
    }
  }
}
</script>

(子)


<template>
  <span class="calendar-style">
    <input-calendar
      :label="label1 +`from`"
      v-model="dateFromTo[0]"
      @change="$emit('input', dateFromTo)"
    />&emsp;
    <input-calendar
      :label="label1+`to`"
      v-model="dateFromTo[1]"
      @change="$emit('input', dateFromTo)"
    />
  </span>
</template>

<script>
import InputCalendar from '~/components/atomics/InputCalendar'

export default {
  components: {
    InputCalendar
  },

  props: {
    value: {
      type: Array,
      default: () => (['', ''])
    },
    label1: {
      type: String,
      default: ''
    },
    label2: {
      type: String,
      default: ''
    }
  },

  data () {
    return {
      dateFromTo: ['', '']
    }
  },

  watch: {
    value (val) {
      this.dateFromTo = val
    }
  }
}
</script>

<style lang="scss" scoped>
  .calendar-style {
    display: inline-flex ;
  }
</style>

(親)


<template>
  <span>
    <v-col cols="12" class="calendar">
      <v-row>
        <p>{{ arriveDay }}</p>
        <calendar-from-to
          :label1="arriveDay"
          v-model="FromTo"
        />
        <p>{{ shipDay }}</p>
        <calendar-from-to
          :label1="shipDay"
          v-model="S_FromTo"
        />
      </v-row>
    </v-col>
    <v-row>
      <v-col cols="3">
        <input-arrive-place-company
          v-model="companyName"
        />
      </v-col>
      <v-col cols="3">
        <input-arrive-place-company-kana
          v-model="companyNameKana"
        />
      </v-col>
      <v-col cols="3">
        <input-ware-house v-model="warehouse" />
      </v-col>
    </v-row>
    <v-row>
      <v-col cols="3">
        <input-warning
          v-model="alert"
        />
      </v-col>
      <v-col cols="3">
        <input-status
          v-model="status"
        />
      </v-col>
      <v-col cols="3">
        <Input-registered-person
          v-model="person"
        />
      </v-col>
    </v-row>
  </span>
</template>

<script>
import CalendarFromTo from '~/components/molecules/CalendarFromTo'
import InputArrivePlaceCompany from '~/components/atomics/InputArrivePlaceCompany'
import InputArrivePlaceCompanyKana from '~/components/atomics/InputArrivePlaceCompanyKana'
import InputWareHouse from '~/components/atomics/InputWareHouse'
import InputWarning from '~/components/atomics/InputWarning'
import InputStatus from '~/components/atomics/InputStatus'
import InputRegisteredPerson from '~/components/atomics/InputRegisteredPerson'

export default {
  components: {
    CalendarFromTo,
    InputArrivePlaceCompany,
    InputArrivePlaceCompanyKana,
    InputWareHouse,
    InputWarning,
    InputStatus,
    InputRegisteredPerson
  },
  data () {
    return {
      arriveDay: '納品日',
      shipDay: '出荷日',
      warehouse: [],
      companyName: [],
      companyNameKana: [],
      alert: [],
      status: [],
      person: [],
      date: '',
      FromTo: ['', ''],
      S_FromTo: []
    }
  },
  methods: {
  }
}
</script>

うまくいったとき

孫を直しました。
template内で@での呼び出しで、emitではなくonChangeというfunctionを呼び出し、$emitでinput とchangeを発火させるようにしました。
(孫のtemplate内)


<v-date-picker
      v-model="date"
      @input="calendar = false"
      @change="onChange"
    />

(孫のscript内)


methods: {
    onChange (e) {
      this.$emit('input', e)
      this.$emit('change', e)
    }
  }

孫のtemplate内の$emitの呼び出しだけではうまく子のvalueの値が書き変わらなかったので困っているところ、
助けてもらい、functionで強制発火する方法で解決できました。

0
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2