计算属性不评估何时加载组件

时间:2018-03-12 15:36:19

标签: javascript vue.js vuejs2 vue-component

我有一个正在初始化谷歌地图的maps组件,根据从父项传递的道具为该地图添加标记,然后设置地图的正确边界。但是,这些标记是通过计算属性添加的,因为我希望它是反应性的。实际上一切都运行良好,除了我的计算属性中的addMarkers函数似乎没有在页面和因此加载组件时进行评估。

现在奇怪的是:当我打开Vue Devtools并点击maps组件时,addMarkers会立即评估并正确更改地图。

任何帮助高度赞赏:-)

<template lang="pug" >

div.google-map(id="results-map")

</template>
<script>

import Gmaps from 'gmaps';

export default {
    name: 'maps',
    props: {
        results: {
            type: Array,
            required: true
        }
    },
    data() {
        return {
            map: {},
            bounds: {}
        }
    },
    computed: {
        addMarkers() {
            this.results.forEach((result) => {
                if (result.latitude && result.longitude) {
                    var marker = this.map.addMarker({
                        lat: result.latitude,
                        lng: result.longitude,
                        title: result.name,
                        infoWindow: {
                            content: result.name
                        }
                    });
                }
                this.bounds.extend(marker.position)
            });
            this.map.fitBounds(this.bounds)
        }
    },
    mounted() {
        this.map = new Gmaps({
            div: '#results-map',
            lat: 0,
            lng: 0,
            zoom: 15
        });
        this.bounds = new google.maps.LatLngBounds();
    }
}
</script>

3 个答案:

答案 0 :(得分:0)

您没有在任何地方使用addMarkers计算属性。我想您希望将其更改为方法,并在mounted函数中调用它。

答案 1 :(得分:0)

由于您要对results外部更改您的组件做出反应:

  • addMarkers()计算属性转换为results上的观察者

每当results道具更改时,这将确保代码执行

此外,由于您在mounted()挂钩中运行了一些DOM操作逻辑:

  • results监视的逻辑包含在Vue.nextTick()内,以确保在DOM准备好更改时执行(也就是在配置<google-maps>之后):
  

Vue.nextTick():将回调推迟到下一个DOM更新周期后执行。在更改了一些数据以等待DOM更新后立即使用它。

因此,您的手表(曾经是addMarkers()计算属性)会变为:

watch: {                                                                 // line changed
    results: {                                                           // line changed
        deep: true,                                                      // line changed
        handler () {                                                     // line changed
            Vue.nextTick(() => {                                         // line changed
                this.results.forEach((result) => {
                    if (result.latitude && result.longitude) {
                        var marker = this.map.addMarker({
                            lat: result.latitude,
                            lng: result.longitude,
                            title: result.name,
                            infoWindow: {
                                content: result.name
                            }
                        });
                    }
                    this.bounds.extend(marker.position)
                });
                this.map.fitBounds(this.bounds)
            });                                                         // line changed
        }                                                               // line changed
    }
},

答案 2 :(得分:0)

addMarkers没有返回任何值时,计算属性应该返回值

此外,计算属性仅在您需要时计算。因此,在创建组件时未显示标记的事实是计算属性从不需要。

但是,当您打开开发工具时,VueJS会尝试评估该计算属性并执行代码。并且您的代码添加了标记,但它不是计算属性。

所以你在这里有不同的解决方案。

要么尝试在mounted挂钩上强制计算您的计算属性:

mounted() {
    this.map = new Gmaps({
        div: '#results-map',
        lat: 0,
        lng: 0,
        zoom: 15
    });
    this.bounds = new google.maps.LatLngBounds();
    this.addMarkers
}

或者您可以创建addMarkers的方法并随时执行它:

import Gmaps from 'gmaps';

export default {
    name: 'maps',
    props: {
        results: {
            type: Array,
            required: true
        }
    },
    data() {
        return {
            map: {},
            bounds: {}
        }
    },
    methods: {
        addMarkers() {
            this.results.forEach((result) => {
                if (result.latitude && result.longitude) {
                    var marker = this.map.addMarker({
                        lat: result.latitude,
                        lng: result.longitude,
                        title: result.name,
                        infoWindow: {
                            content: result.name
                        }
                    });
                }
                this.bounds.extend(marker.position)
            });
            this.map.fitBounds(this.bounds)
        }
    },
    mounted() {
        this.map = new Gmaps({
            div: '#results-map',
            lat: 0,
            lng: 0,
            zoom: 15
        });
        this.bounds = new google.maps.LatLngBounds();
        this.addMarkers()
    }
}

例如,如果您想在更改results时重新渲染标记,则可以使用watch属性:

export default {
    ...
    watch: {
        results: {
            deep: true,
            handler () {
                this.addMarkers()
            }
        }
    }
}