Con su sintaxis limpia y expresividad, entre muchas otras cualidades, Laravel es uno de los frameworks PHP más populares utilizados por los desarrolladores.
Antes de que apareciera Laravel UI, una de sus características principales era admitir Vue.js de forma predeterminada desde Laravel v5.3 a v6. Vue es un marco de interfaz de usuario de JavaScript moderno para crear interfaces de usuario.
¿Por qué Laravel y Vue combinan tan bien?
Estas son algunas de las ventajas clave de usar Laravel con Vue para crear un flujo de trabajo completo para sus proyectos:
-
El código fuente se fusiona en un proyecto en lugar de tener proyectos separados para el backend y el frontend.
-
Instalación y configuración sencillas
-
Una única implementación puede manejar ambos marcos.
¿Qué es un balneario? (aplicación de una sola página)
¿Cómo ingresa una aplicación de una sola página (SPA para abreviar) a la configuración del BIOS en Windows 10? Tutorial gráfico detallado de ocho pasos Los nuevos datos se cargan dinámicamente desde el servidor web a la página web sin actualizar toda la página.
Ejemplos de sitios populares que utilizan SPA incluyen gmail.com y youtube.com; en otras palabras, los SPA son en gran medida omnipresentes. La mayoría de los paneles de administración que probablemente utilice a diario se crearon utilizando SPA.
Beneficios del Spa:
-
La experiencia del usuario es más flexible
-
datos de caché en el navegador
-
tiempo de carga rápido
Desventajas del SPA:
-
Puede dañar el SEO (optimización de motores de búsqueda)
-
posibles problemas de seguridad
-
Consume muchos recursos del navegador.
configuración del proyecto
Esta publicación demostrará cómo desarrollar una aplicación de tareas pendientes que permita a los usuarios registrarse para obtener una cuenta y agregar tareas.
En este tutorial se utiliza Laravel 9, el cual requiere PHP 8.1 y Vue 3; también necesitamos PHP y NGINX instalados.
Comencemos con el siguiente comando:
compositor crear-proyecto --prefer-dist laravel/laravel laravel-vue-demo
A continuación, instalaremos las dependencias de JavaScript.
instalación npm
Antes de que podamos agregar Vue a nuestro proyecto, debemos instalar algunos paquetes.
Además, se debe instalar plugin-vue ¿ Cómo pueden los teléfonos móviles Xiaomi comprobar si el hardware está roto? ¿Cómo detectar el teléfono móvil Xiaomi por sí solo? Porque Laravel 9 viene con Vite en lugar de webpack-mix, que es el paquete de Laravel para JavaScript. Ahora hagamos esto:
npm instala vue@siguiente vue-loader@siguiente @vitejs/plugin-vue
Abra el archivo llamado y agregue a la configuración: vite.config.js``vue()
importar {defineConfig} desde 'vite'; importar laravel desde 'laravel-vite-plugin'; importar vue desde '@vitejs/plugin-vue' exportar default defineConfig({ complementos: [ vue(), laravel([ 'resources/css/app.css', 'resources/js/app.js', ]), ], });
Edite el archivo y el fragmento de código para el arranque de la aplicación Vue 3: app.js
require('./bootstrap'); importar {createApp} desde 'vue' importar aplicación desde './App.vue' createApp (App).mount("#app")
Cree un archivo llamado y agregue el siguiente contenido: App.vue
<template> <h1> Hola, Vuejs con Laravel </h1> </template> <script> export default { setup() { } } </script>
Finalmente, abra el archivo ubicado en la carpeta y agregue el siguiente contenido: bienvenido.blade.php ``resources/views
<!DOCTYPE html> <html> <head> .... @vite('resources/css/app.css') </head> <body> <div id="app"></div> @vite( 'recursos/js/app.js') </body> </html>
Para obtener una vista previa de nuestra aplicación, necesitamos iniciar nuestra aplicación Vue y el servidor Laravel en dos terminales/líneas de comando diferentes :
npm run dev php servicio artesanal
Para construir nuestra aplicación de tareas pendientes, necesitamos crear algunos archivos más. Vue creará varias páginas, principalmente:
-
página de inicio de sesión
-
pagina de registro
-
pagina de inicio
Para comunicarnos con los puntos finales de Laravel, necesitamos instalar Axios:
npm instala axios
enrutamiento de vista
Hay varias estrategias de enrutamiento disponibles en Vue usando el paquete vue-router ; estas estrategias también se conocen como patrones históricos.
Cuando un usuario solicita una ruta como esta (que devolverá un error 404 cuando se actualice la página), podemos confiar en Laravel para detectar cualquier ruta alternativa y luego entregar el archivo Blade que contiene nuestra aplicación. http://localhost:8000/casa
Por tanto, usaremos el modo HTML5:
Ruta::get('/{vue_capture?}', function() { return view('bienvenido'); })->where('vue_capture', '[\/\w\.-]*'); importar {createRouter, createWebHistory} desde 'vue-router'; const enrutador = createRouter({ historial: createWebHistory(), rutas: [ { ruta: '/', componente: () => import('./pages/Login.vue') }, { ruta: '/register', componente: () => import('./pages/Register.vue') }, { ruta: '/home', componente: () => import('./pages/Home.
Debido a la simplicidad del proyecto, básicamente utilizamos Laravel Sanctum para manejar la autenticación de la página de inicio de sesión y luego guardamos nuestros tokens en el almacenamiento local.
Para que otras solicitudes tengan éxito, el token se adjuntará al encabezado, lo que permitirá que Laravel identifique al usuario solicitante.
Aquí está nuestra página de inicio de sesión:
A continuación se muestra nuestra página de registro:
Finalmente, aquí están los bloques de código relevantes para ambos:
<!--Login.vue--> <plantilla> <div class="mx-auto w-4/12 mt-10 bg-blue-200 p-4 rounded-lg"> <div class="bg - white sombra-lg redondeado-lg px-8 pt-6 pb-8 mb-2 flex flex-col" > < h1 class="text-gray-600 py-5 font-bold text-3xl"> Iniciar sesión </h1> <ul class="list-disc text-red-400" v-for="(valor, índice) en errores" :key="index" v-if="tipo de errores === 'objeto'"> <li>{ {valor[0]}}</li> </ul> <p class="lista-disco texto-rojo -400" v-if="tipo de errores === 'cadena'">{ {errores}}</p> <form método="post" @submit.prevent="handleLogin"> <div class="mb- 4"> <etiqueta class="block text-grey-dark text-sm font-bold mb-2" for="nombre de usuario" > Dirección de correo electrónico </label> <input class="apariencia de sombra-ninguno borde redondeado w-full py-2 px- 3 texto-gris-oscuro" id="nombre de usuario" tipo="texto" v-model="form.correo electrónico" requerido /> </div> <div class="mb-4"> <label class="bloque de texto-gris-oscuro texto-sm fuente-bold mb-2" for="contraseña" > Contraseña </label> <input class="apariencia de sombra-ninguno borde borde-rojo redondeado w-full py-2 px-3 texto-gris-oscuro mb-3" id="contraseña" tipo="contraseña" v - model= Se requiere "form.contraseña" /> </div> <div class="flex items-center justify-between"> <button class="bg-blue-500 hover:bg-blue-900 texto-blanco fuente-negrita py-2 px-4 redondeado" tipo="enviar" > Iniciar sesión </button> <router-link class="inline-block align-baseline font-bold text-sm text-blue hover:text-blue-darker" to="register" > Regístrate </router-link> </div> </ formulario> </div> </div> </template> exportar predeterminado { setup() { const errores = ref() const enrutador = useRouter(); forma constante = reactiva({ correo electrónico: '', contraseña: '',mensaje || "" } } } devolver { formulario, errores, handleLogin, } } }
Las vistas/páginas de Vue manejan todos, como crear, eliminar, actualizar y enumerar todos. Todas las operaciones realizan solicitudes al punto final con un token de usuario para autorización con Axios. Hogar
Veamos cómo se ven, seguido de los fragmentos relevantes:
<!-- Inicio --> <plantilla> <div class="w-6/12 p-10 mx-auto"> <div class="flex justify-between"> <h1 class="text-2xl"> Todo </h1> <span class="capitalize">Bienvenido { { usuario && nombre.usuario }}, <button class="text-orange-500 subrayado al pasar el mouse:sin subrayado redondeado-md" @click="handleLogout">Cerrar sesión</button></span> </div> <input type="text" class="p-2 w-64 borde redondeado-md" v- model="todo" placeholder="Ingresa tu tarea"/> <button class="bg-blue-600 text-white px-5 py-2 rounded-md ml-2 hover:bg-blue-400" @click= "addTodo">Agregar</button> <Loader v-if="isLoading"/> <ul class="border-t mt-3 cursor-pointer"> <li :class="`py-3 border-b text-gray-600 ${val.has_completed ? 'line-through' : ''}` " v-for="(val, idx) en todos" :key="idx"> <input type="checkbox" :checked="val.has_completed" @click="checked(idx)"/> <span @ click="checked(val, idx)" class="pl-3">{ { val.title }} </span> <button class="float-right bg-red-400 px-2 text-white font- negrita redondeada-md hover:bg-red-600" @click="deleteTodo(val,idx)">× </button> </li> </ul> </div> </template> setup() { const todo = ref('') const todos = ref([]) const usuario = ref() const isLoading = ref() let router = useRouter(); onMounted(() => { autenticación() handleTodos() }); autenticación const = async () => { isLoading.value = true try { const req = await request('get', '/api/user') user.value = req.data } catch (e) { await router.push ('/') } } const handleTodos = async () => { try { const req = await request('get', todos.value = req.data.data } catch (e) { await router.push('/') } isLoading.value = false } const handleNewTodo = async (title) => { try { const data = {title: title } const req = await request('post', '/api/todos', data) if (req.data.message) { isLoading.value = false return alert(req.data.message) } todos.value.push( req.data.data) } catch (e) { await router.push('/') } isLoading.valor = falso } const handleLogout = () => { localStorage.removeItem('APP_DEMO_USER_TOKEN') router.push('/') } const addTodo = () => { if (todo.value === "") { return alert("Todo no puede estar vacío"); } isLoading.value = true handleNewTodo(todo.value) todo.value = "" } const check = async (val, index) => { try { const data = {has_completed:!val.has_completed} const req = await request( 'poner', `/api/todos/${val.id}`, datos) if (req.data.message) { isLoading. return alert(req.data.message) } todos.value[index].has_completed = !val.has_completed } catch (e) { await router.push('/') } isLoading.value = false } const deleteTodo = async ( val, index) => { if (window.confirm("¿Estás seguro")) { intenta { const req = await request('delete', `/api/todos/${val.id}`) if (req .data.message) { isLoading.value = false todos.value.splice(index, 1) } } catch (e) { await router.push('/') } isLoading.value = false } }
Para Laravel crearemos lo siguiente:
-
controlador(AuthController``TodoController)
-
modelo(,Todo``Usuario)
-
ruta (api)
-
middleware(). autenticación: santuario
Nuestra ruta está en , que maneja todos los puntos finales que utiliza Vue. api.php
Ruta::post('/auth/register', [AuthController::class, 'register']); Ruta::post('/auth/login', [AuthController::class, 'login']); Ruta::apiResource('todos', TodoController::class)->middleware('auth:sanctum'); Ruta::middleware('auth:sanctum')->get('/usuario', función (Solicitud $solicitud) { return $solicitud->usuario(); });
La lógica de registro registra al usuario y crea un token. Controlador de autenticación
registro de función pública (Solicitud $ solicitud): \Illuminate\Http\JsonResponse { intentar { //Validado $validateUser = Validator::make($request->all(), [ 'nombre' => 'requerido', 'correo electrónico' => 'requerido|correo electrónico|único:usuarios,correo electrónico', 'contraseña' => 'requerido' ]); if($validateUser->fails()){ return respuesta()->json([ 'status' => false, 'mensaje' => 'error de validación', 'errores' => $validateUser->errors() ] , 401); } $usuario = Usuario::crear([ 'nombre' => $solicitud->nombre, 'correo electrónico' => $solicitud->correo electrónico, 'contraseña' => Hash::make($solicitud->contraseña) ], 201); return respuesta()->json([ 'estado' => verdadero, 'mensaje' => 'Usuario creado exitosamente', 'token' => $usuario->createToken("API_TOKEN")->plainTextToken ], 200); } catch (\Throwable $e) { return respuesta()->json([ 'estado' => falso, 'mensaje' => $e->getMessage() ], 500); } }
Una solicitud de verificación de inicio de sesión verifica que el usuario existe y luego crea un token:
inicio de sesión de función pública (Solicitud $ solicitud): \Illuminate\Http\JsonResponse { intentar { //Validado $validateUser = Validator::make($request->all(), [ 'correo electrónico' => 'requerido', 'contraseña' => 'requerido' ]); if ($validateUser->fails()){ return respuesta()->json([ 'estado' => falso, 'mensaje' => 'error de validación', 'errores' = > $validarUsuario->errores() ], 401); } si (!Auth:: return respuesta()->json([ 'estado' => falso, 'mensaje' => 'El correo electrónico y la contraseña no existen.', ], 401); } $ usuario = Usuario::where('correo electrónico', $solicitud->correo electrónico)->primero(); return respuesta()->json([ 'estado' => verdadero, 'mensaje' => 'Registrado En Successfully', 'token' => $user->createToken("API_TOKEN")->plainTextToken ], 200); } catch (\Throwable $e) { return respuesta()->json([ 'status' = > falso, } }
El punto final POST para agregar una nueva tarea pendiente se administra mediante un método en el controlador de tareas pendientes: . tienda``/api/todos
almacén de funciones públicas(Solicitud $solicitud): \Illuminate\Http\JsonResponse { $datos = Todo::where('user_id', $solicitud->usuario()->id)->where('título', $solicitud- >título); if ($datos->primero()) { return respuesta()->json(['estado' => falso, 'mensaje' => 'Ya existe']); } $req = $solicitud->todos(); $req['user_id'] = $solicitud->usuario()->id; $datos = Todo::create($req); return respuesta()->json(['estado' => verdadero, 'datos' => $datos], 201); }
Esto administrará el punto final de actualización, al que se llama cuando el usuario completa una tarea pendiente, en . Todo``/api/todos/id
actualización de función pública (Solicitud $solicitud, $id): \Illuminate\Http\JsonResponse { $validateUser = Validator::make($request->all(), [ 'has_completed' => 'requerido', ]); if ($validateUser->fails()) { return respuesta()->json([ 'status' => false, 'mensaje' => 'error de validación', 'errores' => $validateUser->errors() ] , 401); } $datos = Todo::find($id); $datos->has_completed = $solicitud->has_completed; $datos->actualizar(); devolver respuesta()->json(['estado' => verdadero, 'datos' => $datos], 202); }
Cuando un usuario elimina, se llamará al punto final, que lo manejará: Todo``/api/todos/id
función pública destruir(int $id): \Illuminate\Http\JsonResponse { throw_if(!$id, 'falta el ID de todo'); Todo::findOrFail($id)->delete(); return respuesta()->json(['estado' => verdadero, 'mensaje' => 'todo eliminado']); }
¡Excelente trabajo, creamos una aplicación de una sola página usando Laravel y Vue! A continuación se muestra el resultado final de nuestra aplicación de tareas pendientes. ¡Bien hecho, creamos una aplicación de una sola página usando Laravel y Vue! :
en conclusión
Pudimos determinar que era mucho más sencillo crear una aplicación de lista de tareas y autenticación de usuario simple con Vue y Laravel que con una combinación tradicional de PHP/Vue, lo que probablemente requirió más trabajo de configuración.
En mi opinión, la combinación de Vue y Laravel facilita el desarrollo de aplicaciones de una sola página porque no hay necesidad de preocuparse por el enrutamiento, el middleware o el manejo de CORS. Déjeme saber sobre sus experiencias en el desarrollo de SPA en la sección de comentarios a continuación.