javascript - VueJS子组件不渲染数据

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

请原谅上面转储的代码量,我不确定我可以/应该删除哪些内容以使问题更简短。

任何人都可以告诉我如何在该组件首次加载时自动加载数据吗?

提前非常感谢。

最佳答案

mounted 钩子(Hook)是异步的,这使得这种情况变得棘手。

<小时/> <小时/>

与您尝试执行的操作类似的示例..

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

关于javascript - VueJS子组件不渲染数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56200816/

相关文章:

javascript - 如何匹配/捕获元素的outerHTML 的开始标签

javascript - Google Maps API v3 - 地理编码器结果有边界问题

javascript - 使用 Vue.js 设置数据

javascript - VueJS - "npm run build"不在 dist 文件夹中生成 index.html 文件

javascript - 如何使用 v-for 在每个元素中呈现不同的 CSS 类

html - 如何在vue js html中倒序显示json数据?

javascript - 无法使用 jQuery 将 HTML 代码附加到一个 div

javascript - 使用 jQuery Mobile 在 Intel XDK 上显示灰色 Google map

vue.js - Vuetify 2.0 : How can I achieve this layout from Vuetify 1. 5?

javascript - Vue.js Safari 移动和兼容性