protonemedia / laravel-splade-core
一个用于在Laravel Blade中使用Vue 3的Composition API的包。
资助包维护!
pascalbaljet
protonemedia
Requires
- php: ^8.1
- illuminate/contracts: ^10.0
- mck89/peast: ^1.15
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.0
- dev-main
- 4.0.1
- 4.0.0
- 3.2.0
- 3.1.1
- 3.1.0
- 3.0.0
- 2.4.0
- 2.3.0
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.1
- 2.1.0
- 2.0.0
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6.0
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.0
- 1.2.0
- 1.1.0
- 1.0.1
- 1.0.0
- dev-wrap-vue-import-into-blade-view
- dev-experimental-slot-support
- dev-slot-wip
- dev-php83
- dev-experimental-props-passthrough
This package is auto-updated.
Last update: 2024-03-14 21:00:15 UTC
README
一个用于在Laravel Blade中使用Vue 3的Composition API的包。
⚠️ 此包已被废弃: 关于Splade的思考:我休息了一周来四处看看并反思。
赞助Splade
我们非常珍视我们的社区支持,在我们努力创建和提供免费Laravel包的过程中。如果您觉得我们的包对您有益,并且您的工作依赖于它,我们恳请您支持赞助其维护和发展。处理问题和拉取请求是一项耗时的工作,您的帮助将非常感激。感谢您考虑我们的请求!❤️
为什么这是实验性的?
虽然这个包附带了一个全面的测试套件,但需要注意的是,它处于实验阶段。这是一个新包,我还没有在生产环境中使用过。目前,我使用原始Splade v1包来满足我的生产需求。然而,我计划在2023年第四季度将这个新包整合到两个新项目中。还值得一提的是,我尚未确认此包与原始Splade包的所有功能完全兼容。
这与现有的Laravel Splade包有什么关系?
Laravel Splade目前提供了大量功能
- 使用Blade构建单页应用
- 20+个交互式组件
- 广泛的表单和表格组件
- 模态框、滑动面板、Toast、SEO、SSR等
虽然这很好,并且极大地帮助了使用Laravel构建SPAs,但它也使得维护和扩展包变得更加困难。这就是我决定将Splade拆分成多个包的原因
- Splade Core:此包。它仅包含在Blade中使用Vue 3的Composition API的核心功能。没有预构建的组件。没有标记。没有CSS。只是核心功能。
- Splade Navigation:原始Splade包中的SPA和导航组件(模态框、滑动面板、Toast、SEO、SSR等)
- Splade UI:原始Splade包中的UI组件,不包括表单和表格组件。
- Splade Form:原始Splade包中的表单组件。
- Splade Table:原始Splade包中的表格组件。
需求
- PHP 8.1
- Laravel 10
- Vue 3.3
- Vite 4.0
功能
- 新项目的自动安装器
- 在Blade模板中使用Vue 3的Composition API
- 支持Blade组件和Blade视图
- 从前端调用Blade组件方法
- 从前端刷新Blade组件而无需重新加载页面
- 使用Blade属性作为Vue属性
- 在Blade模板中访问Js/Vue生态系统
限制
- 内联Blade组件不受支持(模板在组件类中定义,而不是在单独的
.blade.php
文件中)。
安装
您可以通过composer安装此包
composer require protonemedia/laravel-splade-core
自动安装
对于新项目,您可以使用 splade:core:install
Artisan 命令来自动安装该软件包
php artisan splade:core:install
这将安装 JavaScript 软件包,创建根布局和一个演示组件,并将所需的配置添加到您的 app.js
和 vite.config.js
文件中。运行此命令后,您可能需要运行 npm install
来安装 JavaScript 依赖项,然后运行 npm run dev
来启动 Vite。
npm install npm run dev
手动安装
首先,您应该安装伴随的 JavaScript 软件包
npm install @protonemedia/laravel-splade-core @protonemedia/laravel-splade-vite
Splade Core 会自动为您的所有 Blade 模板生成 Vue 组件。默认情况下,它们存储在 resources/js/splade
。您不需要将这些文件提交到您的仓库,因为它们在运行 Vite 时会自动生成。要初始化此目录,请运行以下命令
php artisan splade:core:initialize-directory
在您的主要 JavaScript 文件中(app.js
),您必须创建一个新的 Vue 应用实例并使用 Splade Core 插件。遵循 Laravel 的约定,app.js
文件存储在 resources/js
,因此您可以将相对路径 ./splade
传递给插件选项
import { createApp } from 'vue/dist/vue.esm-bundler.js' import { SpladeCorePlugin } from '@protonemedia/laravel-splade-core' createApp() .use(SpladeCorePlugin, { components: import.meta.glob('./splade/*.vue', { eager: true }), }) .mount('#app')
在您的 vite.config.js
文件中,您必须添加 laravel-splade-vite
插件。确保在 laravel
和 vue
插件之前添加
import { defineConfig } from 'vite' import laravel from 'laravel-vite-plugin' import vue from '@vitejs/plugin-vue' import spladeCore from '@protonemedia/laravel-splade-vite' export default defineConfig({ plugins: [ spladeCore(), laravel({ ... }), vue({ ... }), ], })
最后,在您的根布局文件中,您必须为 Vue 应用创建根元素,并必须包含一个用于 Splade 模板堆栈的脚本标签。这必须在 #app
元素之前完成
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>My app</title> @vite("resources/js/app.js") </head> <body> <script> @stack('splade-templates') </script> <div id="app"> {{ $slot }} </div> </body> </html>
与 Blade 组件一起使用
您可以使用默认的 make:component
Artisan 命令来生成 Blade 组件
php artisan make:component MyComponent
在 Blade 模板中,您可以使用 <script setup>
标签使您的组件具有响应性
<script setup> const message = ref('Hello Vue!') const uppercase = computed(() => message.value.toUpperCase()) </script> <input v-model="message" /> <p v-text="uppercase" />
除了运行 Vite 开发服务器外,您不需要做任何其他事情。该组件将自动编译并注册为 Vue 组件。
Echo 语法
Blade 和 Vue 使用相同的花括号语法来渲染变量。这意味着您不能在模板中使用 {{ message }}
语法来渲染 Vue 变量。技术上,这是因为 Blade 编译器在 Vue 编译器之前。有两种方法可以解决这个问题
使用 v-html
或 v-text
指令
<p v-text="uppercase" />
或者,使用 @
符号来转义花括号
<p>@{{ uppercase }}</p>
组合 API 导入
在上面的第一个例子中,我们使用了 Vue 的组合 API 中的 ref
和 computed
函数。Splade Core 会自动为您导入这些函数。以下是所有自动导入的函数列表
computed
inject
nextTick
onActivated
onBeforeMount
onBeforeUnmount
onBeforeUpdate
onDeactivated
onErrorCaptured
onMounted
onUnmounted
onUpdated
provide
reactive
readonly
ref
watch
watchEffect
watchPostEffect
watchSyncEffect
属性继承
就像常规 Blade 组件一样,您可以使用 $attributes
变量来继承传递给组件的属性。这也适用于 v-model
这是 <x-form>
组件的模板
<script setup> const form = ref({ framework: 'laravel', }) </script> <form> <x-select v-model="form.framework" /> </form>
这是 <x-select>
组件的模板
<select {{ $attributes }}> <option value="laravel">Laravel</option> <option value="tailwind">Tailwind</option> <option value="vue">Vue</option> </select>
带有脚本标签的组件的继承
如果您正在传递属性的组件有一个 <script>
标签,则属性将作为 Vue props 传递给组件的根元素。如果您想将属性传递给不同的元素,可以使用 v-bind="$attrs"
指令
<script setup></script> <div class="wrapper"> <input v-bind="$attrs" /> </div>
Splade Core 会自动检测自定义指令。
元素引用
您可以使用 $refs
变量来访问元素引用。这不在 Vue 3 的组合 API 中自然工作,但在 Vue 2 中效果很好,所以我决定在 Splade Core 中再次添加它
<script setup> onMounted(() => { const creditcardEl = $refs.creditcard; }); </script> <input ref="creditcard" />
利用 Vue 生态系统
使用 Js/Vue 生态系统的库和包非常容易。以下是一个使用 Flatpickr 的示例。
<script setup> import flatpickr from "flatpickr"; const emit = defineEmits(["update:modelValue"]); onMounted(() => { let instance = flatpickr($refs.date, { onChange: (selectedDates, newValue) => { emit("update:modelValue", newValue); }, }); instance.setDate(props.modelValue); }); </script> <input ref="date" />
请注意,您可以在不定义它的前提下使用 props.modelValue
。Splade Core 会自动检测 modelValue
的使用并将它添加到 props
对象中。
调用 Blade 组件上的方法
如果您的 Blade 组件有一个 public
方法,您可以从模板中调用它,无论是脚本还是模板。Splade Core 会检测当前页面的 HTTP 中间件并将其应用到后续请求。您需要做的只是给方法添加 Vue
属性。
<?php namespace App\View\Components; use Illuminate\View\Component; use ProtoneMedia\SpladeCore\Attributes\Vue; class UserProfile extends Component { #[Vue] public function notify(string $message) { auth()->user()->notify($message); } public function render() { return view('components.user-profile'); } }
模板
<script setup> const message = ref('Hey there!') </script> <input v-model="message" placeholder="Enter a message" /> <button @click="notify(message)">Notify User</button> <p v-if="notify.loading">Notifying user...</p>
请注意,您可以使用 notify.loading
来检查方法是否正在运行。
警告
虽然原始中间件已应用于请求,但您仍然需要验证传入的数据。
将 Blade 变量作为 Vue Props 传递
您可以将 Blade 变量作为 Vue Props 传递。如果您想从后端传递数据到前端,这非常有用。您只需给属性添加 VueProp
属性即可。
<?php namespace App\View\Components; use Illuminate\View\Component; use ProtoneMedia\SpladeCore\Attributes\VueProp; class UserProfile extends Component { #[VueProp] public string $defaultMessage = 'Hey there!' }
现在您可以在模板和脚本标签中使用 defaultMessage
prop。您不需要在 props
对象中指定该 prop,因为 Splade Core 会自动为您完成。
<script setup> const defaultMessageInUpperCase = props.defaultMessage.toUpperCase(); </script> <label>Default message:</label> <p v-text="defaultMessage" />
将 Blade 变量作为 Vue Refs 传递
将 Blade 变量作为 Vue Refs 传递比作为 Vue Props 传递更强大。这样,您可以在模板中将变量用作响应式变量。您可以在前端更新它们,当您调用 Blade 组件方法时,后端上的值也会更新。您只需给属性添加 VueRef
属性即可。
<?php namespace App\View\Components; use Illuminate\View\Component; use ProtoneMedia\SpladeCore\Attributes\VueRef; class UserProfile extends Component { #[VueRef] public string $notification = 'Hey there!' #[Vue] public function notify() { auth()->user()->notify($this->notification); } public function render() { return view('components.user-profile'); } }
模板
<script setup></script> <input v-model="notification" placeholder="Enter a message" /> <button @click="notify">Notify User</button>
警告
小心您定义的公共属性。例如,如果您将 Eloquent 模型定义为公共属性,它将被序列化为 JSON 并传递到前端。请确保敏感属性已被 隐藏。
回调函数
您也可以从脚本中调用方法,而不是从模板中调用。这样,您可以使用 then
、catch
和 finally
。
<script setup> function notifyWithFixedMessage() { notify('Hey there!') .then(() => alert('User notified!')) .catch(() => alert('Something went wrong!')) .finally(() => { // }) } </script> <button @click="notifyWithFixedMessage">Notify User</button>
或者,您也可以将全局回调添加到 notify
方法中。
<script setup> notify.before((data) => { }) notify.then((response, data) => { }) notify.catch((e) => { }) </script> <input v-model="message" placeholder="Enter a message" /> <button @click="notify('Hey there!')">Notify User</button>
刷新组件
为了使组件可刷新,您必须将 Refreshable
中间件添加到路由中。
use ProtoneMedia\SpladeCore\Http\Refreshable::class; Route::get('/login', LoginController::class)->middleware(Refreshable::class);
然后,您可以使用 refreshComponent
方法来刷新组件。这将重新渲染组件并重新获取数据。
<script setup> const message = ref('Initial message') </script> <input v-model="message" placeholder="Enter a message" /> <small>User last updated: {{ auth()->user()->updated_at }}</small> <button @click="refreshComponent">Refresh</button>
与调用 Blade 方法类似,您可以使用 refreshComponent.loading
来检查组件是否正在刷新。您还可以使用带有 refreshComponent
的回调。
与 Blade 视图一起使用
如果您不想使用 Blade 组件,您也可以使用 Blade 视图。目前,不支持重新加载 Blade 视图。
就像使用 Blade 组件一样,您可以在 Blade 视图的顶部使用 <script setup>
标签。如果您正在扩展布局,请确保将 <script setup>
标签放在 slot 中。
<x-layout> <script setup> const message = ref('Hello Vue!') </script> <input v-model="message" /> </x-layout>
包含 Blade 视图
请注意,您在每个 Blade 视图中只能使用 一个 脚本标签。例如,如果您的 Blade 视图已经有一个脚本标签,您不能使用 @include
指令包含另一个带有脚本标签的 Blade 视图。如果您想这样做,将包含的 Blade 视图转换为 Blade 组件。
变更日志
有关最近更改的详细信息,请参阅 CHANGELOG。
贡献
有关详细信息,请参阅 CONTRIBUTING。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 pascal@protone.media 联系,而不是使用问题跟踪器。
鸣谢
许可证
MIT 许可证 (MIT)。更多信息请参阅 许可证文件。