II. Avec Laravel▲
Comme ce tutoriel est essentiellement consacré à Laravel il me faut évoquer l'utilisation de Vue.js 2 avec Laravel 5.3 puisque cette version a été enrichie de tout ce qu'il faut pour sceller ce mariage. J'en ai un peu parlé dans mon tutoriel sur les nouveautés de la version 5.3 je vais y revenir de façon plus précise maintenant en poursuivant l'exemple du panier dans le contexte de Laravel.
II-A. État des lieux▲
Dans l'article référencé ci-dessus, j'avais présenté l'infrastructure en place lorsqu'on installe Laravel 5.3 :
On a déjà :
- un composant vue.js 2 : Exemple.vue ;
- une application de base : app.js ;
- un fichier d'initialisation : bootstrap.js.
Avec Laravel on n'utilise pas directement Webpack - on pourrait si on le voulait -, mais plutôt Elixir qui est lui-même une sur couche qui simplifie l'utilisation de Gulp.
Si on regarde le fichier de configuration de Gulp (gulpfile.js) :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
const elixir =
require
(
'laravel-elixir'
);
require
(
'laravel-elixir-vue-2'
);
/*
|--------------------------------------------------------------------------
| Elixir Asset Management
|--------------------------------------------------------------------------
|
| Elixir provides a clean, fluent API for defining some basic Gulp tasks
| for your Laravel application. By default, we are compiling the Sass
| file for our application, as well as publishing vendor resources.
|
*/
elixir
(
mix =>
{
mix.sass
(
'app.scss'
)
.webpack
(
'app.js'
);
}
);
On voit qu'on lance une tâche Webpack en référençant le fichier app.js qui est l'entrée de l'application. C'est donc Elixir qui se charge de tout de façon invisible (on n'a pas de fichier webpack.config.js, mais on peut en créer un au besoin).
Concernant npm on a ce fichier package.json :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
{
"private"
:
true,
"scripts"
:
{
"prod"
:
"gulp --production"
,
"dev"
:
"gulp watch"
},
"devDependencies"
:
{
"bootstrap-sass"
:
"^3.3.7"
,
"gulp"
:
"^3.9.1"
,
"jquery"
:
"^3.1.0"
,
"laravel-elixir"
:
"^6.0.0-11"
,
"laravel-elixir-vue-2"
:
"^0.2.0"
,
"laravel-elixir-webpack-official"
:
"^1.0.2"
,
"lodash"
:
"^4.16.2"
,
"vue"
:
"^2.0.1"
,
"vue-resource"
:
"^1.0.3"
}
}
On voit qu'on charge vue ainsi que le plugin vue-resource dont je parlerai dans un autre chapitre.
On dispose aussi de deux scripts :
- dev : pour le développement avec une observation des modifications (watch) ;
- prod : pour la production en compressant les fichiers.
II-B. Installation▲
La première chose à faire est évidemment d'utiliser npm pour charger toutes les dépendances :
npm install
Ce qui crée le dossier node_modules avec tous les fichiers :
On sait qu'on aura besoin du système de template pug pour le panier, alors on l'ajoute :
npm install pug
On a ainsi tout ce qu'il faut au niveau des dépendances !
En faisant mes essais, je me suis rendu compte que la transformation du code ES6 en ES5 avec Elixir n'était pas assurée par Babel, mais par Bublé. Cela a certaines conséquences parce que ce n'est pas l'ensemble de ES6 qui est pris en charge, ce qui est justifié dans la documentation :
Bublé limits itself to ES features that can be compiled to compact, performant ES5
Vous disposez d'ailleurs d'une page avec les fonctionnalités non supportées. En particulier on y trouve le for…of que j'ai utilisé précédemmentOn s'organise ! pour justement tester la transformation effectuée par Babel. C'est d'ailleurs comme ça que je m'en suis rendu compte, parce que je tombais sur une erreur et que j'ai dû un peu fouiller parce que rien n'est indiqué dans la documentation de Laravel…
On peut tout de même changer les options de fonctionnement de Bublé, mais pas d'une façon qui m'a semblé suffisamment claire et adaptable à la situation. On peut évidemment utiliser Babel, mais le loader est codé en dur dans Elixir…
Pour le présent chapitre, j'ai pris la configuration par défaut et enlevé le for…of du code, ce qui était le plus simple !
II-C. Le panier▲
Maintenant pour mettre en place le panier c'est tout simple. On crée une route pour le tester :
La vue test.blade.php :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
<!
DOCTYPE html
>
<html
lang
=
"fr"
>
<head>
<meta
charset
=
"utf-8"
>
<meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
<meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1"
>
<title>
Test vue.js</title>
<link
rel
=
"stylesheet"
href
=
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
>
<link
rel
=
"stylesheet"
href
=
"https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"
>
<link
rel
=
"stylesheet"
href
=
"https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/united/bootstrap.min.css"
>
</head>
<body>
<div
class
=
"container"
>
<br>
<div
id
=
"app"
>
<app></app>
</div>
</div>
<script
src
=
"/js/app.js"
></script>
</body>
</html>
On a :
- un identifiant app pour servir de référence à Vue.js ;
- une balise app pour notre application ;
- le chargement du fichier JavaScript de l'application /js/app.js.
Dans app.js on change le composant :
On met en place nos trois composants et on supprime Exemple.vue :
Pour rappel voici le code de App.vue :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
<template>
<div
id
=
"app"
>
<panier
:
panier
=
"panier"
></panier>
</div>
</template>
<script>
import Panier from './Panier.vue'
export default {
name
:
'application'
,
data
(
) {
return {
panier
:
[
{
article
:
"Cahier"
,
quantite
:
2
,
prix
:
'5.30'
},
{
article
:
"Crayon"
,
quantite
:
4
,
prix
:
'1.10'
},
{
article
:
"Gomme"
,
quantite
:
1
,
prix
:
'3.25'
}
]
}
},
components
:
{
Panier
}
}
</script>
Le code de Panier.vue :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
<template>
<div
class
=
"panel panel-primary"
>
<div
class
=
"panel-heading"
>
Panier</div>
<table
class
=
"table table-bordered table-striped"
>
<thead>
<tr>
<th
class
=
"col-sm-4"
>
Article</th>
<th
class
=
"col-sm-2"
>
Quantité</th>
<th
class
=
"col-sm-2"
>
Prix</th>
<th
class
=
"col-sm-2"
>
Total</th>
<th
class
=
"col-sm-1"
></th>
<th
class
=
"col-sm-1"
></th>
</tr>
</thead>
<tbody>
<tr
v-for
=
"(item, index) in panier"
>
<td>
{{
item.article }}
</td>
<td>
{{
item.quantite }}
</td>
<td>
{{
item.prix }}
€</td>
<td>
{{
(
item.quantite *
item.prix)
.toFixed(
2
)
}}
€</td>
<td><button
class
=
"btn btn-info btn-block"
@
click
=
"modifier(index)"
><i
class
=
"fa fa-edit fa-lg"
></i></button></td>
<td><button
class
=
"btn btn-danger btn-block"
@
click
=
"supprimer(index)"
><i
class
=
"fa fa-trash-o fa-lg"
></i></button></td>
</tr>
<tr>
<td
colspan
=
"3"
></td>
<td><strong>
{{
total }}
€</strong></td>
<td
colspan
=
"2"
></td>
</tr>
<editeur
:
article
=
"article"
@
add
=
"ajouter"
></editeur>
</tbody>
</table>
</div>
</template>
<script>
import Editeur from './Editeur.vue'
export default {
props
:
[
'panier'
],
data
:
function (
) {
return {
article
:
{
article
:
''
,
quantite
:
0
,
prix
:
0
}
}
},
computed
:
{
total
:
function (
) {
let total =
0
;
this.
panier.forEach
(
function(
el) {
total +=
el.
prix *
el.
quantite;
}
);
return total.toFixed
(
2
)
}
},
methods
:
{
modifier
:
function(
index) {
this.
article =
this.
panier[
index]
this.
panier.splice
(
index,
1
)
},
supprimer
:
function(
index) {
this.
panier.splice
(
index,
1
)
},
ajouter
:
function(
input) {
this.
panier.push
(
input)
this.
article =
{
article
:
''
,
quantite
:
0
,
prix
:
0
}
}
},
components
:
{
Editeur
}
}
</script>
C'est là que j'ai supprimé le for…of.
Et Editeur.vue :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
<template
lang
=
"pug"
>
tr(class="bleu")
td
input(type="text" class="form-control" v-model="input.article" ref="modif" placeholder="Article")
td
input(type="text" class="form-control" v-model="input.quantite" placeholder="Quantité")
td
input(type="text" class="form-control" v-model="input.prix" placeholder="Prix")
td(colspan="3")
button(class="btn btn-primary btn-block" @click="ajouter()") "Ajouter"
</template>
<script>
export default {
props
:
[
'article'
],
computed
:
{
input
:
function(
) {
return this.
article;
}
},
methods
:
{
ajouter
:
function(
) {
this.
$emit
(
'add'
,
this.
input);
}
}
}
</script>
<style
lang
=
"sass"
>
$fond:
lightblue;
.bleu
{
background-color:
$fond !important;
}
</style>
II-D. On lance Gulp▲
Il ne reste plus qu'à voir si ça fonctionne :
Apparemment tout se passe bien en mode développement. On retrouve bien le panier :
Et on est en mode watch pour que tous les changements soient pris en compte.
Et voilà ce que ça donne en mode production :
Cette fois le fichier /js/app.js est minifié et le panier fonctionne encore !
On voit donc que la mise en œuvre de Vue.js2 avec Laravel 5.3 est assez facile.
Reste toutefois à voir s'il est aussi facile de modifier la configuration selon les besoins. Je n'en ai pas l'expérience parce que je n'ai eu aucun projet qui justifie ce genre de mise en œuvre.