VueJS компонент отображает другое содержимое компонента - PullRequest
0 голосов
/ 29 мая 2020

Цель: Vue компонент адрес ввода должен находиться внутри Vue компонента mail- composer и отображать список адресов только при нажатии Адресная книга кнопка. Когда кто-то щелкает одно из отображаемых писем или заполняет поле Кому вручную, createdmail.to должен получить значение, а я должен скрыть список адресов.

Vue компонент почта- composer. Этот компонент получает список адресов. (Здесь все работает, я думаю, что единственная часть, которая не работает должным образом, - это v-модель внутри input-address tag)

Vue.component('mail-composer', {
    props: ['addressesbook'],
    methods: {
      send: function(createmail) {
        this.$emit('send', createmail);
      }


    },
            template:
            `
            <div>
              <input-address :addresses="addressesbook" v-model="createmail.to"></input-address>
              <p><b>Subject: </b><input type="text" v-model="createmail.subject"></input></p>
              <p><b>Body: </b><textarea v-model="createmail.body"></textarea></p>
              <button @click="send(createmail)">Send</button>
            </div>
            `,
            data(){
              return{
                createmail:{
                  to: '',
                  subject: '',
                  body: ''
                }

              }
            }

      });

Другой компонент Vue - это , который находится в том же файле. (Я думаю, что все проблемы здесь).

Мне нужно отображать список адресов только тогда, когда кто-то нажимает кнопку Адресная книга , и мне приходится скрывать его, когда кто-то снова нажимает кнопку или одно из писем, которые есть в списке. Когда кто-то щелкает письмо из списка, свойство createmail.to из mail- composer должно получить значение почты, даже если я решу отправить почту по со стороны должно происходить то же самое.

Vue.component('input-address',{
        props:["addresses"],
        template:
        `
          <div>
          <label><b>To: </b><input type="text"></input><button @click="!(displayAddressBook)">Address Book</button></label>
          <ul v-if="displayAddressBook">
            <li  v-for="address in addresses">
            {{address}}
            </li>
          </ul>
          </div>
        `,
        data(){
          return{
            displayAddressBook: false
          }
        }


      })

1 Ответ

0 голосов
/ 30 мая 2020

В вашем коде есть некоторые ошибки:

  • @click="!(displayAddressBook)" должно быть @click="displayAddressBook = !displayAddressBook" - первое действительно ничего не делает (интересно), второе (предлагается) устанавливает значение displayAddressBook наоборот.
  • компонент адреса ввода на самом деле ничего не делает с полем ввода (отсутствует v-model)
  • изменения в дочернем компоненте (input-address ) не отправляются обратно родительскому компоненту (добавлен watch er для этого в дочернем компоненте)
  • родительский компонент (mail-composer) должен обрабатывать значения, испускаемые дочерним элементом (добавлен @address-change обработчик действий)
  • v-for в вашем компоненте input-address не имеет набора key. Добавлен key с использованием индекса для него (не лучшее решение, но его легко сделать).
  • просто поместите createmail.to: {{ createmail.to }} в конец MailComposer, чтобы вы могли видеть, как он меняется

Предложения

  • всегда используйте CamelCase для имен компонентов - если вы к нему привыкнете, то получите меньше «почему не работает ?!» моменты
  • следите за опечатками: createmail выглядит не очень хорошо - createEmail или просто createemail было бы лучше (ладно, это выглядит не так красиво - может, вам стоит выбрать совершенно другой имя для этого)

Vue.component('InputAddress', {
  props: ["addresses"],
  data() {
    return {
      displayAddressBook: false,
      address: null
    }
  },
  template: `
          <div>
          <label><b>To: </b>
            <input
              type="text"
              v-model="address"
            />
            <button
              @click="displayAddressBook = !displayAddressBook"
            >
              Address Book
            </button>
          </label>
          <ul v-if="displayAddressBook">
            <li
              v-for="(address, i) in addresses"
              :key="i"
              @click="clickAddressHandler(address)"
             >
              {{address}}
            </li>
          </ul>
          </div>
        `,
  watch: {
    address(newVal) {
      // emitting value to parent on change of the address
      // data attribute
      this.$emit('address-change', newVal)
    }
  },
  methods: {
    clickAddressHandler(address) {
      // handling click on an address in the address book
      this.address = address
      this.displayAddressBook = false
    }
  }
})

Vue.component('MailComposer', {
  props: ['addressesbook'],
  data() {
    return {
      createmail: {
        to: '',
        subject: '',
        body: ''
      }
    }
  },
  methods: {
    send: function(createmail) {
      this.$emit('send', createmail);
    },
    addressChangeHandler(value) {
      this.createmail.to = value
    }
  },
  template: `
            <div>
              <input-address
                :addresses="addressesbook"
                v-model="createmail.to"
                @address-change="addressChangeHandler"
              />
              <p>
                <b>Subject: </b>
                <input
                  type="text"
                  v-model="createmail.subject"
                />
              </p>
              <p>
                <b>Body: </b>
                <textarea v-model="createmail.body"></textarea>
              </p>
              <button @click="send(createmail)">Send</button><br />
              createmail.to: {{ createmail.to }}
            </div>
            `
});

new Vue({
  el: "#app",
  data: {
    addressesbook: [
      'abcd@abcd.com',
      'fghi@fghi.com'
    ]
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <mail-composer :addressesbook="addressesbook" />
</div>
...