Xây dựng giao diện website trên Laravel với Vuejs

Tình cờ khi lướt new feeds trên Facebook thấy có cuộc khảo sát và tech talk của Topdev về cuộc chiến vương quyền frontend: React, Angular2 và Vuejs; thế là nhớ ra mình cũng đang có 1 project dùng Vuejs và thấy khá thú vị. Trong khi React và Angular2 được mọi người biết đến khá nhiều thì Vuejs lại đang đón nhận được sự quan tâm thời gian gần đây. Hiện tại Vuejs đang được hỗ trợ bởi Laravel và sẽ được hỗ trợ bởi Rails trong bản 5.1 tới. Ở bài viết này mình sẽ giúp mọi người tìm hiểu qua về cách dùng của Vuejs và Laravel 5.3 (hiện tại thì Vuejs verion 2.2.0 và Laravel version 5.4).

Chúng ta sẽ quan tâm tới file gulpfile.js và viết các component trong thư mục resources/assets/js/components và file app.js(mặc đinh trong thư mục components của laravel sẽ có file Example.vue). Trong project của mình, mình chia các component thành module/folder để dễ quản lý. Lan man quá 😄 kwuay? thôi ProjectController:

public function index()
    {
    	return Response::json(['projects' => $this->project->all()]);
    }

Trong controller ta dùng để trả về dữ liệu dưới dạng JSON nhằm mục đích client request đến server để lấy dữ liệu. Nên để router này trong middleware api. Tạo 2 file vue components: projects.vueproject.vue: Component là một trong những tính năng nổi bật của vuejs. Nó giúp ta đóng gói HTML elements cho việc reuse code sau này. Chúng ta sẽ viết các HTML element trong <template></template> project.vue:

<template lang="html">
  <li class="isotope-item websites">
    <div class="portfolio-item img-thumbnail">
       <router-link :to="{ name: 'project.show', params: { projectSlug: project.slug }}" class="thumb-info secundary">
        <img alt="" class="img-responsive" v-bind:src="'/user/img/projects/' + project.image.main">
        <span class="thumb-info-title">
          <span class="thumb-info-inner">{{ project.name }}</span>
          <span class="thumb-info-type">{{ project.type }}</span>
        </span>
        <span class="thumb-info-action">
          <span title="Universal" class="thumb-info-action-icon"><i class="fa fa-link"></i></span>
        </span>
      </router-link>
    </div>
  </li>
</template>
<script>
  export default {
      // passing data
      props: ['project']
  }
</script>

props là dùng để tham chiếu property từ parent component tới child component. Ở đây mình dùng luôn router-link (require vue-router) của Vuejs luôn với mục đích xây dựng dạng SPA (Single-Page App). Nếu mọi người dùng thì nhớ kéo nó về qua npm install --save vue-router nhé. projects.vue:

<template lang="html">
    // template html here
    ...
    <ul class="portfolio-list sort-destination full-width" data-sort-id="portfolio">
      <Project v-for="project in projects" v-bind:project="project"></Project>
    </ul>
</template>
<script>
  import Project from './Project.vue';
  export default {
    data() {
      return {
        projects: []
      }
    },
    components: { Project },
    created() {
      this.fetchProjects();
    },
    methods: {
      fetchProjects() {
        this.$http.get('/api/guest/projects').then(response => {
          this.projects = response.data.projects;
        });
      }
    }
  }
</script>

Ở file này mình dùng v-for để duyệt dữ liệu theo mảng (giống như foreach nhỉ 😄). Dữ liệu sẽ được truyền tới component project.vue qua props. Ở đây mình sẽ tạo file js tương ứng với module thay vì viết trong file app.js:

var Vue = require('vue');
var VueResource = require('vue-resource');
var VueRouter =  require('vue-router');
import Projects from './components/guest/projects/Projects.vue';
Vue.use(VueRouter);
Vue.use(VueResource);
var router = new VueRouter({
  routes: [
    { path: '/', name: 'index', component: Index },
    { path: '/members', name: 'member.index', component: Members },
    { path: '/projects', name: 'project.index', component: Projects },
  ]
});
const app = new Vue({
    el: '#app',
    router
});

Vue.filter('str_limit', function (string, value) {
	return string.substring(0, value) + '...';
});

Note: Việc dùng router do Vuejs là optional nhé. e1: '#app' chính là id trong thẻ body (render data):

<!DOCTYPE html>
<html>
    @include('layouts.guest.includes.head')
    <body>
        <div class="body" id="app">
            <noscript>
                Your script is turn off.Turn it on browser setting
            </noscript>
            <div class="wrapper">
              @include('layouts.guest.includes.header')
                    <router-view></router-view>
              @include('layouts.guest.includes.footer')
              @include('layouts.guest.includes.scripts')
            </div>
        </div>
    </body>
</html>

Ở trong file gulpfile.js:

const source = 'resources/assets/';
require('laravel-elixir-vue-2');
elixir(mix => {
    mix.webpack(source + 'js/guest.js', 'public/js/guest/guest.js');
});

Sau khi thêm vào gulpfile.js mọi người nhớ vào terminal chạy command: gulp Ở trong view gọi component projects :

@extends('layouts.guest.desktop')
@section('content')
	<Projects></Projects>
@stop
@push('script')
	<script src="{{ elixir('user/js/user.js') }}"></script>
@endpush

Các bạn nên cài thêm vue devtool extension trên trình duyệt để tiện debug và theo dõi các component của Vuejs nhé. Sau khi tiếp xúc mình thấy Vuejs khá dễ nhớ, dễ học và thực hành. Hy vọng mọi người sẽ biết và dùng nó trong project của mình. Thân ái ! References Vuejs - The Progressive JavaScript Framework