VueJS子组件未呈现数据

时间:2019-05-18 16:25:02

标签: javascript vue.js vue-component

我有一个屏幕,将其主要数据部分划分为多个选项卡,希望每个选项卡都位于其自己的组件上。

但是,由于某些原因,第一次渲染时数据没有显示在组件上。关键是,如果单击按钮刷新数据,则加载的数据就很好。无论哪种方式我都没有收到错误消息,所以我认为我一定在误解了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 个答案:

答案 0 :(得分:0)

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;
  });

答案 1 :(得分:0)

我知道了!

代码问题在下面的行中:

self = this;

在第一次运行代码时(而且是第一次),它在寻找错误的上下文。替换为

let self = this;

问题已经解决。

我有时讨厌计算机,它们总是按照我的意思而不是我的意思!