实现 vue-router 后 Vue.js 不工作
Posted
技术标签:
【中文标题】实现 vue-router 后 Vue.js 不工作【英文标题】:Vue.js not working after vue-router is implemented 【发布时间】:2020-07-24 11:41:03 【问题描述】:这是我用来尝试创建单页应用程序的代码。我正在阅读有关 vue 路由器的信息,并尝试将其应用到我的项目中。我不确定代码有什么问题,但我看不到应用程序运行的页面。我在 chrom 控制台上遇到了一些错误,但这是在我将 vue 路由器添加到我的项目之后发生的。有什么解决办法吗?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""/>
<link href="https://fonts.googleapis.com/css2?family=Courgette&display=swap" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js" integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew==" crossorigin=""></script>
<title>C safe!</title>
</head>
<body>
<style>
h1
font-family: 'Courgette', cursive;
.list-group
max-height: 300px;
margin-bottom: 10px;
overflow:scroll;
-webkit-overflow-scrolling: touch;
#map
height: 400px;
</style>
<div class="container-fluid bg-light p-0" id="app">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 p-5">
<ul class="nav">
<router-link to="/">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
</router-link>
</ul>
</div>
</div>
<script type="text/x-template" id="search-bar">
<div class="row justify-content-center m-0" style="height:100vh;">
<div class="col-sm-12 col-md-8 col-lg-8 p-5 mx-auto">
<h1 class="mt-5 mb-3 text-center">C</h1>
<div class="input-group">
<input type="email" class="form-control rounded-0" v-on:change="instantSearch()" v-model="q" placeholder="Cerca nelle vicinanze es: Pizzeria">
<div class="input-group-append">
<button class="btn btn-outline-success rounded-0" v-on:click="instantSearch()">Cerca</button>
</div>
</div>
<ul v-if="resultSet" class="list-group rounded-0">
<small v-if="q" class="list-group-item rounded-0"><a class="text-muted" href="#" v-on:click="resetSearch()">Annulla</a></small>
<router-link to="/results">
<a v-for="result in resultSet" :key="result.id" v-on:click="expandMap(result.lat, result.lon)" href="#" class="list-group-item rounded-0" :place="result.display_name"> result.display_name </a>
</router-link>
</ul>
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">FAQ</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Aggiungi la tua attività</a>
</li>
</ul>
</div>
</div>
</script>
<script type="text/x-template" id="result-detail">
<div class="collapse" id="map-collapsable">
<div class="row m-0 results-map">
<div class="col-sm-12 col-md-8 col-lg-8 p-0" id="map"></div>
<div v-for="place in placeData" class="col-sm-12 col-md-4 col-lg-4">
place.lat place.lng
</div>
</div>
</div>
</script>
<router-view></router-view>
</div>
<!-- TODO: Vue components -->
<script src="app.js"></script>
</body>
</html>
这是 JS vue 代码
window.onload = function()
Vue.component('search-bar',
template: '#search-bar',
data()
return
);
Vue.component('view-result',
template: '#result-detail',
data()
return
);
const searchbar = template: 'search-bar'
const result = template: 'view-result'
const routes = [
path: '/', component: searchbar,
path: '/results', component: result
];
const router = new VueRouter(
routes // short for `routes: routes`
);
const web = new Vue(
router,
el: '#app',
data:
pageData: [],
resultSet: [],
placeData: [],
q: '',
name: '',
,
mounted: function()
//this.initPage();
,
ready: function()
,
computed:
,
watch:
q: function(val, oldVal)
this.instantSearch();
,
methods:
instantSearch: function()
axios.get('https://nominatim.openstreetmap.org/search?q='+this.q+'&format=json').then( (places) =>
console.log(places);
this.resultSet = [];
places.data.forEach( (item, i) =>
this.resultSet.push(item);
);
);
,
resetSearch: function()
this.resultSet = [];
this.q = '';
,
expandMap: function(lat, lng)
let collapsable = document.getElementById('map-collapsable');
console.log(lat, lng);
//$(collapsable).collapse();
this.placeData.push(lat: lat, lng: lng);
,
initMap: function(data)
).$mount('#app');
我得到的错误如下:
vue.js:634 [Vue warn]: Property or method "result" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in <Root>)
warn @ vue.js:634
warnNonPresent @ vue.js:2047
has @ vue.js:2092
eval @ VM258:3
Vue._render @ vue.js:3551
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
Vue._init @ vue.js:5012
Vue @ vue.js:5078
window.onload @ app.js:28
load (async)
(anonymous) @ app.js:1
vue.js:634 [Vue warn]: Error in render: "TypeError: Cannot read property 'display_name' of undefined"
(found in <Root>)
warn @ vue.js:634
logError @ vue.js:1893
globalHandleError @ vue.js:1888
handleError @ vue.js:1848
Vue._render @ vue.js:3553
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
Vue._init @ vue.js:5012
Vue @ vue.js:5078
window.onload @ app.js:28
load (async)
(anonymous) @ app.js:1
vue.js:1897 TypeError: Cannot read property 'display_name' of undefined
at Proxy.eval (eval at createFunction (vue.js:11649), <anonymous>:3:1557)
at Vue._render (vue.js:3551)
at Vue.updateComponent (vue.js:4067)
at Watcher.get (vue.js:4478)
at new Watcher (vue.js:4467)
at mountComponent (vue.js:4074)
at Vue.$mount (vue.js:9044)
at Vue.$mount (vue.js:11944)
at Vue._init (vue.js:5012)
at new Vue (vue.js:5078)
logError @ vue.js:1897
globalHandleError @ vue.js:1888
handleError @ vue.js:1848
Vue._render @ vue.js:3553
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
Vue._init @ vue.js:5012
Vue @ vue.js:5078
window.onload @ app.js:28
load (async)
(anonymous) @ app.js:1
vue.js:634 [Vue warn]: Cannot find element: #app
warn @ vue.js:634
query @ vue.js:5666
Vue.$mount @ vue.js:11882
window.onload @ app.js:83
load (async)
(anonymous) @ app.js:1
vue.js:634 [Vue warn]: Property or method "result" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in <Root>)
warn @ vue.js:634
warnNonPresent @ vue.js:2047
has @ vue.js:2092
eval @ VM258:3
Vue._render @ vue.js:3551
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
window.onload @ app.js:83
load (async)
(anonymous) @ app.js:1
vue.js:634 [Vue warn]: Error in render: "TypeError: Cannot read property 'display_name' of undefined"
(found in <Root>)
warn @ vue.js:634
logError @ vue.js:1893
globalHandleError @ vue.js:1888
handleError @ vue.js:1848
Vue._render @ vue.js:3553
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
window.onload @ app.js:83
load (async)
(anonymous) @ app.js:1
vue.js:1897 TypeError: Cannot read property 'display_name' of undefined
at Proxy.eval (eval at createFunction (vue.js:11649), <anonymous>:3:1557)
at Vue._render (vue.js:3551)
at Vue.updateComponent (vue.js:4067)
at Watcher.get (vue.js:4478)
at new Watcher (vue.js:4467)
at mountComponent (vue.js:4074)
at Vue.$mount (vue.js:9044)
at Vue.$mount (vue.js:11944)
at window.onload (app.js:83)
logError @ vue.js:1897
globalHandleError @ vue.js:1888
handleError @ vue.js:1848
Vue._render @ vue.js:3553
updateComponent @ vue.js:4067
get @ vue.js:4478
Watcher @ vue.js:4467
mountComponent @ vue.js:4074
Vue.$mount @ vue.js:9044
Vue.$mount @ vue.js:11944
window.onload @ app.js:83
load (async)
(anonymous) @ app.js:1
我不知道为什么,但在我创建组件并尝试使用 vue-router 之前,一切正常。
【问题讨论】:
【参考方案1】:有几个问题:
script type=text/x-template
s 需要移出app
div
。否则,模板将作为app
模板的一部分进行处理,从而导致您在控制台中观察到undefined
错误。
由于你的 Vue 声明已经指定了el: #app
,你需要删除.$mount('#app')
。
路由路径在 template: 'search-bar'
和 template: 'result-detail'
中错误地指定了文字字符串模板。那应该分别是 template: '<search-bar />'
和 template: '<result-detail />'
。
q
和 resultSet
数据属性应该移动到 search-bar
组件中。同样,placeData
数据属性应该移动到result-detail
组件中。
演示:
window.onload = function()
Vue.component('search-bar',
template: '#search-bar',
data()
return
resultSet: [],
q: '',
);
Vue.component('view-result',
template: '#result-detail',
data()
return
placeData: [],
);
const searchbar = template: '<search-bar />'
const result = template: '<view-result />'
const routes = [
path: '/', component: searchbar,
path: '/results', component: result
];
const router = new VueRouter(
routes // short for `routes: routes`
);
const web = new Vue(
router,
el: '#app',
data:
pageData: [],
name: '',
,
mounted: function()
//this.initPage();
,
ready: function()
,
computed:
,
watch:
q: function(val, oldVal)
this.instantSearch();
,
methods:
instantSearch: function()
axios.get('https://nominatim.openstreetmap.org/search?q='+this.q+'&format=json').then( (places) =>
console.log(places);
this.resultSet = [];
places.data.forEach( (item, i) =>
this.resultSet.push(item);
);
);
,
resetSearch: function()
this.resultSet = [];
this.q = '';
,
expandMap: function(lat, lng)
let collapsable = document.getElementById('map-collapsable');
console.log(lat, lng);
//$(collapsable).collapse();
this.placeData.push(lat: lat, lng: lng);
,
initMap: function(data)
)
<script src="https://unpkg.com/vue@2.6.11/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue-router@3.1.6/dist/vue-router.js"></script>
<style>
h1
font-family: 'Courgette', cursive;
.list-group
max-height: 300px;
margin-bottom: 10px;
overflow:scroll;
-webkit-overflow-scrolling: touch;
#map
height: 400px;
</style>
<div class="container-fluid bg-light p-0" id="app">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 p-5">
<ul class="nav">
<router-link to="/">
<li class="nav-item">
<a class="nav-link" href="#">Home</a>
</li>
</router-link>
</ul>
</div>
</div>
<router-view></router-view>
</div>
<script type="text/x-template" id="search-bar">
<div class="row justify-content-center m-0" style="height:100vh;">
<div class="col-sm-12 col-md-8 col-lg-8 p-5 mx-auto">
<h1 class="mt-5 mb-3 text-center">C</h1>
<div class="input-group">
<input type="email" class="form-control rounded-0" v-on:change="instantSearch()" v-model="q" placeholder="Cerca nelle vicinanze es: Pizzeria">
<div class="input-group-append">
<button class="btn btn-outline-success rounded-0" v-on:click="instantSearch()">Cerca</button>
</div>
</div>
<ul v-if="resultSet" class="list-group rounded-0">
<small v-if="q" class="list-group-item rounded-0"><a class="text-muted" href="#" v-on:click="resetSearch()">Annulla</a></small>
<router-link to="/results">
<a v-for="result in resultSet" :key="result.id" v-on:click="expandMap(result.lat, result.lon)" href="#" class="list-group-item rounded-0" :place="result.display_name"> result.display_name </a>
</router-link>
</ul>
<ul class="nav">
<li class="nav-item">
<a class="nav-link" href="#">FAQ</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Aggiungi la tua attività</a>
</li>
</ul>
</div>
</div>
</script>
<script type="text/x-template" id="result-detail">
<div class="collapse" id="map-collapsable">
<div class="row m-0 results-map">
<div class="col-sm-12 col-md-8 col-lg-8 p-0" id="map"></div>
<div v-for="place in placeData" class="col-sm-12 col-md-4 col-lg-4">
place.lat place.lng
</div>
</div>
</div>
</script>
【讨论】:
感谢您的帮助。我是vue的新手,所以我现在犯了很多错误。从 vue 的主实例中,有什么我可以传递给组件的吗?我需要使用<router-link>
函数在点击即时搜索结果时更改视图
特别是搜索结果的详细信息需要传递给结果组件,不胜感激
@guggio 有几种方法可以处理这个问题。您可以在 search-bar
中实现 v-model,在 view-result
中实现公共属性。在app
中,使用本地数据道具将两者绑定在一起。我建议将其作为一个新问题提出,以获得更多有用的答案。以上是关于实现 vue-router 后 Vue.js 不工作的主要内容,如果未能解决你的问题,请参考以下文章