在 Vue.js 中过滤流派数据(带有选择)

Posted

技术标签:

【中文标题】在 Vue.js 中过滤流派数据(带有选择)【英文标题】:Filter data for genres (with a select) in Vue.js 【发布时间】:2021-11-03 11:57:56 【问题描述】:

我正在使用 Laravel api.php 路由,我需要根据音乐家的共同流派来过滤他们,所以在单击选择后,我想切换页面并转到一个页面,其中有所有音乐家的选择的流派。

问题是,无论我从选择中选择哪种流派,它总是让我回到相同的三个音乐家,而且我不知道如何让那个 id 传递到过滤器函数中。

ps:现在我只是在同一个页面中显示音乐家,但最终结果应该显示在不同的页面中,正如我上面提到的那样。

这是我的代码:

ExampleComponent.vue 如下,这里我在寻找作为参数传递给 filter() 函数的 id 时遇到了问题。

<template>
    
        <div class="jumbotron bg-jumbotron">
            <div class="container">
                <div class="row">
                    <div class="col-xs-6 col-md-6 col-lg-6">
                        <h1 class="headline">Playing the mood</h1>
                    
                        <div class="form-group">
                            <select @change="filter(1)" class="form-control mb-2" id="exampleFormControlSelect1">
                                <option :value="genre.id" v-for="genre in genres" :key="genre.id"> genre.name </option>
                            </select>
                        </div>
                    </div>
                    <div v-for="musician in musicians" :key="musician.id">
                         musician.stagename 
                    </div>
                    <div class="col-xs-6 col-md-6 col-lg-6">
                        <img class="img-fluid" src="images/jumboimg.png" >
                    </div>
                </div>
            </div>
        </div>
    
</template>

<script>
    export default 
        name: 'ExampleComponent',

        data() 
            return 
                genres: [],
                musicians: []
            
        ,

        methods: 
            getGenres() 
                axios.get('http://127.0.0.1:8000/api/genres')
                .then( res => 
                    this.genres = res.data;
                    // console.log( this.genres )
                    
                )
                .catch( err => 
                    console.log( err )
                )
            ,

            filter(id) 
                axios.get(`http://127.0.0.1:8000/api/filter/$id`)
                .then( res => 
                    res.data.forEach( el => 
                        this.musicians = el.musicians
                    )
                    console.log( this.musicians )
                )
                .catch( err => 
                    console.log( err )
                )
            
        ,

        created() 
            this.getGenres()
            // this.filter(this.$routes.params.id)
        
    
</script>

api.php 路由

Route::middleware('auth:api')->get('/user', function (Request $request) 
    return $request->user();
);

Route::namespace('Api')->group( function() 

    Route::get('/genres', 'GenreController@index');
    Route::get('/filter/id', 'GenreController@filter');
);

类型控制器

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

use App\Genre;

class GenreController extends Controller

    public function index() 

        $genres = Genre::all();

        return response()->json($genres);
    

    public function filter($id) 
        

        $genres = Genre::where('id', $id)->with('musicians')->get();

        return response()->json($genres);
    

音乐家模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Musician extends Model

    protected $fillable = [
        'user_id', 
        'stagename',
        'slug', 
        'description',
        'bio',
        'services',
        'typology',
        'cover'
    ]; 

    public function user() 
        return $this->hasOne('App\User'); 
    

    public function genres() 
        return $this->belongsToMany('App\Genre'); 
    

类型模型

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Genre extends Model

    protected $fillable = [
        'name', 
        'slug'
    ]; 

    public function musicians() 
        return $this->belongsToMany('App\Musician'); 
    

【问题讨论】:

【参考方案1】:

GenreController 中的过滤方法必须返回音乐家,而你返回$genres,我认为你的过滤方法应该是这样的(考虑到音乐家和流派之间的关系):

public function filter($id) 

  $musicians = Musician::whereHas('genres', function($query) use ($id) 
    $query>where('id', '=', $id);
  )->get();
    
    return response()->json($musicians );

并在您的 vue 组件中记录 http://127.0.0.1:8000/api/filter/$id 的结果 以确保您从 url 得到什么响应。

【讨论】:

问题是我没有genre_id 外键,因为有一个数据透视表(genre_musician),其中所有流派都与相关音乐家相关联。那么我如何从枢轴中获取该genre_id? 请检查我的答案的编辑,我认为它现在应该可以工作【参考方案2】:

您手动将 id if 1 传递给 filter(1)

尝试将 v-model 应用于选择(输入绑定)。 https://vuejs.org/v2/guide/forms.html#Select

                    <div class="form-group">
                        <select @change="filter()"  v-model="filter_id" class="form-control mb-2" id="exampleFormControlSelect1">
                            <option:value="genre.id" v-for="genre in genres" :key="genre.id"> genre.name </option>
                        </select>
                    </div>

//数据

    data() 
        return 
            genres: [],
            musicians: [],
            filter_id:null
        
    ,

// 方法

filter() 
                axios.get(`http://127.0.0.1:8000/api/filter/$this->filter_id`)
                .then( res => 
                    res.data.forEach( el => 
                        this.musicians = el.musicians
                    )
                    console.log( this.musicians )
                )
                .catch( err => 
                    console.log( err )
                )
            

这里的想法是你有一个动态数据“filter_id”,它绑定到选择输入的值,然后传递给你的 axois 调用。

我也相信您可以更新您的请求控制器以使用 a

$musicians = App\Modles\Musician::with(['genere' => function ($query)  use ($id) 
    $query->whereId($id);
])->get();

然后在 axios (vue) 中,您可以只使用 this.musicians = response.data 并避免 foreach 循环。

【讨论】:

我刚刚尝试过,可能是对 Vue 部分的修复,但在 Laravel 中,我仍然必须从genre_musician 数据透视表中捕获该外键(genre_id)。否则它将总是返回相同的三个音乐家。 $musicians= Musician::whereHas('generes', function($q) use($id) $q-&gt;whereIn('id', $id); )-&gt;get(); $id 是您作为参数传递的genere的v-model filter_id 没用,我认为在 filter() 函数中找到获取该 id 的方法可以解决问题,但是如何解决呢? 我贴了上面的方法,你需要 v-model 并将 id 绑定到 select 然后在 axios 中传递它 我错过了@change="filter()" 中的参数(v-model),现在可以了! ;)

以上是关于在 Vue.js 中过滤流派数据(带有选择)的主要内容,如果未能解决你的问题,请参考以下文章

基于具有唯一值的数组创建多个动态选择过滤器以过滤 Vue.js 中的另一个数组

如果选择“全部”,则重置过滤器 Vue Js

带有逻辑的 Vue JS 选择

如何在vue js的过滤器搜索中添加大于等于的条件

如何在Vue js中绑定带有芯片的复选框(双向绑定)

使用带有 select2 指令的 vue.js 方法