Reputation: 1521
I have an application with multiple web pages. On each webpage, I want to be able to bind a Vue instance to some element on the page as to give it a more dynamic user interaction.
In the base Laravel project, you're supposed to bind a Vue instance to #app in app.js which I've done. Including any more instances, however, give a "element not found" error when you're on any page that doesn't include that element. I imagine you're not supposed to put all of your instances in app.js...
What is the general architecture for having a different Vue instance on each page? Do I make a new js file for each page, and include it?
Sorry for my naivety!
Upvotes: 1
Views: 2314
Reputation: 1058
I just use a single Vue instance.
I have a master blade layout in which the body section looks like the code given below and I extend it for all the pages. It's basically a template with head tag filled with @yield('tags_like_meta', default_value)
and some other javascript imports.
<body>
<div id="app">
@yield('contents')
</div>
</body>
And then I have a single Vue instance like this on my js file.
const app=new Vue({el:"#app"});
For different pages I use Vue-router to dynamically load the component. For example, if I want my contact page to be loaded via Vue, I will have my contact_page.blade.php
look like this
@extends(layout.master)
@section('contents')
<router-view></router-view>
@endsection
And Vue-router will handle the rendering if I have the contact page url specified in the routes.
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/contact',
name: 'contact',
component: () => import('./components/contact/index')
}]
});
This way, you can work with single Vue instance (as mentioned in the docs)
Upvotes: 1
Reputation: 11044
You can create a new Vue instance on a yielded scripts section in app.blade.php
that every view extends (mostly) for each page where needed to avoid the Vue warning
For example, Laravel Vapor website does* this, in the main page you can find this code
*they use a CDN to include the library instead of the compiled one from webpack
<script>
var app = new Vue({
el: '#form',
data: {
email: '',
submitted: false,
submitting: false
},
methods: {
onSubmit: function () {
this.submitting = true;
fetch('/api/early-access', {
method: 'POST',
body: JSON.stringify({ email: this.email }),
headers: {
'Content-Type': 'application/json'
}
}).then(response => {
this.submitted = true;
this.submitting = false;
});
}
}
})
</script>
In layouts/app.blade.php
yield a section for the scripts right before the closing tag of the body, for example
<main class="py-4">
@yield('content')
</main>
</div>
@yield('scripts')
</body>
Then instantiate a new Vue instance in the Blade view file of a page like so
@extends('layouts.app')
@section('content')
<div class="container">
<div id="home-page"></div>
</div>
@endsection
@section('scripts')
<script>
new Vue({
el: '#home-page',
});
</script>
@stop
Hope this helps
Upvotes: 2