使用TypeScript和Vue 3的组合API增强Laravel和Inertia.js,构建强大的SPA
简介
Laravel结合Inertia.js,为创建现代单页应用提供了一对强大的组合,这些应用在复杂性上与使用Vue.js或React的全前端框架相媲美。本文将引导您通过将Laravel与Inertia.js和Vue 3结合使用的过程,并进一步介绍TypeScript在Vue的Composition API中的使用。
先决条件
- 在您的本地机器上已安装Composer
- 已安装Node.js和npm/yarn
- 具备Laravel、Vue.js和TypeScript的基本知识
设置Laravel与Inertia.js
创建一个新的Laravel项目并导航到项目目录
composer create-project laravel/laravel inertia-example
cd inertia-example
使用Composer安装Inertia.js
composer require inertiajs/inertia-laravel
并发布Inertia.js配置
php artisan inertia:middleware
确保在app/Http/Kernel.php
中的web
中间件组末尾注册Inertia中间件。
集成Vue 3和TypeScript
在Laravel设置完成后,让我们将关注点转移到前端。安装Vue 3和Inertia.js的Vue适配器
npm install vue @inertiajs/vue3 @types/ziggy-js lodash --save-dev
添加TypeScript及其Vue插件
npm install typescript @vitejs/plugin-vue vue-tsc --save-dev
为TypeScript设置tsconfig.json
{
"compilerOptions":{
"allowJs":true,
"module":"ESNext",
"moduleResolution":"Node",
"target":"esnext",
"jsx":"preserve",
"strict":true,
"esModuleInterop":true,
"skipLibCheck":true,
"forceConsistentCasingInFileNames":true,
"noEmit":true,
"isolatedModules":true,
"types": ["vite/client"]
},
"include":[
"resources/js/**/*.ts",
"resources/js/**/*.d.ts",
"resources/js/**/*.vue"
]
}
现在,让我们创建所需的TypeScript类型
前往 resources/js
目录,创建一个名为 types
的目录,在该目录中创建一个 TS 文件名为 global.d.ts
,并将以下内容复制到文件中
import { PageProps as InertiaPageProps } from '@inertiajs/core';
import { AxiosInstance } from 'axios';
import ziggyRoute, { Config as ZiggyConfig } from 'ziggy-js';
import { PageProps as AppPageProps } from './';
declare global {
interface Window {
axios: AxiosInstance;
}
var route: typeof ziggyRoute;
var Ziggy: ZiggyConfig;
}
declare module 'vue' {
interface ComponentCustomProperties {
route: typeof ziggyRoute;
}
}
declare module '@inertiajs/core' {
interface PageProps extends InertiaPageProps, AppPageProps {}
}
为 Vue 中的路由处理安装 Ziggy
Ziggy 是由 Tighten 开发的一个包,用于在 Laravel 中共享来自 routes/web.php
的路由到客户端。
composer require tightenco/ziggy
更新前端构建工具
通过调整你的 vite.config.js
来配置 Vite 以使用 TypeScript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
import path from 'path';
export default defineConfig({
"plugins":[
laravel({
"input": [
"resources/css/app.css",
"resources/js/app.ts"
],
"refresh": true
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
})
],
});
修改 package.json
以包括 TypeScript 编译和 Vite 构建过程的脚本
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"ts-check": "vue-tsc --noEmit"
},
在 resources/js/app.ts
中更新你的入口点为 TypeScript,并确保将 resources/js/app.js
的扩展名更改为 app.ts
,以及将 bootstrap.js
更改为 bootstrap.ts
。
import './bootstrap';
import '../css/app.css';
import { createApp, h, DefineComponent } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { ZiggyVue } from '../../vendor/tightenco/ziggy/dist/vue.es';
const appName = window.document.getElementsByTagName('title')[0]?.innerText || 'Laravel';
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob<DefineComponent>('./Pages/**/*.vue')),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue, Ziggy)
.mount(el);
}, progress: {
color: '#4B5563',
},});
定义路由和视图
在 resources/views/app.blade.php
中创建布局文件
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}" class="h-full bg-gray-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title inertia>{{ config('app.name', 'Laravel') }}</title>
<!-- Fonts -->
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
<!-- Scripts -->
@routes
@vite(['resources/js/app.ts', "resources/js/Pages/{$page['component']}.vue"])
@inertiaHead
</head>
<body class="font-sans antialiased h-full">
@inertia
</body>
</html>
在 routes/web.php
中定义你的 Inertia 路由
Route::get('/', function () {
return Inertia\Inertia::render('Welcome');
});
Route::get('/about', function () {
return Inertia\Inertia::render('About');
});
确保你在 resources/js/Pages
目录中创建了相应的 Vue 组件。
使用 TypeScript 与 Vue 的 Composition API
为了在 Vue 组件中利用 TypeScript,使用 <script setup lang="ts">
语法,这简化了 Composition API 的使用。
示例 resources/js/Pages/Welcome.vue
<script setup lang="ts">
import { ref } from 'vue';
import { Link } from '@inertiajs/vue3';
const greeting = ref('Welcome to Your Vue.js + TypeScript App');
</script>
<template>
<h1>{{ greeting }}</h1>
<Link href="/about">Go to About page</Link>
</template>
以及另一个 About.vue
<template>
<h1>{{ greeting }}</h1>
<Link href="/">Go to Welcome page</Link>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { Link } from '@inertiajs/vue3';
const greeting = ref('Welcome to About page');
</script>
结论
将 TypeScript 与 Laravel、Inertia.js 以及 Vue 3 的 Composition API 集成可能在最初时显得有些挑战,但它对开发效率和性能的提升是非常值得的。通过这种设置,你可以获得 TypeScript 的类型检查能力、Vue 3 的反应性和可组合性,以及 Inertia.js 提供的无缝交互性,所有这些都在一个强大的 Laravel 应用程序中。
为了进一步探索,可以考虑深入了解 TypeScript 的高级功能、Vuex 或 Pinia 中的状态管理,以及 Inertia 路由链接的自动类型生成。
driesvints 赞同了这篇文章