Reputation: 3183
I get some trouble with Vue.js and his routing system. I made an example here.
Why the method is correctly attach when I use a template (see Foo) and why not when I use an el (see Bar) ?
Here his the code:
index.js
var Foo = Vue.extend({
template: '<p v-on:click.prevent="foo">This is foo!</p>',
methods: {
foo: function(){
alert('YEAH')
}
}
})
var Bar = Vue.extend({
el: function(){
return '#bar'
},
methods: {
bar: function(){
alert('YEAH')
}
}
})
var App = Vue.extend({})
var router = new VueRouter()
router.map({
'/foo': {
component: Foo
},
'/bar': {
component: Bar
}
})
router.start(App, '#app')
index.html
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- use v-link directive for navigation. -->
<a v-link="{ path: '/foo' }">Go to Foo</a>
<a v-link="{ path: '/bar' }">Go to Bar</a>
</p>
<div id="bar" v-bind:class="$route.path == '/bar' ? '' : 'hidden'">
<p v-on:click.prevent="bar">This is bar!</p>
</div>
<!-- use router-view element as route outlet -->
<router-view></router-view>
</div>
Upvotes: 0
Views: 189
Reputation: 418
You misunderstood the el
purpose. When you pass el
to component it tells Vue on which element to mount itself
Note that the provided element merely serves as a mounting point; it will be replaced if a template is also provided, unless replace is set to false. The resolved element will be accessible as vm.$el.
Actually you have no template inside #bar
that Vue could compile and that's why you have no output. Also using el
inside another Vue's el
(in your case #app
) is a bad idea. The v-on:click.prevent="bar"
bit is compiled in parent's (App
instance) scope, and since App
has no bar
method you get a warning.
Better solution: http://codepen.io/anon/pen/zqWKrg
Notice that now each component has it's own template and you can clearly see scope of each component: #app
is compiled in App
scope, #foo
is compiled in Foo
scope and #bar
is compiled in Bar
scope.
Upvotes: 3
Reputation: 23988
you should use template: '#bar'
instead of el: '#bar'
the el
option is not a selector for the template.
var Bar = Vue.extend({ template: '#bar',
methods: {
bar: function(){
alert('YEAH')
}
}
})
You (ab)used a regular HTML element in the Apps main template as a sub-template for a component - that's not something you should do.
Its also the reason the click event is not working: the content of that div, including the click event, is evaluated by the App component, not the Bar component. And the App component has no "bar" method.
Hence the error in the console:
[Vue warn]: v-on:click="bar" expects a function value, got undefined
The template should look like this:
<script type="x-template" id="bar">
<div>
<p v-on:click.prevent="bar">This is bar!</p>
</div>
</script>
<!-- or with HTML5 template tag: -->
<template id="bar">
<div>
<p v-on:click.prevent="bar">This is bar!</p>
</div>
</template>
Upvotes: 0