【问题标题】:Computed property not evaluating when component is loaded加载组件时计算属性未评估
【发布时间】:2018-08-20 16:48:21
【问题描述】:

我有一个 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>

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    计算属性应该返回一个值,而您的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()
                }
            }
        }
    }
    

    【讨论】:

    • 为您的详细回答干杯,就像一个魅力。我不知道计算属性总是应该返回一个值——我还是 Vue 的新手!
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      因为你想对results外部你的组件变化做出反应:

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

      这将确保代码在每次results 属性更改执行

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

      • results 手表的逻辑包装在Vue.nextTick() 中,以确保它在准备好更改DOM 时执行(也就是在您配置&lt;google-maps&gt; 之后):

      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
          }
      },
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-12
        • 2018-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-03
        • 2019-10-22
        • 1970-01-01
        相关资源
        最近更新 更多