导入Vue JS组件会引发“未捕获的SyntaxError:意外的标识符". [英] Importing Vue JS component raises "Uncaught SyntaxError: Unexpected identifier"
问题描述
我对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®ion=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 const
s 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屋!