vuejs / vue-router

🚦 The official router for Vue 2
http://v3.router.vuejs.org/
MIT License
18.99k stars 5.06k forks source link

Failed to mount component: template or render function not defined. (found in root instance) #713

Closed lzxb closed 8 years ago

lzxb commented 8 years ago

I write it in this case, but it is wrong. http://router.vuejs.org/en/essentials/getting-started.html

"vue": "^2.0.1",
"vue-router": "^2.0.0",
"vuex": "^2.0.0"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<div id="app">
  <h1>Hello App!</h1>
  <p>
    <!-- use router-link component for navigation. -->
    <!-- specify the link by passing the `to` prop. -->
    <!-- <router-link> will be rendered as an `<a>` tag by default -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- route outlet -->
  <!-- component matched by the route will render here -->
  <router-view></router-view>
</div>
</body>
</html>
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
// 0. If using a module system, call Vue.use(VueRouter)

// 1. Define route components.
// These can be imported from other files
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }

// 2. Define some routes
// Each route should map to a component. The "component" can
// either be an actual component constructor created via
// Vue.extend(), or just a component options object.
// We'll talk about nested routes later.
const routes = [
  { path: '/foo', component: Foo },
  { path: '/bar', component: Bar }
]

// 3. Create the router instance and pass the `routes` option
// You can pass in additional options here, but let's
// keep it simple for now.
const router = new VueRouter({
  routes // short for routes: routes
})

// 4. Create and mount the root instance.
// Make sure to inject the router with the router option to make the
// whole app router-aware.
const app = new Vue({
  router
}).$mount('#app')

// Now the app has started!
open url http://localhost:3000/admin/#/bar
fnlctrl commented 8 years ago

Hi, thanks for filling this issue. If you import Vue from 'vue'; you get the runtime only build that cannot compile templates (either in-dom templates or template option). In this case you need the standalone build, here is a helpful section explaining this: https://vuejs.org/guide/installation.html#Standalone-vs-Runtime-only-Build

lzxb commented 8 years ago

thank you

vanpipy commented 7 years ago

Hello :D @fnlctrl @lzxb.

I follow @fnlctrl advice to fix the vue template compiler.

But another problem come out.

All the get start vue code copy from get-start-page

The different is webpack config. Here is below:

const rucksack = require('rucksack-css');
const Webpack = require('webpack');
const path = require('path');

function makeWebpackConfig() {
    return {
        context: path.join(__dirname, './client'),
        entry: {
            js: './index.js',
            html: './index.html',
            vendor: [
                'vue',
                'vue-router',
            ]
        },
        output: {
            path: path.resolve(__dirname, 'dist'),
            publicPath: '/',
            filename: 'bundle.js'
        },
        module: {
            loaders: [
                {
                    test: /\.html$/,
                    loader: 'file?name=[name].[ext]'
                },
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                    query: {
                        presets: ['es2015']
                    }
                },
                {
                    test: /\.css$/,
                    include: /client/,
                    loaders: [
                        'style-loader',
                        'css-loader',
                        'postcss-loader'
                    ]
                }
            ]
        },
        resolve: {
            extensions: ['', '.js', '.jsx'],
            alias: {
                'vue$': 'vue/dist/vue.js'
            }
        },
        postcss: [
            rucksack({
                autoprefixer: true
            })
        ],
        plugins: [
            new Webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'),
            new Webpack.DefinePlugin({
                'process.env': {
                    NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
                }
            })
        ],
        devServer: {
            contentBase: './client',
            hot: true
        }
    };
}

And after the new Vue({ router }).$mount the div#app inner router-view display nothing, I try to compare the get start live example with mine but nothing found.

Can anyone give me some advice for this?

That's mine fault, it's need more { routes } in it. It's fixed already :D. Thanks.

ModleIory commented 7 years ago

It works!!! good!

oleynikd commented 7 years ago

Should I also use standalone build if I'm using Single File Components?

fnlctrl commented 7 years ago

@oleynikd No, single file components will have their templates compiled at build time. As long as you don't use the template: ... option or in-dom templates, you can use the lighter runtime-only build.

xqyww123 commented 7 years ago

@fnlctrl so here is the problem. In main.js, which isn't a single file component so that can not be compiled, how can I declare the top component app under the body tag, without template: ... option in main.js or in-dom template in index.html

