我正在尝试使用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>
components / 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'
”(无效)。
答案 0 :(得分:1)
关于原始问题:
我敢肯定您从评论讨论中知道,错误[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实例来解决此错误。
关于您的后续问题:
我不知道为什么在没有所有
的情况下仍能正常工作el: '#app', template: '<App/>', components: { App }
首先要注意的是,Vue实例属性vm.$el
和Vue实例方法vm.$mount()
在功能上大部分是等效的-每个都允许您指定Vue实例所在的根DOM元素。已安装。
主要区别在于它们的应用:
您可以在实例创建时使用vm.$el
声明根DOM节点。但是,提供值不是必须的,如果不提供,则实例将以未装载状态创建。
vm.$mount()
允许您在实例化后的 后为卸载实例指定根DOM节点。
如文档所述:
如果Vue实例在实例化时未收到el选项,则它将处于“已卸载”状态,并且没有关联的DOM元素。 vm。$ mount()可用于手动启动未安装的Vue实例的安装。
当然,如果在实例创建时使用vm.$mount()
而不是vm.$el
,这很大程度上取决于开发人员的口味(尽管$mount()
也接受各种输入,因此有还有其他细微差别)。但是从您的问题的角度来看,没有实际的区别。
最后,Vue的template
属性和render()
方法只是定义Vue实例的模板结构的两种策略:
template
是更高级别的模板抽象,可让您定义 string模板;例如:<div><App/></div>
,Vue将其解析为一个结构,根据需要实例化任何子组件。
render()
是closer-to-the-compiler alternative to templates的另一种较低级别的模板抽象。对于更细粒度/编程的用例或与其他模板语言(例如JSX或原始JS)一起使用,它更加灵活。
示例中最明显的区别是template
使用<App/>
组件定义了字符串模板。在解析此模板字符串之前,Vue实例需要知道该组件是什么,因此必须将其声明为组件。
鉴于render()
允许直接传递App
组件以进行渲染,因此不需要定义template
属性或声明任何组件。
我的看法是,前者更明确-这不是一件坏事-并且在声明具有多个组件的结构时更具声明性和可读性。为此,Vue似乎推荐大多数情况下使用模板字符串。也就是说,后一种方法也可以很简洁,并且您经常会在安装单个顶级入口点组件(例如App
)的地方看到它。
另一种(隐式)策略是 DOM模板。在没有template
属性或render()
方法的情况下,将使用在根DOM节点中定义的HTML结构-尽管通常不建议这样做。
希望这会有所帮助:)
答案 1 :(得分:0)
我通过将main.js裁剪为仅包含一个new Vue
部分来解决此问题,该部分现在看起来像这样:
new Vue({
router,
render: h => h(App)
}).$mount('#app')
我没有最模糊的想法,但是为什么没有所有el: '#app', template: '<App/>', components: { App }
的东西也能起作用,所以如果可以解释一下,我将不胜感激-我不愿意添加答案,因为我不知道为什么有效;如果有人添加了解释它的答案,我很乐意接受(或随时编辑我的答案并添加解释并删除此段)。
答案 2 :(得分:0)
我发现问题可能不存在
<div id="app"></div>
位于index.html的正文中。