简体   繁体   中英

How to structure Vue.js instances in a Laravel project?

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!

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

A Vue instance just for the Form

<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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM