我正在尝试使用 Vue.js 重新创建我之前使用 Scala Play 制作的前端应用程序(我想了解有关基于组件的网页设计的更多信息)。
我制作的第一个页面的所有内容都加载得很好,但我想实现路由,这样我就可以拥有多个页面(而不是只有一个大型单页应用程序)。我使用 npm install vue-router --save
安装了 vue-router,并尝试遵循以下教程(使用我已经制作的组件):https://scotch.io/tutorials/how-to-build-a-simple-single-page-application-using-vue-2-part-1 .
据我所知,所有内容应该都能顺利加载,但没有加载任何内容,我收到以下控制台错误:
[Vue warn]: Cannot find element: #app
[Vue warn]: Cannot find element: #app
[Vue warn]: Error in render: "TypeError: Cannot read property 'matched' of undefined"
found in
---> <App> at src/App.vue
<Root>
TypeError: Cannot read property 'matched' of undefined
at render (vue-router.esm.js?8c4f:76)
at createFunctionalComponent (vue.runtime.esm.js?2b0e:3033)
.... (etc)
我没有粘贴完整的堆栈跟踪,但如果需要可以粘贴。
我的代码如下:
main.js
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import Home from './components/Home.vue'
Vue.use(VueRouter)
const routes = [
{ path: '/', component: Home }
]
const router = new VueRouter({
routes
})
new Vue({
el: '#app',
template: '<App/>',
components: { App },
router
}).$mount('#app')
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Arial, Helvetica, sans-serif;
line-height: 1.4;
background-color: aliceblue;
}
</style>
组件/Home.vue
<template>
<div id="app">
<Header />
<Posts v-bind:posts="posts" />
</div>
</template>
<script>
import Posts from './Posts.vue'
import Header from './Header.vue'
export default {
name: 'home',
components: {
Header, Posts
},
data() {
return {
posts: []
}
}
}
</script>
<style>
</style>
如果我还需要包含 Header.vue 和 Posts.vue,请告诉我 - 我省略了它们,因为在我尝试使用 vue-router 之前它们渲染得很好。
如何消除这些控制台错误,以便在使用 vue-router 时正确呈现我的主页?我四处搜索,到目前为止,我所有的搜索结果都让我对“确保 router
是小写字母”(确实如此)、“确保 routes
是小写字母”(它是),以及“使用 import Vue from 'vue/dist/vue.js'
”(没有用)。
最佳答案
关于原问题:
我相信您从评论讨论中知道,错误 [Vue warn]: Cannot find element: #app
是因为两个 Vue 实例被配置为一个接一个地挂载在同一个根 DOM 节点 #app
.
第一个 Vue 实例挂载,在这样做的过程中,用在它自己的模板中定义的 HTML 替换根 DOM 节点。因此,#app
根 DOM 节点不存在,第二个 Vue 实例挂载失败,因为它找不到任何 id 为 #app
的 DOM 节点.
这意味着如果第一个 Vue 模板包含一个 ID 为 #app
的 DOM 节点,第二个 Vue 实例可能会安装在那里,用它自己的替换第一个实例中的任何现有 HTML。
通过删除重复的 Vue 实例解决此错误。
关于您的后续问题:
I don't have the faintest idea why this works without all the
el: '#app', template: '<App/>', components: { App }
首先要注意的是 Vue 实例属性 vm.$el
和 Vue 实例方法 vm.$mount()
在大多数情况下它们在功能上是等效的——每个都允许您指定将安装 Vue 实例的根 DOM 元素。
主要区别在于它们的应用:
您使用
vm.$el
在实例创建时声明根 DOM 节点。但是,提供值不是强制性的,如果您不这样做,实例将以未安装状态创建。vm.$mount()
允许您在实例化后为未安装的实例指定根 DOM 节点。
如文档中所述:
If a Vue instance didn’t receive the el option at instantiation, it will be in “unmounted” state, without an associated DOM element. vm.$mount() can be used to manually start the mounting of an unmounted Vue instance.
当然,如果你使用vm.$mount()
而不是 vm.$el
在创建实例时,这在很大程度上取决于开发人员的品味(尽管 $mount()
也接受各种输入,因此存在其他细微差别)。但是从你的问题的 Angular 来看,没有实际的区别。
最后,Vue 的 template
属性(property)和render()
方法只是定义 Vue 实例模板结构的两种策略:
template
是更高级别的模板抽象,允许您定义一个字符串模板;例如:<div><App/></div>
Vue 将其解析为一个结构,根据需要实例化任何子组件。render()
是另一种较低级别的模板抽象,它是 closer-to-the-compiler alternative to templates .它对于细粒度/编程用例或与其他模板语言(如 JSX 或原始 JS)一起使用更加灵活。
您的示例中的主要明显区别是 template
使用 <App/>
定义字符串模板成分。 Vue 实例需要在解析这个模板字符串之前知道这个组件是什么,所以它必须被声明为一个组件。
然而,render()
允许 App
直接传递给渲染的组件,因此不需要定义 template
属性或声明任何组件。
我的观点是,前者更明确——这不是坏事——并且在声明具有多个组件的结构时更具声明性和可读性。为此,Vue 似乎建议在大多数情况下使用模板字符串。也就是说,后一种方法也可以很简洁,并且您经常会在安装单个顶级入口点组件(例如:App
)的地方看到它。
另一个(隐含的)策略是DOM 模板。在没有 template
的情况下属性(property)或render()
方法,使用在根 DOM 节点内定义的 HTML 结构——尽管通常不鼓励这样做。
希望这有帮助:)
关于javascript - 使用 vue-router 给出 "Cannot find element #app"和 "TypeError: Cannot read property ' matched' of undefined"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54735471/