Vue можна використовувати не лише як SPA, а й «острівцями» на серверних сторінках Laravel: змонтувати компонент на елемент Blade-шаблону. Тут є кілька пасток.
1. Конфлікт фігурних дужок. Blade і Vue обидва використовують {{ }}. Blade обробить їх першим і спробує виконати PHP:
<div id="app">
@{{ message }} {{-- @ - Blade лишить {{ message }} для Vue --}}
@verbatim
<p>{{ user.name }}</p> {{-- цілий блок без обробки Blade --}}
@endverbatim
</div>
2. Шаблони в HTML (in-DOM) розбирає браузер, а не компілятор Vue:
- регістр не враховується:
<BlogPost :postTitle="t">браузер перетворить на<blogpost :posttitle="t">. У HTML-шаблонах - лише kebab-case:<blog-post :post-title="t">; - самозакривних тегів немає:
<my-component />браузер прочитає як відкритий тег, і наступні елементи стануть його дітьми. Потрібно<my-component></my-component>; - обмеження вкладеності: у
<table>,<ul>,<select>браузер викидає «чужі» теги. Компонент-рядок таблиці - через<tr is="vue:table-row">.
У .vue-файлах цих обмежень немає - їх компілює Vite.
3. Потрібна повна збірка Vue з компілятором шаблонів, якщо шаблон береться з DOM сторінки: псевдонім vue → vue/dist/vue.esm-bundler.js. Збірка більша і вимагає unsafe-eval у Content Security Policy.
4. Безпека - найважливіше. Якщо в області, на яку змонтовано Vue, є дані користувача, виведені Blade, Vue скомпілює їх як частину шаблону. Коментар із текстом {{ ... }} стане виразом Vue - Blade екранує HTML, але не фігурні дужки. Захист:
- не монтувати Vue на області з користувацьким вмістом;
- позначати такі ділянки
v-pre(Vue не компілюватиме вміст); - передавати дані в компоненти через props з JSON, а не вбудовувати в розмітку.
5. Передача даних з Laravel у компонент:
<user-profile :user='@json($user)'></user-profile>
{{-- або --}}
<script>window.App = @js(['user' => $user->only('id', 'name')]);</script>
@json/Js::from безпечно екранують значення. Передавайте лише потрібні поля - усе, що в JSON, видно в коді сторінки.
Альтернативи «острівцям»: Inertia (повноцінні Vue-сторінки з маршрутизацією Laravel) або Livewire з Alpine, якщо інтерактивність помірна.