首页 > 解决方案 > VueJS - 无法读取未定义的属性

问题描述

我正在尝试通过他们的 API 加载 Youtube 视频,为了获得持续时间,我必须发送第二个 API 请求。我遇到的问题是,有时这段代码有效,有时会抛出

Error in render: "TypeError: Cannot read property 'contentDetails' of undefined"

我认为这是因为当 Vue 尝试访问该属性时,它不存在。如果我在加载失败时使用 Vue Developer 工具访问变量 (resolvedVideoData),它只解析了一个视频。

我究竟做错了什么?我在 created() 中调用 API 查询,所以 DOM 还没有加载?


<script>
import axios from 'axios';
import moment from 'moment'

export default {
    name: 'BlogGrid',
    data(){
        return {
          videos:[],
          base_url_youtube: 'http://www.youtube.com/watch?v=',
          videoId: [],
          resolvedVideoData: [],    
        }
    },
    watch: {
        videos: function (){
           var arrayLength = this.videos.length;
            for (var i = 0; i < arrayLength; i++) {
              this.videoId.push(this.videos[i].id.videoId); 
            }
            this.getVideoDuration()
      }
  },
    created() {
      axios.get(`https://www.googleapis.com/youtube/v3/search?key={{YOUTUBE_API_KEY}}&channelId={{ChannelID}}A&order=date&part=snippet%20&type=video,id&maxResults=50`)
        .then(response => {
          this.videos = response.data.items
  })
  .catch(e => {
    this.errors.push(e)
  })
},
  methods: {
       getVideoDuration(){
        axios.get('https://www.googleapis.com/youtube/v3/videos?id=' + this.videoId.join(', ') + '&part=contentDetails&key={{YOUTUBE_API_KEY}}')
        .then(response => {
          this.resolvedVideoData = response.data.items
  })
  .catch(e => {
    this.errors.push(e)
  })
 }
 }
}
</script>

进一步检查后,如果我为 Google API 生成的 URL 发送垃圾邮件,有时它似乎返回一个值,有时它返回所有值。

既然被要求

 <section class="blog-area ptb-80">
      <div class="container">
        <div class="row">
          <div
            v-for="(item, index) in videos"
            :key="item.etag"
            class="col-lg-4 col-md-6"
          >
            <div class="single-blog-post">
              <div
                class="blog-image"
                :href="base_url_youtube + item.id.videoId "
              >
                <a :href="base_url_youtube + item.id.videoId ">
                  <img
                    :src="item.snippet.thumbnails.high.url"
                    name="videoicon"
                    alt="image"
                  ></a>
                <a :href="base_url_youtube + item.id.videoId ">
                  <div class="overlay hidden-sm">
                    <div class="text">
                      {{ parseDuration(resolvedVideoData[index].contentDetails.duration) }}
                      <br>
                      <a :href="base_url_youtube + item.id.videoId"> <feather type="monitor" /></a>
                    </div>
                  </div>

                </a>
                <div class="date">
                  <feather type="calendar" />
                  {{ format_date(item.snippet.publishedAt ) }}
                </div>
                <div class="blog-post-content">
                  {{ item.snippet.title }}
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>

与我的其他方法一样。

format_date(value){
          if (value) {
            return moment(String(value)).format('DD-MM-YYYY')
           }
       },
parseDuration(e){
    var n = e.replace(/D|H|M/g,":").replace(/P|T|S/g,"").split(":");

    if(1 == n.length)
        2!=n[0].length && (n[0]="0"+n[0]),n[0]="0:"+n[0];
    else 
        for(var r=1, l=n.length-1; l>=r;r++)
            2!=n[r].length && (n[r]="0"+n[r]);

    return n.join(":")
},

标签: javascriptvue.jsyoutubeaxios

解决方案


推荐阅读