VueJS дочерний компонент не отображает данные - PullRequest
0 голосов
/ 18 мая 2019

У меня есть экран, на котором разделены основные разделы данных на вкладки, и надеюсь, что каждая вкладка будет иметь отдельный компонент.

Однако по какой-то причине данные не отображаются на компоненте при первом рендеринге. Дело в том, что если вы нажмете кнопку, чтобы обновить данные, то загрузится просто отлично. В любом случае я не получаю сообщений об ошибках, так что я думаю, что неправильно истолковываю жизненный цикл VueJS.

const CommentScreen = {
      props: {
        accountid: {
            type: Number,
            required: true
        }
    },
    template: `
        <div>
            <CommentForm
                v-on:commentsupdated="comments_get"
                v-bind:accountid="accountid"
            ></CommentForm>
            <v-btn round color="primary" v-on:click="comments_get" dark>Refresh Comments</v-btn>
            <v-data-table
                :headers="commentheaders"
                :items="comments"
                hide-actions>
                    <template slot="items" slot-scope="props">
                        <td>{{ props.item.entrydate }}</td>
                        <td>{{ props.item.entryuserforename + " " + props.item.entryusersurname }}</td>
                        <td>{{ props.item.comment }}</td>
                    </template>
            </v-data-table>
        </div>
    `,
    components: {
        'CommentForm': CommentForm
    },
    data(){
        return {
            commentheaders:[
                { text:'Entry Date', value:'entrydate' },
                { text:'Entry User', value:'entryuserforename' },
                { text:'Comment', value:'comment' }
            ],
            comments:[]
        }
    }
    ,
    mounted() {
        this.comments_get();
    },
    methods:{
        comments_get(){
            let url = new URL('/comments/', document.location);
            url.searchParams.append('accountid',this.accountid);

            let options = {
            method: 'GET',
            mode: 'cors',
            headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json;charset=UTF-8'
                }
            };

            self = this;
            fetch(url, options)
                .then(
                    response => {
                        if (response.status === 401) {
                            self.$root.$emit('notloggedin');
                        } else if (response.status === 403) {
                            self.$root.$emit('displayalert','Missing Permission: View Comments');
                        } else if (response.status === 204) {
                            self.comments = [];
                        } else if(!response.ok) {
                            response.json()
                                .then(data => self.$root.$emit('displayalert', data.errors))
                                .catch(error => self.$root.$emit('displayalert', error.status + ' ' + error.statusText));
                        } else {
                            response.json()
                                .then(data => self.comments = data.comments)
                                .catch(error => self.$root.$emit('displayalert', error));
                        }
                    }
                )
                .catch(error => self.$root.$emit('displayalert', error));
        }
    }
};

Простите за приведенный выше объем кода, я не уверен, что я мог / должен удалить, чтобы сделать вопрос более кратким.

Может кто-нибудь сообщить, как можно автоматически загружать данные на этот компонент при его первой загрузке?

Большое спасибо заранее.

Ответы [ 2 ]

1 голос
/ 18 мая 2019

Крюк mounted равен async, что делает этот вид хитрым.



Пример чего-то похожего на то, что вы пытаетесь сделать ..

new Vue({
  el: "#app",
  data: {
    placeId: 1,
    sight: "",
    sightImages: [],
    slideIndex: 1
  },
  mounted() {
    var self = this;
  fetch(`https://jsonplaceholder.typicode.com/albums/${this.placeId}/photos?_start=1&_end=10`)
      .then(response => {
        if (response.ok) {
          return response;
        } else {
          if (response.status === 401) {
            alert("401");
            //self.$root.$emit("notloggedin");
          }
          if (response.status === 403) {
            alert("403");
            //self.$root.$emit("displayalert", "Missing Permission: View Comments");
          }
          if (response.status === 204) {
            alert("204");
            //self.comments = [];
          }
        }
      })
      .then(response => response.json())
      .catch(error => {
        console.log("ERROR " + error);
      })
      .then(data => {
        self.sight = {
          id: data[0].albumId
        };
        self.sightImages = data;
      })
      /** IF YOU REMOVE THIS THINGS WONT WORK RIGHT */
      .then(() => {
        self.showSlides(self.slideIndex);
      });
    /** */
  },
  methods: {
    showSlides(n) {
      let i;
      let slides = document.getElementsByClassName("mySlides");
      let dots = document.getElementsByClassName("demo");
      let captionText = document.getElementById("caption");

      if (n > slides.length) {
        this.slideIndex = 1;
      }
      if (n < 1) {
        this.slideIndex = slides.length;
      }
      for (i = 0; i < slides.length; i++) {
        slides[i].style.display = "none";
      }
      for (i = 0; i < dots.length; i++) {
        dots[i].className = dots[i].className.replace(" active", "");
      }
      console.log(slides[0]);
      console.log(document.getElementsByClassName("mySlides").length);
      slides[this.slideIndex - 1].style.display = "block";
      dots[this.slideIndex - 1].className += " active";
      captionText.innerHTML = dots[this.slideIndex - 1].alt;
    },
    plusSlides(n) {
      this.showSlides((this.slideIndex += n));
    },
    currentSlide(n) {
      this.showSlides((this.slideIndex = n));
    }
  },
});
.demo-cursor {
  width: 3% !important;
  cursor: pointer;
  margin: 0px 2px
}

.sight-photos {
  width: 6%;
}

.row {
  display: inline-block;
}

.cntrlbtn {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js"></script>

<div id="app">
  <div class="wrapper">
    <div class="sight-container">
      <p class='sight-name'>Sight Id: {{ sight.id }}</p>
      <div class="photos-container">
        <div v-for='(image, index) in sightImages' class="mySlides">
          <div class="numbertext">{{ index + 1 }} / {{ sightImages.length }}</div>
          <img class='sight-photos' :src="image.thumbnailUrl">
        </div>
        <a class="cntrlbtn" @click='plusSlides(-1)'>❮</a>
        <a class="cntrlbtn" @click='plusSlides(1)'>❯</a>
        <div class="caption-container">
          <p id="caption"></p>
        </div>
        <div class="row">
          <img v-for='(image, index) in sightImages' class="demo-cursor" :src="image.url" @click="currentSlide(index + 1)">
        </div>
      </div>
    </div>
  </div>
</div>


Вы можете попробовать что-то вроде этого:

const self = this;
fetch(url, options)
  .then(response => {
    if (response.ok) {
      return response;
    } else {
      if (response.status === 401) {
        self.$root.$emit("notloggedin");
      }
      if (response.status === 403) {
        self.$root.$emit("displayalert", "Missing Permission: View Comments");
      }
      if (response.status === 204) {
        self.comments = [];
      }
    }
  })
  .then(response => response.json())
  .catch(error => {
    self.$root.$emit("displayalert", error);
  })
  .then(data => {
    self.comments = data.comments;
  });
0 голосов
/ 02 июня 2019

Я понял!

Проблема с кодом находится в следующей строке:

self = this;

При первом запуске кода выглядел неверный контекст, и толькопервый раз.Замена на

let self = this;

И проблемы были исправлены.

Иногда я ненавижу компьютеры, они всегда делают то, что я говорю, а не то, что я имею в виду!

...