Closed shimoharuki closed 1 year ago
いつもお世話になっております オートコンプリート機能作成中
手詰まりしているのでご教授お願いしたいです
github公開されているオートコンプリート機能のフレームワークを使用したかったのですが jsの理解が乏しかったため jsの勉強も兼ねて自分で1から実装しました
header.js
document.addEventListener('DOMContentLoaded', () => { const jsSeacrchForm = document.getElementById('search-form') const jsConversion = document.querySelector("#conversion") jsSeacrchForm.addEventListener('input', async () => { const inputValue = jsSeacrchForm.value; // 予測変換の結果を取得する非同期処理(例としてダミーデータを使用) const predictions = await fetchPredictions(inputValue); // 予測変換の結果を HTML に変換して表示する const html = predictions.map(board => { return `<li><a href="/boards/${board.id}">${board.title}</a></li>`; }).reduce((a, b) => { return a + b }) jsConversion.innerHTML = html; }); async function fetchPredictions(inputValue) { // 予測変換の結果を取得する非同期処理を実装する const response = await fetch('/boards.json'); const data = await response.json(); // 入力文字列と部分一致する board をフィルタリングする const matchedBoard = data.filter(board => board.title.includes(inputValue)).slice(0, 3); console.log(data) return matchedBoard; } });
こちらのコードを作成し、 文字列が部分一致する投稿を取得しリンクにしてhtml内に表示 するメソッドを作成したのですが
文字列が部分一致する投稿を取得しリンクにしてhtml内に表示
const response = await fetch('/boards.json');のfetchが一度に取得できる数に限りがあると後で気づき
const response = await fetch('/boards.json');
document.addEventListener('DOMContentLoaded', () => { const jsSearchForm = document.getElementById('search-form'); const jsConversion = document.querySelector("#conversion"); jsSearchForm.addEventListener('input', async () => { const inputValue = jsSearchForm.value; // 予測変換の結果を取得する非同期処理(例としてダミーデータを使用) const predictions = await fetchPredictions(inputValue); // 予測変換の結果を HTML に変換して表示する const html = predictions .map(board => `<li><a href="/boards/${board.id}">${board.title}</a></li>`) .reduce((a, b) => a + b, ""); jsConversion.innerHTML = html; }); async function fetchPredictions(inputValue) { // 全記事を取得するための非同期処理 const allBoards = await fetchAllBoards(); // 入力文字列と部分一致する board をフィルタリングする const matchedBoard = allBoards .filter(board => board.title.includes(inputValue)) .slice(0, 3); return matchedBoard; } async function fetchAllBoards() { let allBoards = []; let page = 1; let limit = 10; // 1回の取得での記事数の上限 while (true) { const response = await fetch(`/boards.json?page=${page}&limit=${limit}`); const data = await response.json(); if (data.length === 0) { // 取得できる記事がなくなったらループを終了 break; } // 取得した記事を逆順に追加していく allBoards = data.concat(allBoards); page++; } return allBoards; } });
全記事を取得するまでループする処理を記述した コードにしたのですが
サーバーがとてつもなく重くなってしまいました。
全記事をサーバーを重くすることなく取得するコードにしたいのですが調べてもあまり出てこずで 詰まっているので教えていただきたいです。
header.html.erb
<header> <%= javascript_include_tag 'header' %> <nav class="navbar navbar-expand-lg navbar-light text-dark bg-dark py-4" id="home"> <%= link_to 'MagicalUsj', root_path, class: 'navbar-brand h1 text-white' %> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <%= render 'boards/search', q: @q, url: boards_path %> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item active"> <%= link_to 'お気に入り', likes_boards_path , class: "nav-link text-white" %> </li> <li class="nav-item"> <%= link_to 'おすすめ', recommendations_path, method: :post, class: 'nav-link text-white' %> </li> <li class="nav-item"> <%= link_to 'MyPage', profile_path, class: "nav-link text-white" %> </li> <li class="nav-item dropdown"> <%= link_to '記事', boards_path , class: "nav-link dropdown-toggle text-white", id: "navbarDropdown", role: "button", "data-toggle": "dropdown", "aria-haspopup": "true", "aria-expanded": "false" %> <div class="dropdown-menu" aria-labelledby="navbarDropdown"> <%= link_to 'パーク', main_index_path , class: "dropdown-item" %> <%= link_to 'イベント', boards_path(tag_name: 'event'), class: "dropdown-item" %> <%= link_to '困った時', boards_path(tag_name: 'question'), class: "dropdown-item" %> <%= link_to '入場までの準備', boards_path(tag_name: 'preparation'), class: "dropdown-item" %> </li> <li class="nav-item"> <%= link_to 'ログアウト', logout_path, class: 'nav-link text-white', method: :delete %> </li> </ul> </div> </nav> </header>
search.html.erb
<div class="form-inline"> <div class="form-group mr-2"> <%= search_form_for @search, url: url do |f| %> <%= f.search_field :title_or_body_cont, id: 'search-form', class: 'form-control', placeholder: '検索ワード' %> <%= f.submit '検索', class: 'btn btn-primary' %> <% end %> </div> </div>
https://www.youtube.com/live/t6M00cRjEA8?feature=share
以下参考にして調べたり色々してみてください。
マルチ検索・オートコンプリート 概要: 食べログの検索フォームのような、様々なカラムから検索可能な検索フォームです。1文字入力するたびに、候補が表示されるため、ユーザーの入力手間を減らし、入力ミスを減らすことができます。
使用技術・ライブラリ:
いつもお世話になっております オートコンプリート機能作成中
手詰まりしているのでご教授お願いしたいです
発生している問題
github公開されているオートコンプリート機能のフレームワークを使用したかったのですが jsの理解が乏しかったため jsの勉強も兼ねて自分で1から実装しました
header.js
こちらのコードを作成し、
文字列が部分一致する投稿を取得しリンクにしてhtml内に表示
するメソッドを作成したのですがconst response = await fetch('/boards.json');
のfetchが一度に取得できる数に限りがあると後で気づきheader.js
全記事を取得するまでループする処理を記述した コードにしたのですが
サーバーがとてつもなく重くなってしまいました。
全記事をサーバーを重くすることなく取得するコードにしたいのですが調べてもあまり出てこずで 詰まっているので教えていただきたいです。
関連のあるコード
header.html.erb
search.html.erb
主に参考にした資料
https://www.youtube.com/live/t6M00cRjEA8?feature=share