skip to Main Content

So I’m thinking about the structure for my restaurant web page which will use laravel as the back-end (routing and displaying blade views to the browser, easy auth system and sessions) and vue.js for the front-end (I have a single vue instance where I register components, this components are each one a view, a whole page, most of these pages have 2 or 3 components nested, like an image slider, to-top anchor, I use axios to fetch my API endpoints without refreshing the page plus many CRUD operations from an admin panel).

This is how my index.blade.php view looks ( www.domain.com/ ), I have many views like posts.index.blade.php…

@extends('layouts.master')
@section('content')
    <page-index></page-index)
@endsection

As you can see, I want to treat each page as a vue.component with many components nested inside of each page component).

I have a few questions about possible complications using this structure.

When displaying views I always return a json object with all the data I want to render on blade, since each page is basically a vue.js component loaded via javascript how will I able to loop through the dishes, events and posts I fetched from the backend. This is, I want to use the v-for directive but how can my component know of the data passed to blade? I donn’t want to use axios on mounted to populate my views… that would increase drastically the number of requests send to the backend.

Since the whole page content is rendered via javascript won’t this affect negatively SEO?? afaik search engones crawlers won’t fetch the content displayed by javascript.

Is this a good practice, is this the best way to handle laravel + vue.js non-SPA? Is this a good abstraction of front-end and back-end?

How I will handle auth is by doing axios requests to laravel login endpoints.

2

Answers


  1. Your app structure wants vue.js files and id of the element where it can render components:

    <html>
        ...
       <head>...</head>
    <body>
        @extends('layouts.master')
        @section('content')
         <div id="app">   //vue will read this id and render components
            <page-index></page-index>
         </div>
        @endsection
    
       <script src="/js/app.js"></scrip> 
       // this is where webpack usually place compiled js files. It will run vue.on element having id=app.
    
     </body>
    

    Remember! You have to include vue.js files where you want to use vue in laravel application

    Login or Signup to reply.
  2. For passing data to your vue component, you can use props.

    IndexController.php

        ...
        $events = [
            ['id' => 111, 'foo' => 'bar'],
            ['id' => 123, 'foo' => 'bar']
        ];
        
        return view('index')->with(compact('events')); // send events to blade
    }
    

    index.blade.php

    @extends('layouts.master')
    @section('content')
        <page-index events="{{ json_encode($events) }}"></page-index> // send events to vue
    @endsection
    

    PageIndexComponent.vue

    <script>
        export default {
            props: ['events'], // get events from here
            mounted() {
                parsedEvents = JSON.parse(this.events);
            }
        }
    </script>
    

    Here you can do your v-for loop with parsedEvents.


    For SEO, you can edit your resources/views/layouts/master.blade.php:

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta http-equiv="X-UA-Compatible" content="IE=edge">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <meta name="csrf-token" content="{{ csrf_token() }}">
            <meta name="title" content="@hasSection('title')@yield('title')@else{{ config('app.name') }}@endif">
            <meta name="description" content="@hasSection('description')@yield('description')@else{{ config('app.name') }}@endif">
            <meta property="og:title" content="@hasSection('title')@yield('title')@else{{ config('app.name') }}@endif">
            <meta property="og:description" content="@hasSection('description')@yield('description')@else{{ config('app.name') }}@endif">
            <meta property="og:image" content="@hasSection('image')@yield('image')@else{{ asset('/images/avatar.jpg') }}@endif">
            <meta property="og:type" content="@yield('type')">
            <meta property="og:url" content="{{ url()->current() }}">
            <meta property="og:locale" content="en_US">
            ...
    

    And in each view you can either hardcode your title, description etc or send it from your Controllers:

    @extends('layouts.master')
    
    @section('title', 'Events') // or something like $page_title received from controller
    @section('description', 'All Events') // or $page_desc sent from controller
    @section('image', 'http://imgurl.com/123.png') // etc, etc
    @section('type', 'article')
    
    @section('content')
        <page-index events="{{ json_encode($events) }}"></page-index)
    @endsection
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search