fnlctrl commented 7 years ago

@xqyww123 If you're using the runtime-only build, anything put inside html cannot be compiled. Therefore, you'll need the mount method

A simple example:

// your entry js
import App from './App.vue';
new Vue(App).mount('#app');
<body>
  <div id="app"></div>
</body>

If you need to add a router/store instance to the root instance, it'll have to be slightly modified:

// your entry js
import App from './App.vue';
import store from './store';
import router from './router';

new Vue({
   ...App // ES7 Object rest spread operator (or Object.assign)
   router,
   store
}).mount('#app');

The above is the javascript approach. However, if you want to avoid the rest spread operator / Object.assign, another approach would be using vue's render functions:

// your entry js
import App from './App.vue';
import store from './store';
import router from './router';

new Vue({
   router,
   store,
   render: h => h(App)
}).mount('#app');
AnsonHwang86 commented 7 years ago

@fnlctrl Therefore, you'll need the mount method. You mean instance method $mount can compiled anything inside html? I make a demo and find this wrong. Runtime-only build with method $mount cann't compiled anything inside html. My code:

// index.html

<div id="app">
  {{ message }}
</div>

// main.js

import App from './App.vue'
new Vue({
  data: {
    message: 'hello, kitty!'
  }
}).$mount('#app') // Noted, it's "$mount" instead "mount", $mount is vue instance method

// result vue.runtime.common.js:519 [Vue warn]: Failed to mount component: template or render function not defined. Your demo is very nice, thanks.

fnlctrl commented 7 years ago

You mean instance method $mount can compiled anything inside html?

No. That's not what I said. Let me rephrase that: since the runtime-only build cannot compile anything (in-dom, template string), you can't put templates inside html, so you either use $mount or the el option to mount the component to the target.

ubershmekel commented 7 years ago

For anyone still finding this thread, this is how I ended up getting past this error for my browserify and typescript setup:

import * as Vue from 'vue/dist/vue.common.js';

var app = new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    }
});
seanfisher commented 7 years ago

@ubershmekel Not to take us too off-topic, but how do you get typings with that setup?

zcdziura commented 7 years ago

If you're using Webpack 2 to build your application, here is what I did to resolve the problem:

From webpack.config.js:

module.exports = {
    ...
    resolve: {
        extensions: ['.js'],
        alias: {
            'vue': 'vue/dist/vue.common.js'
        }
    },
    ...
}

From there, you are able to install Vue as you would expect using ES6 syntax:

import Vue from 'vue';

aiqin-bao commented 6 years ago

有中文的解答吗? 看得不是很明白 ??

wspl commented 6 years ago
import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      component: require('../pages/Main.vue').default
    }
  ]
})

if you use require in router, you need add a .default after require expression.

jacky-jiang commented 6 years ago

as @wspl commented, it would work well.

another option is 'import' as following:

import Vue from 'vue'
import Router from 'vue-router'

import Main from '../pages/Main.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      component: Main
    }
  ]
})
0x1af2aec8f957 commented 6 years ago

删除你的module文件夹,重新更新安装所有依赖(使用npm进行安装)。请不要通过cnpm进行安装依赖,这会导致有些包找不到地址(无法正常找到)。推荐使用npm,更换镜像地址即可!

sxei commented 6 years ago

一群中国人在这里用英语交流,也是醉了哈

toshcn commented 6 years ago

@wspl thanks 正解 the right answers add the require .default routes: [ { path: '/', component: require('../pages/Main.vue').default } ]

SageSanyue commented 6 years ago

Smilar problem, when I write:

let routes = [{ path: '/', component: require('./components/member.vue') }] it failed:[Vue warn]: Failed to mount component: template or render function not defined. add ".default", it works!

let routes = [{ path: '/', component: require('./components/member.vue').default }] PS:"vue": "^2.5.2","vue-router": "^3.0.1""vue-loader": "^13.3.0",

0x1af2aec8f957 commented 6 years ago

@SageSanyue 你可以尝试使用webpack的动态导入语法:

component: () => import ('./HelloWorld')


const routes = [{
path: '/',
component: () => import('./components/member.vue')
}]

上述代码在webpack^3.0中正常工作。

