前端
整體搜尋功能架構:
- SearchBar - 前端搜尋欄位,捕捉使用者輸入。
- HomePage - 用
useLocation
取得網址中的關鍵字,透過 useEffect
監聽關鍵字的變化,再透過 dispatch
來發送請求
- productActions - 與後端 API 溝通,發送帶有
keyword
參數的請求
- 後端 product_views - 根據傳入的關鍵字查詢資料庫,返回符合條件的商品清單
Search Bar Component(搜尋欄)
- 判斷若搜尋表單沒有
keyword
,就停留在當前頁面 window.location.pathname
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const navigate = useNavigate();
const [keyword, setKeyword] = useState("");
const submitHandler = (e) => { e.preventDefault(); if (keyword.trim()) { navigate(`/?keyword=${keyword}`); } else { navigate(window.location.pathname); } }; return ( <Form onSubmit={submitHandler} className='d-flex' style={{ height: "38px" }}> <Form.Control type='text' name='q' onChange={(e) => setKeyword(e.target.value)} placeholder='搜尋商品...' className='me-2 form-control-sm' /> <Button type='submit' variant='outline-success' className='p-2'> <i className='fas fa-search'></i> </Button> </Form> );
|
HomePage.js(首頁)
- 使用
useLocation
取得 route
資訊,這邊是取得 search
也就是網址中的 query string
1 2 3 4 5 6
| let keyword = useLocation().search; console.log(keyword);
useEffect(() => { dispatch(listProducts(keyword)); }, [dispatch, keyword]);
|
檢查主控台,可以看到 keyword
的值是 ?keyword=

productActions.js(Redux Action)
傳入關鍵字的寫法很活,沒有一定
假設在 HomePage
中寫 dispatch(listProducts("")); // 明確傳入空字串
,那在 listProducts
中就可以寫 keyword
即可,都一樣能運作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| export const listProducts = (keyword = "") => async (dispatch) => { try { dispatch({ type: PRODUCT_LIST_REQUEST }); const { data } = await axios.get(`/api/products/${keyword}`); dispatch({ type: PRODUCT_LIST_SUCCESS, payload: data, }); } catch (error) { dispatch({ type: PRODUCT_LIST_FAIL, payload: error.response && error.response.data.message ? error.response.data.message : error.message, }); } };
|
後端
views(取得所有產品)
- 將列出所有產品的程式放在
query
為 None 的情況 products = Product.objects.all()
避免 UnboundLocalError: local variable 'products' referenced before assignment
錯誤
icontains
不區分大小寫
可以先將 query
印出來看看,確認是否有正確接收到前端傳來的關鍵字

1 2 3 4 5 6 7 8 9 10 11 12
| @api_view(['GET']) def getProducts(request): query = request.query_params.get('keyword') if query is None: query = '' products = Product.objects.all() else: products = Product.objects.filter(name__icontains=query)
serializer = ProductSerializer(products, many=True) return Response(serializer.data)
|
最後成功結果,搜尋 a
只顯示產品名稱中有 a
的商品:

若您覺得這篇文章對您有幫助,歡迎分享出去讓更多人看到⊂◉‿◉つ~
留言版