使用vue-router会出现“无法找到元素#app”和“ TypeError:无法读取属性'matched'的未定义”错误

时间:2019-02-17 16:56:45

标签: javascript vue.js vue-router

我正在尝试使用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'”(无效)。

3 个答案:

答案 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的正文中。