Deg5112 commented 6 years ago

thank you @noteScript

molerat619 commented 6 years ago

I still have this issue. This is my app.js:

image

components/index.js:

image

I get this issue only when I enable esModul in webpack like so: mix.config.vue.esModule = true;

How can I fix this? The routes should be fine, I use import.

0x1af2aec8f957 commented 6 years ago

@molerat619 你可以换一种提问题的方式?

期望 -> 现状 -> 结果

---代码---

---问题描述---

你应该尽可能详细的描述你遇到的问题。

PayteR commented 6 years ago

i ran into same issue, but my solution was this:

https://stackoverflow.com/questions/49138501/vue-warn-failed-to-mount-component-template-or-render-function-not-defined-i

i think it's same as in @molerat619 example

askanhan commented 6 years ago

In my case, I imported my component (in router) as:

import bsw from 'common-mod/src/components/webcommon/webcommon'

It is simply solved if I changed it to

import bsw from 'common-mod/src/components/webcommon/webcommon.vue'
javierojeda94 commented 6 years ago

@askanhan solution worked perfect for me! Still I don't know why that caused the problem, the software I'm working on has been online for about 3 years and we are using Vue since 1 year ago but it worked fine :(

isofttechn commented 5 years ago

I solve mine by adding default after closing curly bracket. '.default'. e.g. const routes = [ { path: '/foo', component: Foo }.default, { path: '/bar', component: Bar }.default ]

askanhan commented 5 years ago

@askanhan solution worked perfect for me! Still I don't know why that caused the problem, the software I'm working on has been online for about 3 years and we are using Vue since 1 year ago but it worked fine :(

Couldn't find any reason but I believe it has something to do with the updates of webpack or so

benmo1602 commented 5 years ago

我遇到这个问题了, 打开router .js 然后 ctrl + s 就好了 , 真是诡异 image

skinnn commented 5 years ago

@wspl Thanks, thanks really all I needed to fix the error:

[Vue warn]: Failed to mount component: template or render function not defined.

egulhan commented 5 years ago

@skinnn, maybe you must be missing default keyword when you use like that: require('./components/Example.vue').default

codegeek1001 commented 4 years ago

I was getting the same error but adding .default helped as well. Here is my app.js in case it helps anyone else:

import Vue from "vue";
Vue.component("my-component", require("./components/my-component.vue").default);

new Vue({
  el: "#app"
});
Kasre96 commented 4 years ago

Adding .default works for me too.

In case yours doesn't change after adding .default try recompiling your code (.eg. npm run dev). Worked for me.

salahfarzin commented 4 years ago

Adding .default at the end of component line and worked import VueRouter from "vue-router"; let routes = [ { path: '/', component: require('./components/Home').default }, { path: '/coupon', component: require('./components/Coupon').default } ]; export default new VueRouter({ routes });

chinela commented 4 years ago

You can do import Home from './components/Home;

let routes = [ { path: '/', component: Home }, ]

NickCashFlow commented 3 years ago

I got this error because I had empty style section. Fill the style section or remove it and the problem will solved.

bhojkamal commented 3 years ago

I got blank on my web page. On console, I got this error ->

Vue warn]: Failed to mount app: mount target selector "#app" returned null.

I have used vue 3 with laravel 8 and used laravel-mix.

I've added the bootstrap 5 but it is working on my laravel blade template but other vue component is not working.

On blade

<body class="text-center">
  <div>
    <h2>Hello laravel 8</h2> <!-- this is showing on output in webpage with text center that come from app.js -->
  </div>
  <div id="#app"></div>
  <script src="{{ mix('js/app.js') }}"></script>
</body>

On app.js

import { createApp } from 'vue'
import router from './router'
import App from './App.vue'
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.min';
const app = createApp(App)
app.use(router)
app.mount('#app')

on App.vue

<template>
  <div class="text-center">
    <h1 class="text-bold"> Namaste from vue component </h1> <!-- this is not showing on output in webpage -->
    </div>
  <router-view></router-view>
</template>
<script>
export default {
  name: 'App'
}
</script>
javierojeda94 commented 3 years ago

@bhojkamal so by reading the error you should be able to tell what's wrong.

Replace <div id="#app"></div> with <div id="app"></div> and that should be it.