导入Vue JS组件会引发“未捕获的SyntaxError:意外的标识符". [英] Importing Vue JS component raises "Uncaught SyntaxError: Unexpected identifier"

查看:419
本文介绍了导入Vue JS组件会引发“未捕获的SyntaxError:意外的标识符".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Vue.js还是很陌生,我正在尝试在我的Django项目中使用它.我需要导入vue-google-autocomplete,但是出现以下错误:

I'm quite new to Vue.js and I'm trying to use it in my Django project. I need to import vue-google-autocomplete but i receive the following error:

 "Uncaught SyntaxError: Unexpected identifier"

问题出在这一行:

import VueGoogleAutocomplete from 'vue-google-autocomplete'

我不使用任何软件包管理器(例如npm),而我尝试仅使用html来导入库.

I don't use any package managers (like npm) and I'm trying to use just html to import libraries.

这是代码:

    <script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places&callback=onLoaded&language=sk&region=SR"
            async defer></script>

    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue-google-autocomplete@1.1.0/src/VueGoogleAutocomplete.vue" type="application/octet-stream"></script>
    <script>

        import VueGoogleAutocomplete from 'vue-google-autocomplete'

        Vue.component('vue-google-autocomplete', VueGoogleAutocomplete);
        var app = new Vue({
            delimiters: ['[[', ']]'],
            el: '#app',
            data: {
                address: '',
                business_type_text: '',
            },
            methods: {
               ....
            }
        });
    </script>

编辑

我创建了一个新文件create.js,该文件在vue.js和自动完成CDN之后导入,但仍然会引发错误:

I've created a new file create.js which I import after vue.js and the autocomplete cdn but it still raises an error:

推荐答案

您不能从外部URL导入/加载.vue文件.

You can't import/load a .vue file from an external url.

干净的方法是将.vue文件保存在您的项目中,并将其导入您选择的组件中:

The clean way of doing it would be to save the .vue file in your project and import it into the component of your choice:

import VueGoogleAutocomplete from './VueGoogleAutocomplete.vue'
// assuming you save the .vue file as VueGoogleAutocomplete.vue, 
// in the same folder with the parent component.

,并且在组件的components中:

components: { VueGoogleAutocomplete }

此处中查看工作示例.如果您在public/index.html中使用有效的API密钥,则可以使用.

See a working example here. Works if you use a valid API key in public/index.html.

我将文件导入到/App.vue中并保存到components/VueGoogleAutocomplete.vue中.

I imported the file into /App.vue and saved it into components/VueGoogleAutocomplete.vue.

另一件事:如果在maps js链接上使用async,则您的.vue组件将抱怨google对象未定义.基本上,您要一直挂载VueGoogleAutocomplete,直到地图js加载完毕(使用v-if和helper模型属性,或者不要在地图js脚本上使用async).

