在尝试在Vue.js中对其进行任何操作之前,如何确保要操作的DOM元素已加载?

时间:2019-04-15 16:09:16

标签: javascript vue.js vuejs2

从昨天开始,我一直在与这个问题作斗争,而且我机智。当前,我在vue文件中有一个方法可以做到这一点:

methods: {
    showSlides(n) {
        let slides = document.getElementsByClassName("mySlides");

        slides[0].style.display = "block";
    }
},
mounted(){
    this.showSlides();
}

它找到所有具有“ mySlides”类的元素,将它们存储在变量中,然后尝试更改第一个元素的样式。组件mount()时将调用此函数。

现在,问题是我得到一个错误,指出"TypeError: Cannot read property 'style' of undefined"。事实证明,在执行此功能时,这些DOM元素是未定义的。我通过向按钮添加@click='showSlide()'事件来实现这一点。当我单击按钮时,该函数成功运行,但是,当安装mount()时,该函数却无法运行。

该代码还可以在纯HTML文件中成功运行,该HTML文件的脚本位于页面底部。这就是让我相信有些可疑的事情正在发生。

完整代码:

<template>
    <div class="wrapper">
        <div class="sight-container">
            <p class='sight-name'>{{ sight.name }}</p>
            <p>{{ sight.formatted_address }}</p>
            <p>{{ sight.formatted_phone_number }}</p>
            <p>{{ sight.international_phone_number }}</p>
            <p>{{ sight.website }}</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="'https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + '&key='">
                </div>

                <a class="prev" @click='plusSlides(-1)'>❮</a>
                <a class="next" @click='plusSlides(1)'>❯</a>

                <div class="caption-container">
                    <p id="caption"></p>
                </div>

                <div class="row">
                    <div v-for='(image, index) in sightImages' class="column">
                      <img class="demo cursor" :src="'https://maps.googleapis.com/maps/api/place/photo?maxwidth=1920&photoreference=' + image.photo_reference + '&key='" style="width:100%" @click="currentSlide(1)">
                    </div>
                </div>
            </div>


        </div>
    </div>
</template>

<script>
    import axios from 'axios'

    export default {
        data(){
            return {
                placeId: this.$route.params.placeid,
                sight: "",
                sightImages: [],
                slideIndex: 1
            }
        },
        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", "");
                }

                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);
            }
        },
        mounted(){
            axios.get('/getSight/' + this.placeId)
            .then(response => {
                this.sight = response.data.result.result
                this.sightImages = response.data.result.result.photos
            }).catch((error) => console.log(error));

            this.showSlides(this.slideIndex);
        }
    }
</script>

1 个答案:

答案 0 :(得分:1)

那是因为您使用错误。

通常,mounted在渲染组件的DOM之后称为,此时组件的this.$el就可以使用了。

但是,在mounted中,您要调用异步操作,该操作会在完成后更新data(及更高版本的DOM),但是您尝试使用其结果 发生了。

应该是这样的:

mounted() {
  axios.get('/getSight/' + this.placeId)
       .then(response => {
         this.sight = response.data.result.result;
         this.sightImages = response.data.result.result.photos;
         this.$nextTick(() => {
           this.showSlides(this.slideIndex);
         });
       }).catch((error) => console.log(error));
}

小提示:您可以使用el.className += ...el.className.replace(...)来代替el.classList.add(...)el.classList.remove(...)

文档:Element.classList