#php #laravel #vue.js #nuxt.js
Вопрос:
У меня возникли некоторые проблемы с добавлением фильтрации поиска в реальном времени на стороне клиента в мой проект Nuxt JS, который извлекает данные из моего API Laravel 8. Мой API Laravel 8 использует paginate()
метод для разбиения моих результатов на страницы из моей базы данных и возврата некоторого JSON, в котором data
массив содержит все записи для текущей страницы.
Мой интерфейс содержит таблицу с v-for
циклическим отображением некоторых отфильтрованных результатов, filteredDomains
которые, по сути, получают данные после того, как запрос к моему API получает результаты.
Дело в том, что мой поиск в реальном времени на строительство, но только на первой странице, и я хотел бы, чтобы это фильтр и поиск по всем страницам, как если бы они были одной странице (что они и ранее были, и он работал раньше, теперь, когда он с разбиением на страницы, это не делает)
Что я упускаю?
<b-row>
<b-col>
<b-form-input
style="padding-right: 10rem;"
v-model="search.domain"
type="text"
size="lg"
maxlength="256"
placeholder="Start typing a domain...">
</b-form-input>
</b-col>
</b-row>
<b-row>
<b-col>
<div class="table-responsive">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Domain</th>
<th scope="col">Registrar</th>
</tr>
</thead>
<tbody>
<tr v-for="(domain, index) in filteredDomains" :key="index" class="domain-row">
<td class="text-center" style="min-width: 60px;">
...
</td>
<td :style="domain.has_valid_ssl == 1 ? 'min-width: 260px;' : 'min-width: 150px;'">
...
</td>
<td style="min-width: 150px;">
...
</td>
</tr>
</tbody>
</table>
</div>
</b-col>
</b-row>
<b-row>
<b-col>
<b-pagination
v-model="page"
:total-rows="domains.total"
:per-page="domains.per_page"
first-number
last-number
pills
></b-pagination>
</b-col>
</b-row>
И мой сценарий таков:
export default {
data () {
return {
page: this.$route.query.page ? this.$route.query.page : 1,
hasErrors: false,
isLoading: true,
search: {
domain: ''
},
domains: []
}
},
created () {
this.getDomains()
},
methods: {
/*
** Get domains
*/
getDomains () {
this.hasErrors = false
this.$axios.get(`${process.env.API_URL}/api/domains?page=${this.page}`, { timeout: 60000 }).then(res => {
if (res.data.success) {
this.isLoading = false
this.hasErrors = false
const domains = res.data.domains.data.length > 0 ? res.data.domains : []
if (domains.data amp;amp; domains.data.length > 0) {
for (const [index, domain] of domains.data.entries()) {
if (typeof domain.registrar != 'string' || domain.registrar == null) continue
domain.registrar = JSON.parse(domain.registrar)
}
}
this.domains = domains
}
}).catch(err => {
this.isLoading = false
this.hasErrors = true
})
}
/*
** Navigate to a page
*/
navigateToPage (page) {
try {
const goTo = page
this.page = parseInt(goTo)
this.$router.push({
query: {
page: this.page
}
})
this.getDomains()
} catch (err) {}
}
},
computed: {
/*
** Filter domains for searchable domains
*/
filteredDomains () {
if (!this.domains.data) {
return []
}
return this.domains.data.filter(domain => {
return domain.domain.toLowerCase().includes(this.search.domain.toLowerCase())
})
}
},
watch: {
page (val) {
this.navigateToPage(this.page)
}
}
}
Может быть, мне нужно выполнить for
цикл внутри моей filteredDomains
функции, чтобы построить список всех доменов и отфильтровать этот список? Хотя это кажется излишним…
Ответ №1:
При том, как вы в настоящее время используете разбиение на страницы, в ваших данных есть только одна страница доменов, возвращаемая из API. По умолчанию это будет первая страница, поэтому ваш код ведет себя так, как ожидалось.
Чтобы исправить это, я вижу два варианта:
- Соберите все домены и отфильтруйте их (как вы сами предложили). Вы также можете реализовать разбиение на страницы на стороне клиента, если хотите сохранить эту функцию.
- Передайте свой запрос на поиск в свой API. Таким образом, фильтрацию необходимо будет выполнить на стороне сервера, и будут возвращены только отфильтрованные домены.
Какой из них лучше подходит для вашей ситуации, зависит от количества предметов. Если предметов относительно мало, я бы предложил первый вариант, так как он сохраняет всю логику в одном месте. Однако, если есть сотни или даже тысячи элементов, я бы предложил второй вариант, поскольку базы данных часто лучше оптимизированы для выполнения такого рода фильтрации.
В любом случае вам следует подумать о добавлении отмены, чтобы повысить производительность. Без отмены подписки ваши данные будут просматриваться снова и снова после каждой отдельной буквы, которую пользователь вводит в поле поиска. При отключении данные будут отфильтрованы только после того, как пользователь перестанет печатать в течение определенного промежутка времени (обычно около 300 мс).
Комментарии:
1. Спасибо за это, это помогает мне проверить мое направление!