在Laravel中集成 Vue.js 组件,使用Laravel9+vue3进行全栈开发

957次阅读
没有评论

在Laravel中集成 Vue.js 组件,使用Laravel9+vue3进行全栈开发
Laravel 和 Vue.js 是 Web 开发中常用的两个强大的框架。 Laravel 提供了全面的后端解决方案,而 Vue.js 提供了灵活高效的方式来构建交互式前端组件。尽管 Laravel 为动态界面提供了 Inertia.js 和 Livewire 等替代选项,一般情况下的项目,都是采用前后端分离开发,laravel负责后端接口,vue.js负责前端页面,但在某些情况下,特别是对于全栈开发者,开发人员更喜欢将 Vue.js 直接集成到他们的 Laravel 项目中。本文讲解具体集成方法。
先决条件:开始之前,请确保您具备以下条件:

  • Laravel 框架的基础知识
  • 熟悉 Vue3 基础知识

    安装Laravel

    本文不讲解php和composer的安装和配置了,这两个是最基本的,如果这两个都不会安装,您也不用看本文了,我们直接通过composer来安装laravel项目。请在终端中运行以下命令:

    composer create-project laravel/laravel:^9.0 laravel9-vue3
    cd laravel9-vue3
    php artisan serve

    当可以访问到http://127.0.0.1:8000/页面时即安装成功

    安装 Laravel Breeze

    Laravel Breeze 是一个轻量级的脚手架包,它为 Laravel 应用程序中的身份验证提供了最小的设置。要安装 Laravel Breeze,请在终端中运行以下命令:

    composer require laravel/breeze --dev

    安装后,通过运行以下命令生成身份验证脚手架:

    php artisan breeze:install

    安装数据库并做好配置

    我们可以通过宝塔或者phpmysqladmin数据库管理工具创建数据库。安装好数据库之后,在项目根目录配置好.env文件的数据库信息

    运行数据库迁移

    现在,运行数据库迁移来设置身份验证和用户管理所需的表。在终端中执行以下命令:

    php artisan migrate

    安装依赖项并构建静态资源

    要安装必要的前端依赖项并构建资源,请运行以下命令:

    npm install
    npm run dev

    启动本地Laravel服务

    前面的npm run dev不要终止,开启另一个命令行窗口,要在本地启动Laravel服务,请运行以下命令:

    php artisan serve

    现在就可以使用提供的 URL 在 Web 浏览器中访问项目了。

    安装Vue.js和Vue Loader

    为了增强使用 Vue.js 组件时的开发体验,我们将安装 Vue Loader。 Vue Loader 是 Webpack 加载器,可以编写单文件 Vue 组件。它将 HTML、CSS 和 JavaScript 组合在一个文件中,从而简化了组件结构。
    要安装 Vue Loader,请运行以下命令:

    npm install vue@next vue-loader@next

    安装vite的vue.js插件

    Vite 是下一代前端构建工具,Laravel 提供了一个插件将其与您的 Laravel 应用程序集成。运行以下命令安装 Vite 的 Vue.js 插件:

    npm i @vitejs/plugin-vue 

    更新Vite配置

    要配置 Vite,我们打开项目根目录下的 vite.config.js 文件,并使用以下代码更新它:

    
    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    import vue from '@vitejs/plugin-vue';

export default defineConfig({
plugins: [
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
laravel({
input: [
'resources/css/app.css',
'resources/js/app.js',
],
refresh: true,
}),
],
resolve: {
alias: {
'@': '/resources/js',
'vue': 'vue/dist/vue.esm-bundler.js'
},
},
});


# **编写vue页面**
修改resources/js目录下的app.js
```php
import './bootstrap';

import { createApp } from 'vue';
import ComponentA from './components/ComponentA.vue';
import App from './App.vue';

const app = createApp(App);

app.component('ComponentA', ComponentA);

app.mount("#app");

app.js同目录下新建App.vue,内容如下

<template>
  <div>
    <h1>Laravel9+Vue3快速开发</h1>
    <component-a></component-a>
  </div>
</template>

<script>
  import ComponentA from './components/ComponentA.vue'

  export default {
    components:{
      ComponentA
    }
  }
</script>

<style>

</style>

在 resources/js 目录中创建一个名为“components”的新文件夹。在“components”文件夹中,创建一个 Vue.js 组件文件,例如 ComponentA.vue ,并定义组件的模板和逻辑。例如:

<template>
    <h1>Laravel9 + Vue3.0独立开发者快速开发</h1>
</template>

修改Blade模板

为了使 Vue.js 组件与 Laravel 的 Blade 模板引擎配合使用,我们需要对 Blade 文件进行一些修改。由于laravel默认首页为,我们打开 welcome.blade.php 。修改一下内容,注意要在html头部加入@vite(['resources/css/app.css', 'resources/js/app.js']),修改后内容大致如下

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.bunny.net/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

        <!-- Styles -->
        <style>
            /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.text-center{text-align:center}.text-gray-200{--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity))}.dark\:bg-gray-900{--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity))}.dark\:border-gray-700{--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity))}.dark\:text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.dark\:text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.dark\:text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}}
        </style>

        <style>
            body {
                font-family: 'Nunito', sans-serif;
            }
        </style>
        <!-- Scripts -->
        @vite(['resources/css/app.css', 'resources/js/app.js'])        
    </head>
    <body class="antialiased">
        <div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center py-4 sm:pt-0">
            @if (Route::has('login'))
                <div class="hidden fixed top-0 right-0 px-6 py-4 sm:block">
                    @auth
                        <a href="{{ url('/dashboard') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Dashboard</a>
                    @else
                        <a href="{{ route('login') }}" class="text-sm text-gray-700 dark:text-gray-500 underline">Log in</a>

                        @if (Route::has('register'))
                            <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 dark:text-gray-500 underline">Register</a>
                        @endif
                    @endauth
                </div>
            @endif

            <div></div>
            <div class="max-w-6xl mx-auto sm:px-6 lg:px-8" id="app">

            </div>
        </div>
    </body>
</html>

此时,我们访问http://127.0.0.1:8000/就可以访问出来页面了
在Laravel中集成 Vue.js 组件,使用Laravel9+vue3进行全栈开发

从数据库读取数据

为了演示从数据库中获取数据,我们在组件目录中创建另一个名为 ComponentB.vue 的组件。ComponentB.vue的内容如下

<script setup>
const props = defineProps({
    user: Object
});
</script>

<template>
    <h1>你好, {{ user.name }},欢迎光临</h1>
</template>

我们直接通过axios(默认自动集成)获取后端数据,在web.php文件新增一个路由,内容如下:

Route::get('/author', function () {
    return response()->json(['name'=>'老俊']);
});

修改一下App.vue,获取后端数据并展示

<template>
  <div>
    <h1>Laravel9集成Vue3组件</h1>
    <component-a></component-a>
    <component-b :user="user"></component-b>
  </div>
</template>

<script>
import ComponentA from './components/ComponentA.vue'
import ComponentB from './components/ComponentB.vue'

import axios from 'axios';

export default {
    name: 'app',
    data(){
        return {
            user: {
                name:''
            }
        }
    },
    components:{
        ComponentA,
        ComponentB
    },
    mounted() {
        axios.get('/author').then(res=>{
            console.log(res)
            this.user = res.data
        })
    },
    methods:{

    }
}
</script>

<style>
</style>

修改好之后,再访问http://127.0.0.1:8000/就可以看到数据了
点此获取开源代码
至此,本教程结束

正文完
 

公众号