如何将Laravel Blade变量传递给Vue.js并实现联动下拉框?
Hey there! Let's break down how to pass Laravel Blade variables to Vue and build that dependent dropdown you're working on—this is a super common use case, so I've got you covered.
First: Passing Blade Variables to Vue
The cleanest, safest way to pass PHP variables (like your $locations array) to Vue is using Laravel's built-in @json() directive. This converts your PHP data into valid JavaScript objects/arrays and handles escaping to avoid XSS issues—way better than trying to output raw variables or use hidden inputs (which is probably where you ran into problems earlier).
Option 1: Directly in a Vue Instance
If you're using a root Vue instance (not a single-file component), you can assign the variable directly in your data():
<div id="app"> <!-- Your dropdowns will go here --> </div> <script> new Vue({ el: '#app', data() { return { // Convert PHP $locations to a JS array/object locations: @json($locations), selectedCountry: null, selectedCity: null }; }, // We'll add computed properties and logic next }); </script>
Option 2: Pass to a Vue Component
If you're using Vue components (recommended for larger apps), pass the variable as a prop:
In your Blade template:
<location-dropdown :locations="@json($locations)"></location-dropdown>
In your Vue component:
export default { props: ['locations'], // Define the prop data() { return { selectedCountry: null, selectedCity: null }; } };
Building the Dependent Dropdowns
Assuming your $locations array looks something like this (from your Laravel controller):
$allLocations = [ ['country' => 'China', 'city' => 'Beijing'], ['country' => 'China', 'city' => 'Shanghai'], ['country' => 'USA', 'city' => 'New York'], ['country' => 'USA', 'city' => 'Los Angeles'], ];
We'll use Vue's computed properties to dynamically filter cities based on the selected country. Add these to your Vue instance/component:
computed: { // Get a list of unique countries from the locations data uniqueCountries() { return [...new Set(this.locations.map(item => item.country))]; }, // Filter cities based on the selected country filteredCities() { if (!this.selectedCountry) return []; // No country selected? Return empty return this.locations .filter(item => item.country === this.selectedCountry) .map(item => item.city); } }
Then add the dropdown HTML in your Blade template or component:
<!-- Country Dropdown --> <select v-model="selectedCountry"> <option value="" disabled>Select a country</option> <option v-for="country in uniqueCountries" :key="country" :value="country"> {{ country }} </option> </select> <!-- City Dropdown (disabled until a country is selected) --> <select v-model="selectedCity" :disabled="!selectedCountry"> <option value="" disabled>Select a city</option> <option v-for="city in filteredCities" :key="city" :value="city"> {{ city }} </option> </select>
Why Your Hidden Input Method Might Have Failed
If you tried using a hidden input like <input type="hidden" id="locations" value="{{ $locations }}">, you probably ran into issues because PHP arrays/objects get converted to string representations (like Array or Object) when output directly. This means JavaScript can't parse it into a usable array. Using @json() fixes this by outputting a valid JSON string that JavaScript can interpret immediately.
Quick Notes
- Make sure your
$locationsvariable is actually being passed to the Blade view (double-check your controller'sreturn view('user.profile', ['locations' => $allLocations]);line). - If you're using Vue 3, the syntax for creating the instance is slightly different (
createApp({...}).mount('#app')), but the core logic for passing props and using computed properties stays the same. - For more complex location structures (like nested arrays), adjust the computed properties to match your data shape.
内容的提问来源于stack exchange,提问作者drake24

