从VueJS中的“内联模板”调用Component方法

时间:2019-02-28 16:09:11

标签: javascript laravel vue.js

VueJS 版本1.9.0

app.js

require('./bootstrap');
window.Vue = require('vue');

Vue.component('mapbox', require('./components/mapbox.js'));

const app = new Vue({
    el: '#app'
});

components / mapbox.js

// initially from https://github.com/phegman/vue-mapbox-gl/blob/master/src/components/Mapbox.vue
export default {
    data() {
        return {
            _map: null
        };
    },
    props: {
        accessToken: {
            type: String,
            required: true
        },
        mapOptions: {
            type: Object,
            required: true
        },
        navControl: {
            type: Object,
            default: () => {
                return {
                    show: true,
                    position: 'top-right'
                };
            }
        },
        geolocateControl: {
            type: Object,
            default: () => {
                return {
                    show: false,
                    position: 'top-left',
                    options: {}
                };
            }
        },
        scaleControl: {
            type: Object,
            default: () => {
                return {
                    show: false,
                    position: 'top-left',
                    options: {}
                };
            }
        },
        fullscreenControl: {
            type: Object,
            default: () => {
                return {
                    show: false,
                    position: 'top-right'
                };
            }
        }
    },
    mounted() {
        const map = this.mapInit();
        this._map = map;
        this.registerEvents(map);
    },
    methods: {
        mapClicked(map, e) {
            console.log("clicked");
        },
        mapInit() {
            mapboxgl.accessToken = this.accessToken;
            if (!this.mapOptions.hasOwnProperty('container')) {
                this.mapOptions.container = 'map';
            }
            const map = new mapboxgl.Map(this.mapOptions);
            this.$emit('map-init', map);
            return map;
        },
        registerEvents(map) {
            map.on('load', () => {
                this.$emit('map-load', map);
            });
            map.on('click', e => {
                this.$emit('map-click', map, e);
            });
            map.on('render', () => {
                this.$emit('map-render', map);
            });
        }
    },
    beforeDestroy() {
        this._map.remove();
    }
};

index.blade.php

<mapbox 
    access-token="MY-ACCESS-TOKEN"

    :map-options="{
      style: 'mapbox://styles/mapbox/light-v9',
      center: [-96, 37.8],
      zoom: 3
    }"
    :geolocate-control="{
      show: true,
      position: 'top-left'
    }"
    :scale-control="{
      show: true,
      position: 'top-left'
    }"
    :fullscreen-control="{
      show: true,
      position: 'top-left'
    }"

    @map-click="mapClicked"

    inline-template>

        <div id="map"></div>

</mapbox>

index.blade.php 中,我试图调用 components / mapbox.js 方法中的@map-click="mapClicked"

但是我遇到了错误

  

▶app.js:36934 [Vue警告]:属性或方法“ mapClicked”未在实例上定义,但在渲染期间被引用。通过初始化属性,确保在data选项中或对于基于类的组件,此属性都是反应性的。参见:https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties

     

▶[Vue警告]:事件“ map-click”的无效处理程序:未定义

  1. 我知道是否将mapClicked移至 app.js const app = new Vue({el: '#app', methods: {mapClicked(){..}}});可以工作,但我希望文件干净,并尽量避免这种解决方案。
  2. 我读了这样的文字:Vue inline template not finding methods or data,但它对我不起作用。

1 个答案:

答案 0 :(得分:1)

inline-template属性添加到组件的标签时,组件标签中 内的所有内容都将用作组件的模板,并且作用域仅限于组件的Vue实例。但是,标签本身仍然限于父级。因此,警告告诉您,正如预期的那样,父组件没有mapClicked方法。

您应该只在mapClicked方法中设置的点击处理程序中调用registerEvents方法:

map.on('click', e => {
  this.mapClicked(map, e);
  this.$emit('map-click', map, e);
});