搜索和过滤功能仍然无法正常工作(Vue JS)
Search and filter features still doesn't work properly (Vue JS)
我正在弄清楚我的搜索和过滤功能如何才能正常工作。
我创建了一个搜索功能,并通过 stock
、distance
、price
和 time response
从搜索结果中筛选。我的搜索功能 运行 不错。但是,我做的过滤功能还是不行。
我想在进行搜索后进一步过滤搜索,当其中一个下拉列表发生变化时,有股票和距离等选项,搜索结果项也会根据过滤器发生变化(例如:股票) 是否可用。
还有其他过滤器,例如价格和时间响应。当我点击价格时,项目将按照最低价格到最高价格排序。当我点击时间响应时,搜索项目将按响应从快到晚的顺序排列。
案例
在Type
中,我选择BMW
。然后我点击搜索按钮。将显示 2 个类型为 BMW
的项目结果。然后,在过滤器 Distance
中,我选择 500 KM
。它应该只显示 1 个结果。但是过滤器不起作用。
如果有 6 件商品结果,我点击 price
商品将从最低价格到最高价格排序
我做了如下代码,谁能帮我解决这个问题?
new Vue({
el: '#app',
data: {
selectedType: '',
selectedCountry: '',
selectedYear: '',
selectedStock:'',
selectedDistance:'',
items: [{
name: 'Carthy',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1900',
response: 'fast'
},
{
name: 'Holand',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1050',
response: 'fast'
},
{
name: 'Nolan',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1000',
response: 'fast'
},
{
name: 'Edgar',
type: 'bmw',
year: '2020',
country: 'belgium',
stock: 'available',
distance: '5000',
price: '1200',
response: 'fast'
},
{
name: 'John',
type: 'bmw',
year: '2019',
country: 'england',
stock: 'available',
distance: '500',
price: '1500',
response: 'fast'
},
{
name: 'Axel',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'sold',
distance: '500',
price: '1600',
response: 'late'
}
],
searchResult: [],
itemsToShow: 2,
totalItems: 0,
sortByPrice: true,
sort: 'price',
sortByTime: true,
sort: 'time'
},
computed:{
filterItem: function() {
let filterStock = this.selectedStock,
filterDistance = this.selectedDistance
return this.searchResult.filter(function(item) {
let filtered = true
if (filterStock && filterStock.length > 0) {
filtered = item.stock == filterStock
}
if (filtered) {
if (filterDistance && filterDistance.length > 0) {
filtered = item.distance == filterDistance
}
}
return filtered
})
}
},
methods: {
search: function() {
let filterType = this.selectedType,
filterCountry = this.selectedCountry,
filterYear = this.selectedYear
this.itemsToShow = 2;
this.searchResult = this.items.filter(function(item) {
let filtered = true
if (filterType && filterType.length > 0) {
filtered = item.type == filterType
}
if (filtered) {
if (filterCountry && filterCountry.length > 0) {
filtered = item.country == filterCountry
}
}
if (filtered) {
if (filterYear && filterYear.length > 0) {
filtered = item.year == filterYear
}
}
return filtered
})
},
priceSort: function(){
this.sortByPrice = !this.sortByPrice
if(this.sortByPrice)
this.sort = 'price'
},
timeSort: function(){
this.sortByTime = !this.sortByTime
if(this.sortByTime)
this.sort = 'time'
}
},
mounted() {
this.search()
}
})
.list-item{
margin-top:50px;
}
#app{
position:relative;
padding-bottom: 200px;
}
span{
margin: 0 15px;
cursor:pointer;
}
.filter-box{
margin-top:15px;
}
.card{
box-shadow:0px 10px 16px rgba(0,0,0,0.16);
width:400px;
padding:20px 30px;
margin-bottom:30px;
}
button{
background-color: #1cf478;
border:none;
padding: 10px 25px;
font-weight:bold;
border-radius: 15px;
}
select{
border:none;
padding: 10px 15px;
background-color:#c1c1c1;
border-radius:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.1/vue.js"></script>
<div id="app">
<div class="search-box">
<select v-model="selectedType">
<option value="" disabled selected hidden>Type</option>
<option value="mercedes">Mercedes</option>
<option value="bmw">BMW</option>
</select>
<select v-model="selectedCountry">
<option value="" disabled selected hidden>Country</option>
<option value="belgium">Belgium</option>
<option value="england">England</option>
</select>
<select v-model="selectedYear">
<option value="" disabled selected hidden>Year</option>
<option value="2019">2019</option>
<option value="2020">2020</option>
</select>
<button @click="search">Search</button>
</div>
<div class="filter-box">
<h6>Filter:</h6>
<select v-model="selectedStock" @change="filterItem">
<option value="" disabled selected hidden>Stock</option>
<option value="sold">Sold</option>
<option value="available">Available</option>
</select>
<select v-model="selectedDistance" @change="filterItem">
<option value="" disabled selected hidden>Kilometers</option>
<option value="500">500 KM</option>
<option value="5000">5000 KM</option>
<option value="10000">10.000 KM</option>
</select>
<span class="price" @click="priceSort">Price</span>
<span class="response" @click="timeSort">Time Response</span>
</div>
<section class="result">
<div class="container-fluid">
<div class="row list-item" v-for="(item, id) in searchResult" :key="id">
<div class="col-3 card" v-if="id < itemsToShow">
<p>Name: {{ item.name }}</p>
<p>Car: {{ item.type }}</p>
<p>Year: {{ item.year }}</p>
<p>Country: {{ item.country }}</p>
<p>Price: ${{ item.price }}</p>
<p>stock: {{ item.stock }}</p>
<p>distance: {{ item.distance }}</p>
</div>
</div>
<div class="row">
<div class="col-12">
<button @click="itemsToShow += 1">Load More</button>
</div>
</div>
</div>
</section>
</div>
使用 @change
事件并调用 filterItem
计算 属性。每当 select 值更改时,将调用计算的 属性。
<select v-model="selectedStock" @change="filterItem">
请参阅此 codesandbox 以获得基于您的代码的工作演示。
我的改动
- 在
searchResult
之上的 data
中添加 filterResult
以处理过滤结果,我们只将 filterResult
作为结果呈现。这样就把'search'和'filter'的逻辑分开了,逻辑更清晰。
- 每当过滤器 selected 值发生变化时,我们都会触发
filterItems
方法作为 @click
处理程序。 (之前您使用的是计算 属性 并且这不够简单,我们可以简单地为 @change
调用一个方法并更新 filter results
数据。
- 每当触发搜索时,我们都会重置过滤器 select 值,并显示所有搜索结果(
filterResult
与 searchResult
相同,因为没有过滤器值) .
- 关于排序,对于两个排序
span
元素,我们只能更新this.sort
数据,并使用watch
来触发sortItems
方法每当排序标准改变,会更简单。您可能需要根据需要调整 sortItems
方法。当然,您可以为这两个 'sort' 按钮编写两个单独的方法,这完全取决于您:)
我正在弄清楚我的搜索和过滤功能如何才能正常工作。
我创建了一个搜索功能,并通过 stock
、distance
、price
和 time response
从搜索结果中筛选。我的搜索功能 运行 不错。但是,我做的过滤功能还是不行。
我想在进行搜索后进一步过滤搜索,当其中一个下拉列表发生变化时,有股票和距离等选项,搜索结果项也会根据过滤器发生变化(例如:股票) 是否可用。 还有其他过滤器,例如价格和时间响应。当我点击价格时,项目将按照最低价格到最高价格排序。当我点击时间响应时,搜索项目将按响应从快到晚的顺序排列。
案例
在Type
中,我选择BMW
。然后我点击搜索按钮。将显示 2 个类型为 BMW
的项目结果。然后,在过滤器 Distance
中,我选择 500 KM
。它应该只显示 1 个结果。但是过滤器不起作用。
如果有 6 件商品结果,我点击 price
商品将从最低价格到最高价格排序
我做了如下代码,谁能帮我解决这个问题?
new Vue({
el: '#app',
data: {
selectedType: '',
selectedCountry: '',
selectedYear: '',
selectedStock:'',
selectedDistance:'',
items: [{
name: 'Carthy',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1900',
response: 'fast'
},
{
name: 'Holand',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1050',
response: 'fast'
},
{
name: 'Nolan',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'available',
distance: '500',
price: '1000',
response: 'fast'
},
{
name: 'Edgar',
type: 'bmw',
year: '2020',
country: 'belgium',
stock: 'available',
distance: '5000',
price: '1200',
response: 'fast'
},
{
name: 'John',
type: 'bmw',
year: '2019',
country: 'england',
stock: 'available',
distance: '500',
price: '1500',
response: 'fast'
},
{
name: 'Axel',
type: 'mercedes',
year: '2020',
country: 'england',
stock: 'sold',
distance: '500',
price: '1600',
response: 'late'
}
],
searchResult: [],
itemsToShow: 2,
totalItems: 0,
sortByPrice: true,
sort: 'price',
sortByTime: true,
sort: 'time'
},
computed:{
filterItem: function() {
let filterStock = this.selectedStock,
filterDistance = this.selectedDistance
return this.searchResult.filter(function(item) {
let filtered = true
if (filterStock && filterStock.length > 0) {
filtered = item.stock == filterStock
}
if (filtered) {
if (filterDistance && filterDistance.length > 0) {
filtered = item.distance == filterDistance
}
}
return filtered
})
}
},
methods: {
search: function() {
let filterType = this.selectedType,
filterCountry = this.selectedCountry,
filterYear = this.selectedYear
this.itemsToShow = 2;
this.searchResult = this.items.filter(function(item) {
let filtered = true
if (filterType && filterType.length > 0) {
filtered = item.type == filterType
}
if (filtered) {
if (filterCountry && filterCountry.length > 0) {
filtered = item.country == filterCountry
}
}
if (filtered) {
if (filterYear && filterYear.length > 0) {
filtered = item.year == filterYear
}
}
return filtered
})
},
priceSort: function(){
this.sortByPrice = !this.sortByPrice
if(this.sortByPrice)
this.sort = 'price'
},
timeSort: function(){
this.sortByTime = !this.sortByTime
if(this.sortByTime)
this.sort = 'time'
}
},
mounted() {
this.search()
}
})
.list-item{
margin-top:50px;
}
#app{
position:relative;
padding-bottom: 200px;
}
span{
margin: 0 15px;
cursor:pointer;
}
.filter-box{
margin-top:15px;
}
.card{
box-shadow:0px 10px 16px rgba(0,0,0,0.16);
width:400px;
padding:20px 30px;
margin-bottom:30px;
}
button{
background-color: #1cf478;
border:none;
padding: 10px 25px;
font-weight:bold;
border-radius: 15px;
}
select{
border:none;
padding: 10px 15px;
background-color:#c1c1c1;
border-radius:10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.1/vue.js"></script>
<div id="app">
<div class="search-box">
<select v-model="selectedType">
<option value="" disabled selected hidden>Type</option>
<option value="mercedes">Mercedes</option>
<option value="bmw">BMW</option>
</select>
<select v-model="selectedCountry">
<option value="" disabled selected hidden>Country</option>
<option value="belgium">Belgium</option>
<option value="england">England</option>
</select>
<select v-model="selectedYear">
<option value="" disabled selected hidden>Year</option>
<option value="2019">2019</option>
<option value="2020">2020</option>
</select>
<button @click="search">Search</button>
</div>
<div class="filter-box">
<h6>Filter:</h6>
<select v-model="selectedStock" @change="filterItem">
<option value="" disabled selected hidden>Stock</option>
<option value="sold">Sold</option>
<option value="available">Available</option>
</select>
<select v-model="selectedDistance" @change="filterItem">
<option value="" disabled selected hidden>Kilometers</option>
<option value="500">500 KM</option>
<option value="5000">5000 KM</option>
<option value="10000">10.000 KM</option>
</select>
<span class="price" @click="priceSort">Price</span>
<span class="response" @click="timeSort">Time Response</span>
</div>
<section class="result">
<div class="container-fluid">
<div class="row list-item" v-for="(item, id) in searchResult" :key="id">
<div class="col-3 card" v-if="id < itemsToShow">
<p>Name: {{ item.name }}</p>
<p>Car: {{ item.type }}</p>
<p>Year: {{ item.year }}</p>
<p>Country: {{ item.country }}</p>
<p>Price: ${{ item.price }}</p>
<p>stock: {{ item.stock }}</p>
<p>distance: {{ item.distance }}</p>
</div>
</div>
<div class="row">
<div class="col-12">
<button @click="itemsToShow += 1">Load More</button>
</div>
</div>
</div>
</section>
</div>
使用 @change
事件并调用 filterItem
计算 属性。每当 select 值更改时,将调用计算的 属性。
<select v-model="selectedStock" @change="filterItem">
请参阅此 codesandbox 以获得基于您的代码的工作演示。
我的改动
- 在
searchResult
之上的data
中添加filterResult
以处理过滤结果,我们只将filterResult
作为结果呈现。这样就把'search'和'filter'的逻辑分开了,逻辑更清晰。 - 每当过滤器 selected 值发生变化时,我们都会触发
filterItems
方法作为@click
处理程序。 (之前您使用的是计算 属性 并且这不够简单,我们可以简单地为@change
调用一个方法并更新filter results
数据。 - 每当触发搜索时,我们都会重置过滤器 select 值,并显示所有搜索结果(
filterResult
与searchResult
相同,因为没有过滤器值) . - 关于排序,对于两个排序
span
元素,我们只能更新this.sort
数据,并使用watch
来触发sortItems
方法每当排序标准改变,会更简单。您可能需要根据需要调整sortItems
方法。当然,您可以为这两个 'sort' 按钮编写两个单独的方法,这完全取决于您:)