Мои мысли и проекты
Создаем сайт на Lumen (Laravel) - Frontend с vue + vuetifyjs

Настало время прикрутить библиотеку которая будет отвечать за 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>&copy; 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.

Как можно заметить в текущей версии меню не отображается в шаблоне. Я не стал это делать так как в дальнейшем планирую отдельный модуль SPage с работы со страницей, который и будет использоваться.

Вот тут можно выбрать другой вариант верстки страницы.

Компиляция компонентов 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.

0

Комментарии

Чтобы оставлять комментарии войдите на сайт. Вы можете сделать это через социальную сеть