Настало время прикрутить библиотеку которая будет отвечать за frontend. Штатно в поставке laravel идет Vue. Я буду использовать vuetifyjs которая использует Vue и содержит красивые компоненты.
Для работы необходимо скачать и установить nodejs. Пропишем в PATH папку NodeJS и NPM. Сделаем это в файле init.bat который вызывается при запуске консоли
rem Добавить NodeJS и NPM
set PATH=%PATH%;c:\Program Files\nodejs\;%APPDATA%\npm\
Запустим консоль и выполним следующие команды (по этой инструкции) в папке сайта
# Обновим/установим npm командой до последней версии
npm install npm -g
# Установим Vue CLI 3 для работы с Vue https://cli.vuejs.org/ru/guide/
npm install @vue/cli -g
# Создадим проект ui на Vue
vue create ui
# Перейдем в созданный проект
cd ui
# Добавим плагин Vuetify https://github.com/vuetifyjs/vue-cli-plugin-vuetify
vue add vuetify
Скорректируем настройки, создав в директории проекта файл vue.config.js
module.exports = {
outputDir: "./../public/vue", // Директория для вывода сгенерированных файлов ресурсов
runtimeCompiler: true, // Включать компилятор шаблонов в итоговый файл
// Обязательно для корректной работы!
};
Изменим точку входа src\main.js
import Vue from "vue";
import kebabCase from 'lodash/kebabCase'
import "./plugins/vuetify";
//
Vue.config.productionTip = false
// Подключить и зарегистрировать компоненты из директории .components
const requireComponent = require.context(
// Относительный путь до каталога компонентов
'./components',
//'./../../app/Modules/Template/vue', Эта директория не работает
// Обрабатывать или нет подкаталоги
true,
// Регулярное выражение для определения файлов базовых компонентов
/\w+\.(vue|js)$/
)
requireComponent.keys().forEach(fileName => {
// Получение конфигурации компонента
const componentConfig = requireComponent(fileName)
// Получение имени компонента в PascalCase
const componentName = "s-"+kebabCase(
// Удаление из начала `./` и расширения из имени файла
fileName.replace(/^\.\/(.*)\.\w+$/, '$1')
)
/* eslint-disable no-console */
console.log('fileName',fileName,'=>',componentName);
/* eslint-enable no-console */
// Глобальная регистрация компонента
Vue.component(
componentName,
// Поиск опций компонента в `.default`, который будет существовать,
// если компонент экспортирован с помощью `export default`,
// иначе будет использован корневой уровень модуля.
componentConfig.default || componentConfig
)
})
// Сохранить ссылку на Vue глобально
window.Vue = Vue;
Мы указали что компоненты следует искать в директории components и регистрировать их с именем s-[<имя директории>-]<имя файла в kebabCase>
Создадим Vue компонент и сохраним его в файл src\components\Template\Base.vue
<template>
<v-app id="inspire">
<v-navigation-drawer fixed v-model="drawer" app>
<v-list dense>
<v-list-tile>
<v-list-tile-action>
<v-icon>home</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title><a href="#">Home</a></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile>
<v-list-tile-action>
<v-icon>contact_mail</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Contact</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar fixed app>
<v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
<v-toolbar-title>Application 3</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>search</v-icon>
</v-btn>
<v-tooltip left>
<v-btn fab icon slot="activator">
<v-avatar size="48px" color="grey lighten-4">
<img src="/images/guest.png" alt="avatar" />
</v-avatar>
</v-btn>
<span>@ВоЙти!</span>
</v-tooltip>
</v-toolbar>
<v-content>
<v-container fluid fill-height>
<v-layout justify-center align-center>
<slot></slot>
</v-layout>
</v-container>
</v-content>
<v-footer class="pa-3">
<v-spacer></v-spacer>
<span>© 2017</span>
</v-footer>
</v-app>
</template>
<script>
export default {
data: function() {
return {
drawer: null
};
}
};
</script>
<style></style>
Создадим Vue компонент и сохраним его в файл src\components\Html.vue
<template><span></span></template>
<script>
export default {
};
</script>
Создадим Vue компонент и сохраним его в файл src\components\Test.vue
<template>
<v-btn small color="primary">[<slot></slot>]</v-btn>
</template>
<script>
export default {
data: () => ({})
};
</script>
<style></style>
Создадим шаблон в папке проекта сайта app\Modules\Template\views\vue.php
<?php
$files = [
'js'=>[],
'css'=>[]
];
\App\Init::fetchFiles( base_path("public/vue"),function($file) use (&$files) {
if( !$file->isDir() ) {
$ext = $file->getExtension();
if( !array_key_exists($ext,$files) ) {
$files[$ext] = [];
}
$files[$ext][] = substr($file->getRelativePath(),6);
}
});
$menuItems = [
[
'url'=>'#',
'title'=>"Пункт меню 1"
],
[
'url'=>'#',
'title'=>"Пункт меню 2"
],
[
'url'=>'#',
'title'=>"Пункт меню 3"
]
];
?>
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<?php
foreach($files['css'] as $item) {
echo '<link href="'.$item.'" rel="stylesheet">';
}
?>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<h1>Валера</h1>
<div id="app">
<s-template-base :menuItems="menuItems">
<s-html>
<b>Меню</b>
<ol>
<?php
foreach($menuItems as $item) {
echo '<li><a href="'.$item['url'].'">'.$item['title'].'</a></li>';
}
?>
</ol>
</s-html>
Данные страницы {<s-test>Тестовый компонент</s-test>}
</s-template-base>
</div>
<?php
foreach(array_reverse($files['js']) as $item) {
echo '<script src="'.$item.'"></script>';
}
?>
<script>
new window.Vue({
el: "#app",
data : function() {
return {
menuItems : <?php echo json_encode($menuItems);?>
}
}
});
</script>
</body>
</html>
Определим роутинг в routes\web.php
$router->get('/', function () use ($router) {
return view('Template::vue');
});
и получим красивую страницу на которой мы уже можем использовать компоненты vuetifyjs и свои компоненты s-html и s-test.
Вот тут можно выбрать другой вариант верстки страницы.
Компиляция компонентов vue в js
rem Компиляция
npm run build
rem Компиляция для режима разработки. Файл будет пересобран при изменении какого либо файла из сборки
npx vue-cli-service build --watch
Как можно заметить компоенты Vue находятся отдельно от модулей. Это связано с тем, что проект Vue CLI 3 не позволяет обращаться с файлами за пределами папки проекта (по крайней мере так я понял невозможность подключить vue-компонент из внешней по отношению к папке проекта директории). Не очень удобно когда модуль разделен по разным папкам (php Lumen отдельно, а vue компоненты отдельно). И в дальнейшем я постараюсь это исправить. Самое очевидное - это переместить проект Lumen внуть папки проекта Vue CLI 3.