One more thing: if you use async on the maps js link, your .vue component will complain about google object not being defined. Basically, you want to hold mounting VueGoogleAutocomplete until the maps js has loaded (use a v-if and a helper model property, or don't use async on the maps js script).

如果要在单个文件中执行此操作,请按以下步骤操作(基本上定义一个 在Vue.component中复制并粘贴.vue的内容(包括模板).由于您是在全局Vue实例上定义的,因此无需在components中声明它就可以使用它:

If you want to do it in a single file, here's how to do it (basically define a Vue.component in which you copy-paste the contents of the .vue, including the template). Since you define it on the global Vue instance, it's available without declaring it in components:

Vue.config.productionTip = false;
Vue.config.devtools = false;

const ADDRESS_COMPONENTS = {
  street_number: "short_name",
  route: "long_name",
  locality: "long_name",
  administrative_area_level_1: "short_name",
  administrative_area_level_2: "county",
  country: "long_name",
  postal_code: "short_name"
};

const CITIES_TYPE = ["locality", "administrative_area_level_3"];
const REGIONS_TYPE = [
  "locality",
  "sublocality",
  "postal_code",
  "country",
  "administrative_area_level_1",
  "administrative_area_level_2"
];

Vue.component('vue-google-autocomplete', {
  name: "VueGoogleAutocomplete",
  template: `<input
    ref="autocomplete"
    type="text"
    :class="classname"
    :id="id"
    :placeholder="placeholder"
    v-model="autocompleteText"
    @focus="onFocus()"
    @blur="onBlur()"
    @change="onChange"
    @keypress="onKeyPress"
    @keyup="onKeyUp"
  >`,
  props: {
    id: {
      type: String,
      required: true
    },

    classname: String,

    placeholder: {
      type: String,
      default: "Start typing"
    },

    types: {
      type: String,
      default: "address"
    },

    country: {
      type: [String, Array],
      default: null
    },

    enableGeolocation: {
      type: Boolean,
      default: false
    },

    geolocationOptions: {
      type: Object,
      default: null
    }
  },

  data() {
    return {
      /**
       * The Autocomplete object.
       *
       * @type {Autocomplete}
       * @link https://developers.google.com/maps/documentation/javascript/reference#Autocomplete
       */
      autocomplete: null,

      /**
       * Autocomplete input text
       * @type {String}
       */
      autocompleteText: "",

      geolocation: {
        /**
         * Google Geocoder Objet
         * @type {Geocoder}
         * @link https://developers.google.com/maps/documentation/javascript/reference#Geocoder
         */
        geocoder: null,

        /**
         * Filled after geolocate result
         * @type {Coordinates}
         * @link https://developer.mozilla.org/en-US/docs/Web/API/Coordinates
         */
        loc: null,

        /**
         * Filled after geolocate result
         * @type {Position}
         * @link https://developer.mozilla.org/en-US/docs/Web/API/Position
         */
        position: null
      }
    };
  },

  watch: {
    autocompleteText: function(newVal, oldVal) {
      this.$emit("inputChange", { newVal, oldVal }, this.id);
    },
    country: function(newVal, oldVal) {
      this.autocomplete.setComponentRestrictions({
        country: this.country === null ? [] : this.country
      });
    }
  },

  mounted: function() {
    const options = {};

    if (this.types) {
      options.types = [this.types];
    }

    if (this.country) {
      options.componentRestrictions = {
        country: this.country
      };
    }

    this.autocomplete = new google.maps.places.Autocomplete(
      document.getElementById(this.id),
      options
    );

    this.autocomplete.addListener("place_changed", this.onPlaceChanged);
  },

  methods: {
    /**
     * When a place changed
     */
    onPlaceChanged() {
      let place = this.autocomplete.getPlace();

      if (!place.geometry) {
        // User entered the name of a Place that was not suggested and
        // pressed the Enter key, or the Place Details request failed.
        this.$emit("no-results-found", place, this.id);
        return;
      }

      if (place.address_components !== undefined) {
        // return returnData object and PlaceResult object
        this.$emit("placechanged", this.formatResult(place), place, this.id);

        // update autocompleteText then emit change event
        this.autocompleteText = document.getElementById(this.id).value;
        this.onChange();
      }
    },

    /**
     * When the input gets focus
     */
    onFocus() {
      this.biasAutocompleteLocation();
      this.$emit("focus");
    },

    /**
     * When the input loses focus
     */
    onBlur() {
      this.$emit("blur");
    },

    /**
     * When the input got changed
     */
    onChange() {
      this.$emit("change", this.autocompleteText);
    },

    /**
     * When a key gets pressed
     * @param  {Event} event A keypress event
     */
    onKeyPress(event) {
      this.$emit("keypress", event);
    },

    /**
     * When a keyup occurs
     * @param  {Event} event A keyup event
     */
    onKeyUp(event) {
      this.$emit("keyup", event);
    },

    /**
     * Clear the input
     */
    clear() {
      this.autocompleteText = "";
    },

    /**
     * Focus the input
     */
    focus() {
      this.$refs.autocomplete.focus();
    },

    /**
     * Blur the input
     */
    blur() {
      this.$refs.autocomplete.blur();
    },

    /**
     * Update the value of the input
     * @param  {String} value
     */
    update(value) {
      this.autocompleteText = value;
    },

    /**
     * Update the coordinates of the input
     * @param  {Coordinates} value
     */
    updateCoordinates(value) {
      if (!value && !(value.lat || value.lng)) return;
      if (!this.geolocation.geocoder)
        this.geolocation.geocoder = new google.maps.Geocoder();
      this.geolocation.geocoder.geocode(
        { location: value },
        (results, status) => {
          if (status === "OK") {
            results = this.filterGeocodeResultTypes(results);
            if (results[0]) {
              this.$emit(
                "placechanged",
                this.formatResult(results[0]),
                results[0],
                this.id
              );
              this.update(results[0].formatted_address);
            } else {
              this.$emit("error", "no result for provided coordinates");
            }
          } else {
            this.$emit("error", "error getting address from coords");
          }
        }
      );
    },

    /**
     * Update location based on navigator geolocation
     */
    geolocate() {
      this.updateGeolocation((geolocation, position) => {
        this.updateCoordinates(geolocation);
      });
    },

    /**
     * Update internal location from navigator geolocation
     * @param  {Function} (geolocation, position)
     */
    updateGeolocation(callback = null) {
      if (navigator.geolocation) {
        let options = {};
        if (this.geolocationOptions)
          Object.assign(options, this.geolocationOptions);
        navigator.geolocation.getCurrentPosition(
          position => {
            let geolocation = {
              lat: position.coords.latitude,
              lng: position.coords.longitude
            };
            this.geolocation.loc = geolocation;
            this.geolocation.position = position;

            if (callback) callback(geolocation, position);
          },
          err => {
            this.$emit("error", "Cannot get Coordinates from navigator", err);
          },
          options
        );
      }
    },

    // Bias the autocomplete object to the user's geographical location,
    // as supplied by the browser's 'navigator.geolocation' object.
    biasAutocompleteLocation() {
      if (this.enableGeolocation) {
        this.updateGeolocation((geolocation, position) => {
          let circle = new google.maps.Circle({
            center: geolocation,
            radius: position.coords.accuracy
          });
          this.autocomplete.setBounds(circle.getBounds());
        });
      }
    },

    /**
     * Format result from Geo google APIs
     * @param place
     * @returns {{formatted output}}
     */
    formatResult(place) {
      let returnData = {};
      for (let i = 0; i < place.address_components.length; i++) {
        let addressType = place.address_components[i].types[0];

        if (ADDRESS_COMPONENTS[addressType]) {
          let val =
            place.address_components[i][ADDRESS_COMPONENTS[addressType]];
          returnData[addressType] = val;
        }
      }

      returnData["latitude"] = place.geometry.location.lat();
      returnData["longitude"] = place.geometry.location.lng();
      return returnData;
    },

    /**
     * Extract configured types out of raw result as
     * Geocode API does not allow to do it
     * @param results
     * @returns {GeocoderResult}
     * @link https://developers.google.com/maps/documentation/javascript/reference#GeocoderResult
     */
    filterGeocodeResultTypes(results) {
      if (!results || !this.types) return results;
      let output = [];
      let types = [this.types];
      if (types.includes("(cities)")) types = types.concat(CITIES_TYPE);
      if (types.includes("(regions)")) types = types.concat(REGIONS_TYPE);

      for (let r of results) {
        for (let t of r.types) {
          if (types.includes(t)) {
            output.push(r);
            break;
          }
        }
      }
      return output;
    }
  }
});

new Vue({
  el: '#app',
  methods: {
    getAddressData(result, place, id) {
      console.log('getAddressData was called with:', {result, place, id});
    }
  }
})

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY_HERE&libraries=places"></script>

<div id="app">
  <vue-google-autocomplete
    id="map"
    class="form-control"
    placeholder="Start typing"
    @placechanged="getAddressData"
    :country="['ie']"
  />
</div>

注意:仅适用于有效的API密钥.

Note: only works with a valid API key.

文档中概述的方法,而不是使用Vue.component()您还可以使用普通的JavaScript对象:

As outlined in the docs, instead of using Vue.component() you can also use a plain JavaScript object:

const ADDRESS_COMPONENTS = { 
   //same as above...
};
const CITIES_TYPE = [
   // same...
];
const REGIONS_TYPE = [
   // same...
];
let VueGoogleAutocomplete = {
  // exactly same contents from above, in the `Vue.component()` call...
}

new Vue.app({
  el: '#app',
  components: { VueGoogleAutocomplete }
})

请注意,在注册组件之前,必须先声明vue组件使用的const(在.vue文件中不会导出),因为该组件在内部使用它们.

Note the consts used by the vue component (which in the .vue file are not exported), need to be declared before you register the component, as the component uses them internally.

这篇关于导入Vue JS组件会引发“未捕获的SyntaxError:意外的标识符".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