导入Vue JS组件会引发“未捕获的SyntaxError:意外的标识符”

时间:2019-09-21 11:38:52

标签: javascript html vue.js

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

 "Uncaught SyntaxError: Unexpected identifier"

问题出在这一行:

import VueGoogleAutocomplete from 'vue-google-autocomplete'

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

这是代码:

    <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之后导入,但是仍然会引发错误:

enter image description here

2 个答案:

答案 0 :(得分:0)

尝试

Vue.use(vue-google-autocomplete)

您可能需要替换名称。

JavaScript解释器无法识别

import。需要先进行编译。

如果要使用import,则必须创建一个文件(即main.js),并将其包含在HTML文件中,如下所示:

<script type="module" src="main.js"></ 

答案 1 :(得分:0)

您无法从外部网址导入/加载.vue文件。

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

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 }

请参见有效示例here。如果您在public/index.html中使用有效的API密钥,则可以使用。

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

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


如果要在单个文件中执行此操作,请按以下步骤操作(基本上定义一个 在Vue.component中复制粘贴.vue的内容(包括模板)。由于您是在全局Vue实例上定义的,因此无需在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密钥。


the docs中所述,除了使用Vue.component()之外,您还可以使用普通的JavaScript对象:

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文件中不会导出),因为该组件在内部使用它们。