Laravel, Vue 3 및 Tailwind를 사용하여 프로젝트 템플릿 만들기 - 섹션 3
Laravel, Vue 3 및 Tailwind를 사용하여 프로젝트 템플릿 만들기
제3부<-왔구나.
한 페이지 애플리케이션을 통해 직접 인증하는 것과 달리, Laravel에서 제공하는 기본 인증을 사용하여 SPA 서비스의 뷰에 액세스하는 것이 좋습니다.내가 보기에 이것은 더욱 간단한 시작 방식의 하나다.사용자가 인증을 통과하면 Sanctum은 단일 API 요청에 대한 인증을 제공합니다.
성소를 설치하다
대부분의 Laravel의 첫 번째 패키지와 마찬가지로 설치가 간단합니다.
composer
설치를 통해 자산을 발표하고 필요한 이전을 실행할 것입니다.composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
이어서 산텀의 중간부품을 api
중간부품 그룹에 추가할 것입니다.// app/Http/Kernel.php
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
기본적으로 Laravel은 routes/api.php
에 간단한 루트를 포함하고 인증된 사용자의 User
모델만 되돌려줍니다.우리가 해야 할 일은 SPA가 이 경로에 접근할 수 있도록 지정한 중간부품을 업데이트하는 것이다.// routes/api.php
...
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
API 사용
이제 우리는 새로운 구성 요소에서 출력을 호출하고 표시할 수 있는 정상적인 작업 단점이 생겼다.우리는 이 구성 요소에 사용할 것이다 composition API.
// resources/js/components/Dashboard.vue
<template>
<h1 class="text-2xl font-bold mb-2">Dashboard</h1>
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
{{ user }}
</div>
</div>
</template>
<script>
import { ref, onMounted } from 'vue';
export default {
setup(props, {}) {
const user = ref({});
function getUser() {
axios.get('/api/user/')
.then(response => user.value = response.data)
.catch(error => user.value = error);
}
onMounted(() => {
getUser();
});
return {
user
}
},
};
</script>
구성 요소를 등록하고 설치하기 전에 빠르게 살펴보겠습니다.Vue의 mounted
생명주기 갈고리를 이용하여 함수를 실행하고 있습니다. 이 함수는 axios
((resources/js/bootstrap.js
에 연결된 창) 을 사용하여 get 요청을 통해 사용자 데이터를 가져옵니다.통화가 성공하든 안 하든 결과는 나타날 것이다.그것을 라비 보기에 연결합시다.// resources/views/dashboard.blade.php
...
<div id="app" class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<dashboard />
</div>
</div>
...
// resources/js/app.js
require("./bootstrap");
require('alpinejs');
import { createApp } from "vue";
import Home from "./components/Home.vue";
import Dashboard from "./components/Dashboard.vue";
const app = createApp({
components: {
Home,
Dashboard
}
});
app.mount("#app");
/register
에 새 사용자를 등록하면 dashboard
보기로 리셋됩니다. 이 보기에서 새 구성 요소가 사용자 데이터를 토해냅니다.이렇게!우리는 새로운 기능을 구축하기 위해 사용할 수 있는 API와 작업 흐름을 가지고 있다.이제 미친 듯이 실행할 준비가 되어 있지만, 떠날 때 칼날 템플릿과 Vue 구성 요소의 혼합 보기를 보면 적합하지 않습니다.SaaS의 우호적인 전면에 좋은 출발점을 만들어 드리겠습니다.
401개의 오류 문제가 발생하면 Sanctum의 상태 구성에 포함되지 않은 도메인에서 요청을 보낼 수 있습니다.BrowserSync를 사용하는 것을 좋아하고, 서로 다른 항목 사이를 뛰어넘는 경향이 있기 때문에, 때때로 나는 최종적으로 "localhost: 3002"에서 나의 앞부분을 실행하는데, 기본적으로 그것을 포함하지 않는다.
애플리케이션 구축
우리가 수영 센터를 가지고 있다고 말할 수 있도록 앞부분으로 돌아가서 간단한 틀을 세우자.기본 계획은 새로 추가된 구성 요소 사이를 탐색할 수 있도록 일반적인 관리 대시보드의 케이스를 만들고 설치하는 것입니다.
새 blade 파일을 추가하는 것부터 시작합니다. 이 파일은 프로그램 케이스를 보여 줍니다. 단지 이것뿐입니다.그리고 전용 컨트롤러로부터 보기를 제공하기 위해 노선을 업데이트할 것입니다.
// resources/views/app.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
</head>
<body>
<div id="app">
<app :user="{{ $user }}" />
</div>
</body>
</html>
// routes/web.php
...
use App\Http\Controllers\AppController;
...
Route::get('/app', [AppController::class, 'index'])->name('app');
Route::get('/app/{vue_capture?}', [AppController::class, 'app'])->where('vue_capture', '[\/\w\.\-\ \&\=]*');
...
// app/Http/Controllers/AppController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class AppController extends Controller
{
public function index()
{
return redirect('app/dashboard');
}
public function app()
{
return view('app', [
'user' => auth()->user()
]);
}
}
이 두 노선 중의 두 번째 노선은 네가 통상적으로 보는 것과 약간 다르다.우리는 단지 Regex를 사용하여 Vue에서 처리해야 할 모든 루트를 찾은 다음, 그 루트를 우리의 응용 프로그램에 서비스를 제공하는blade 보기로 가져갈 뿐입니다.저희는
/app
를 사용하여 저희 수욕센터에 서비스를 제공할 것이기 때문에 로그인할 때 방향을 바꿔야 합니다.사용자가 로그인할 때, 우리는 welcome.blade.php
에서 사용한 경로를 업데이트할 것입니다.// app/Providers/RouteServiceProvider.php
...
public const HOME = '/app';
...
// resources/views/welcome.blade.php
...
@auth
<a href="{{ url('/app') }}" class="text-sm text-gray-700 underline">Dashboard</a>
@else
<a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Login</a>
@if (Route::has('register'))
<a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
@endif
@endauth
...
그런 다음 Vue 3을 지원하는 Vue 라우터 4를 설치합니다.최고의 버전 제어는 아니지만 뭘 할 수 있어요?routes.js
파일을 추가하여 app.js
에 라우터를 생성하고 Vue 인스턴스에 추가합니다.npm install vue-router@4
// resources/js/app.js
...
import { createRouter, createWebHistory } from 'vue-router';
import routes from './routes.js';
const router = createRouter({
history: createWebHistory(),
routes: routes.routes,
});
...
app.use(router);
app.mount("#app");
// resources/js/routes.js
import Dashboard from './components/Dashboard.vue';
import AnotherComponent from './components/AnotherComponent.vue';
export default {
routes: [
{
path: '/app/dashboard',
component: Dashboard,
name: 'dashboard',
meta: {
title: 'Dashboard'
},
},
{
path: '/app/another-component',
component: AnotherComponent,
name: 'another-component',
meta: {
title: 'Another Component'
},
},
],
};
routes.js
파일에 자리 표시자 구성 요소를 추가하여 Dashboard
와 AnotherComponent
사이를 이동하여 Vue 라우터의 작동 상태를 확인할 수 있습니다.// resources/js/components/AnotherComponent.vue
<template>
<h1 class="text-2xl font-bold">Another Component</h1>
</template>
<script>
export default {};
</script>
이제 우리는 응용 프로그램 레이아웃만 있으면 그것을 한데 통합할 수 있다.판식에 많은 변화가 있기 때문에 우리는 다음 글에서 많은 변경을 할 것이기 때문에 지금은 마음대로 복제할 수 있다.// resources/js/components/App.vue
<template>
<div class="h-screen flex overflow-hidden bg-gray-50">
<div v-show="showMenu" class="md:hidden">
<div class="fixed inset-0 flex z-40">
<div class="fixed inset-0">
<div class="absolute inset-0 bg-gray-600 opacity-75"></div>
</div>
<div v-show="showMenu" class="relative flex-1 flex flex-col max-w-xs w-full bg-white">
<div class="absolute top-0 right-0 -mr-12 pt-2">
<button @click="showMenu = false" class="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none">
<span class="sr-only">Close sidebar</span>
<svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
<div class="flex-shrink-0 flex items-center px-4">
<img class="h-8 w-auto" src="/images/laravue3-logo.png" alt="logo">
</div>
<nav class="mt-5 px-2 space-y-1">
<router-link
v-for="(route, index) in $router.options.routes"
:key="index"
:to="{ name: route.name }"
exact
@click="showMenu = false"
class="hover:bg-gray-50 text-gray-600 hover:text-gray-900 group flex items-center px-2 py-2 text-base font-medium rounded-md"
>
{{ route.meta.title }}
</router-link>
</nav>
</div>
<div class="flex-shrink-0 flex border-t border-gray-200 p-4">
<a href="#" class="flex-shrink-0 group block">
<div class="flex items-center">
<div>
<img class="inline-block h-10 w-10 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixqx=DS9XwDWeLa&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
</div>
<div class="ml-3">
<p class="text-base font-medium text-gray-700 group-hover:text-gray-900">
{{ user.name }}
</p>
<p class="text-sm font-medium text-gray-500 group-hover:text-gray-700">
View profile
</p>
</div>
</div>
</a>
</div>
</div>
<div class="flex-shrink-0 w-14"></div>
</div>
</div>
<div class="hidden md:flex md:flex-shrink-0">
<div class="flex flex-col w-64">
<div class="flex flex-col h-0 flex-1 border-r border-gray-200 bg-white">
<div class="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
<div class="flex items-center flex-shrink-0 px-4">
<img class="h-8 w-auto" src="/images/laravue3-logo.png" alt="logo">
</div>
<nav class="mt-5 flex-1 px-2 bg-white space-y-1">
<router-link
v-for="(route, index) in $router.options.routes"
:key="index"
:to="{ name: route.name }"
exact
class="hover:bg-gray-50 text-gray-600 hover:text-gray-900 group flex items-center px-2 py-2 text-sm font-medium rounded-md"
>
{{ route.meta.title }}
</router-link>
</nav>
</div>
<div class="flex-shrink-0 flex border-t border-gray-200 p-4">
<a href="#" class="flex-shrink-0 w-full group block">
<div class="flex items-center">
<div>
<img class="inline-block h-9 w-9 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixqx=DS9XwDWeLa&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
</div>
<div class="ml-3">
<p class="text-sm font-medium text-gray-700 group-hover:text-gray-900">
{{ user.name }}
</p>
<p class="text-xs font-medium text-gray-500 group-hover:text-gray-700">
View profile
</p>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
<div class="flex flex-col w-0 flex-1 overflow-hidden">
<div class="md:hidden pl-1 pt-1 sm:pl-3 sm:pt-3">
<button @click="showMenu = true" class="-ml-0.5 -mt-0.5 h-12 w-12 inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<span class="sr-only">Open sidebar</span>
<svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<main class="flex-1 relative z-0 overflow-y-auto focus:outline-none" tabindex="0">
<div class="py-6">
<div class="max-w-7xl mx-auto px-4 sm:px-6 md:px-8">
<router-view></router-view>
</div>
</div>
</main>
</div>
</div>
</template>
<script>
import { ref } from 'vue';
export default {
props: {
user: {
type: Object,
required: true,
}
},
setup(props, {}) {
const showMenu = ref(false);
return {
showMenu,
user: props.user
}
}
}
</script>
이제 루트 Vue 인스턴스App.vue
에 등록하면 성공합니다.// resources/js/app.js
...
import App from "./components/App .vue";
...
const app = createApp({
components: {
App,
Home,
Dashboard
}
});
...
Vue 라우터 결론과 다음 단계
우리는 기능성 수욕 센터가 하나 있다!우리는 백엔드를 구축하고 기본적인 백엔드 작업을 해서 결과를 보여줘야 한다.나는 앞부분을 충실하게 하기 위해 한 편의 댓글을 더 보낼 것이다.우리는 백엔드처럼 신속하게 원형화할 수 있도록 전단을 설정할 것이다.동시에 나에게 어떻게 진전되었는지 알려줘!다음에 무엇을 보고 싶은지 평론을 남겨 주세요.
Reference
이 문제에 관하여(Laravel, Vue 3 및 Tailwind를 사용하여 프로젝트 템플릿 만들기 - 섹션 3), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/heynolnor/creating-a-project-template-using-laravel-vue-3-and-tailwind-part-3-1klj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)