Ukládání dat do mezipaměti pomocí parametrů URL dotazu v JavaScriptu

Jak dočasně uložit data v parametrech dotazu URL a načíst je a analyzovat pro použití ve vašem uživatelském rozhraní.

Začínáme

Pro tento tutoriál použijeme full-stack JavaScriptový framework CheatCode, Joystick. Joystick spojuje rozhraní front-end UI s back-endem Node.js pro vytváření aplikací.

Pro začátek budeme chtít nainstalovat Joystick přes NPM. Před instalací se ujistěte, že používáte Node.js 16+, abyste zajistili kompatibilitu (pokud se potřebujete naučit, jak nainstalovat Node.js nebo spustit více verzí na vašem počítači, přečtěte si nejprve tento tutoriál):

Terminál

npm i -g @joystick.js/cli

Tím se Joystick nainstaluje globálně do vašeho počítače. Po instalaci vytvořte nový projekt:

Terminál

joystick create app

Po několika sekundách se zobrazí zpráva odhlášena na cd do nového projektu a spusťte joystick start . Než spustíte joystick start , potřebujeme nainstalovat jeden balíček, query-string :

Terminál

cd app && npm i query-string

Tento balíček nám pomůže analyzovat a nastavovat parametry dotazu za běhu. Po instalaci pokračujte a spusťte server:

Terminál

joystick start

Poté by vaše aplikace měla být spuštěna a my jsme připraveni začít.

Přidání některých globálních CSS

Abychom lépe uvedli do kontextu naše demo, přidáme CSS do celého tutoriálu. Pro začátek musíme přidat nějaké globální CSS, které se postará o celkové zobrazení našich stránek:

/index.css

* {
  margin: 0;
  padding: 0;
}

*, *:before, *:after {
  box-sizing: border-box;
}

body {
  font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
  font-size: 16px;
  background: #fff;
}

.container {
  width: 100%;
  max-width: 800px;
  margin: 15px auto;
  padding: 0 15px !important;
}

@media screen and (min-width: 768px) {
  .container {
    margin-top: 50px;
  }
}

Ve výchozím nastavení, když otevřete tento soubor, pouze CSS pro body značka bude existovat. Na specifikách zde příliš nezáleží, ale to, co děláme, je přidání některých „resetovacích“ stylů pro všechny prvky HTML v prohlížeči (odstranění výchozího CSS prohlížeče, které přidává další okraje a odsazení a mění způsob, jakým prvky v poli proudí model) a .container třída, která nám umožní snadno vytvořit vycentrovaný <div></div> pro zabalení obsahu.

To je vše, co tady potřebujeme. Později přidáme další CSS na úrovni jednotlivých komponent. Dále musíme zapojit trasu pro fiktivní stránku, kterou použijeme k testování parametrů dotazu.

Přidání trasy k přesměrování pro testování parametrů

V aplikaci Joystick jsou všechny trasy definovány na serveru na jednom místě:/index.server.js . Pojďme to teď otevřít a přidat trasu pro fiktivní stránku, na kterou se můžeme přesměrovat, a ověřit, že naše parametry dotazu fungují podle očekávání:

/index.server.js

import node from "@joystick.js/node";
import api from "./api";

node.app({
  api,
  routes: {
    "/": (req, res) => {
      res.render("ui/pages/index/index.js", {
        layout: "ui/layouts/app/index.js",
      });
    },
    "/listings/:listingId": (req, res) => {
      res.render("ui/pages/listing/index.js");
    },
    "*": (req, res) => {
      res.render("ui/pages/error/index.js", {
        layout: "ui/layouts/app/index.js",
        props: {
          statusCode: 404,
        },
      });
    },
  },
});

Když jste spustili joystick start dříve z kořenového adresáře vaší aplikace je to soubor, který spustil joystick. Zde node.app() funkce spustí novou aplikaci Node.js používající Express.js v zákulisí. Chcete-li vyjádřit, routes objekt je definován na objektu options předaném node.app() je předán.

Ve výchozím nastavení tohoto objektu vidíme / a * jsou definovány trasy. Výše jsme přidali novou trasu /listings/:listingId . Pro naši aplikaci vytváříme falešné uživatelské rozhraní pro vyhledávání nemovitostí, kde si uživatelé budou moci přizpůsobit některé parametry vyhledávání a zobrazovat záznamy.

Zde vytváříme trasu pro falešnou stránku – nenačte žádná skutečná data, jen nějaká statická fiktivní data – stránku se seznamem, na kterou se uživatel bude moci přesměrovat. Myšlenka je taková, že nastavíme nějaké parametry dotazu na adresu URL na / (index) a poté umožnit uživateli kliknout na odkaz na tento /listings/:listingId strana. Když se tak stane, parametry dotazu, které jsme nastavili, „zmizí“. Když se vrátí zpět, očekáváme, že se tyto parametry dotazu obnoví.

Uvnitř trasy zde voláme funkci na res objekt, res.render() což je speciální funkce, kterou joystick přidává ke standardnímu Express res objekt. Tato funkce je navržena tak, aby provedla cestu ke komponentě joysticku v naší aplikaci a vykreslila ji na stránce.

Zde předpokládáme, že budeme mít stránku umístěnou na /ui/pages/listing/index.js . Pojďme to teď zapojit.

Zapojení falešné stránky se seznamem

Tenhle je rychlý. Zde se příliš nestaráme o stránku samotnou, jen o to, že existuje, abychom uživatele přesměrovali.

/ui/pages/listing/index.js

import ui from '@joystick.js/ui';

const Listing = ui.component({
  css: `
    .listing-image img {
      max-width: 100%;
      width: 100%;
      display: block;
      height: auto;
    }

    .listing-metadata {
      margin-top: 25px;
    }

    .listing-metadata .price {
      font-size: 28px;
      color: #333;
    }

    .listing-metadata .address {
      font-size: 18px;
      color: #888;
      margin-top: 7px;
    }

    .listing-metadata .rooms {
      font-size: 16px;
      color: #888;
      margin-top: 10px;
    }
  `,
  render: () => {
    return `
      <div class="container">
        <div class="listing-image">
          <img src="/house.jpg" alt="House" />
        </div>
        <div class="listing-metadata">
          <h2 class="price">$350,000</h2>
          <p class="address">1234 Fake St. Winter, MA 12345</p>
          <p class="rooms">3br, 2ba, 2,465 sqft</p>
        </div>
      </div>
    `;
  },
});

export default Listing;

Zde vytvoříme komponentu Joystick voláním .component() funkce definovaná na ui objekt importujeme z @joystick.js/ui balík. Této funkci předáme objekt voleb k definování naší komponenty.

Počínaje spodní částí máme render() funkce, která říká naší komponentě HTML, které bychom chtěli pro naši komponentu vykreslit. Zde, protože nepotřebujeme funkční stránku, vrátíme pouze řetězec prostého HTML s několika pevně zakódovanými daty. Za zmínku stojí house.jpg obrázek, který se zde vykresluje, si můžete stáhnout z našeho bucketu S3 zde. Toto by mělo být umístěno v /public složku v kořenovém adresáři projektu.

Kromě toho, jak jsme již naznačili dříve, přidáváme některé CSS. Abychom to mohli udělat, na komponentě joysticku máme css možnost, které můžeme předat řetězec CSS. Joystick automaticky upraví rozsah tohoto CSS na tuto komponentu, aby nám pomohl zabránit úniku stylů do jiných komponent.

To je tady. Opět je to jen fiktivní komponenta, která nám pomáhá otestovat logiku parametru dotazu, kterou nastavíme v další části.

Zapojení falešného uživatelského rozhraní vyhledávání s filtry a stránkou výsledků

I když se toho v této komponentě hodně děje, část, na kterou se chceme zaměřit, je logika pro správu našich parametrů dotazů. Abychom se tam dostali, nejprve sestavíme kostru uživatelského rozhraní pro naši komponentu a poté přidáme skutečnou logiku, aby to fungovalo.

Ačkoli jsme o tom dříve nemluvili, zde přepíšeme stávající obsah /ui/pages/index/index.js soubor:

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const Index = ui.component({
  css: `
    .search {
      padding: 20px;
    }

    header {
      display: flex;
      margin-bottom: 40px;
      padding-left: 20px;
    }

    header > * {
      margin-right: 20px;
    }

    .options label {
      margin-right: 10px;
    }

    .options label input {
      margin-right: 3px;
    }

    .listings ul {
      display: grid;
      grid-template-columns: 1fr;
      list-style: none;
    }

    .listings ul li {
      position: relative;
      padding: 20px;
      border: 1px solid transparent;
      cursor: pointer;
    }

    .listings ul li:hover {
      border: 1px solid #eee;
      box-shadow: 0px 1px 1px 2px rgba(0, 0, 0, 0.01);
    }

    .listings ul li a {
      position: absolute;
      inset: 0;
      z-index: 5;
    }

    .listing-image img {
      max-width: 100%;
      width: 100%;
      display: block;
      height: auto;
    }

    .listing-metadata {
      margin-top: 25px;
    }

    .listing-metadata .price {
      font-size: 24px;
      color: #333;
    }

    .listing-metadata .address {
      font-size: 16px;
      color: #888;
      margin-top: 7px;
    }

    .listing-metadata .rooms {
      font-size: 14px;
      color: #888;
      margin-top: 7px;
    }

    @media screen and (min-width: 768px) {
      .search {
        padding: 40px;
      }

      .listings ul {
        display: grid;
        grid-template-columns: 1fr 1fr;
      }  
    }

    @media screen and (min-width: 1200px) {
      .listings ul {
        display: grid;
        grid-template-columns: 1fr 1fr 1fr 1fr;
      }  
    }
  `,
  render: () => {
    return `
      <div class="search">
        <header>
          <input type="text" name="search" placeholder="Search listings..." />
          <select name="category">
            <option value="house">House</option>
            <option value="apartment">Apartment</option>
            <option value="condo">Condo</option>
            <option value="land">Land</option>
          </select>        
          <select name="status">
            <option value="forSale">For Sale</option>
            <option value="forRent">For Rent</option>
            <option value="sold">Sold</option>
          </select>
          <div class="options">
            <label><input type="checkbox" name="hasGarage" /> Garage</label>
            <label><input type="checkbox" name="hasCentralAir" /> Central Air</label>
            <label><input type="checkbox" name="hasPool" /> Pool</label>
          </div>
          <a href="#" class="clear">Clear</a>
        </header>
        <div class="listings">
          <ul>
            <li>
              <a href="/listings/123"></a>
              <div class="listing-image">
                <img src="/house.jpg" alt="House" />
              </div>
              <div class="listing-metadata">
                <h2 class="price">$350,000</h2>
                <p class="address">1234 Fake St. Winter, MA 12345</p>
                <p class="rooms">3br, 2ba, 2,465 sqft</p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    `;
  },
});

export default Index;

Nahoře dostáváme základní HTML a CSS na stránku pro naše uživatelské rozhraní. Naším cílem je opět mít pseudovyhledávací uživatelské rozhraní, kde si uživatel může nastavit některé parametry vyhledávání a zobrazit seznam výsledků na stránce. Zde vytváříme základní uživatelské rozhraní a upravujeme jej. Když toto přidáme, navštívíme http://localhost:2600/ (ignorujte 2605 na níže uvedeném snímku obrazovky (toto bylo jen pro testování při psaní) v našem prohlížeči bychom měli vidět něco takového:

Dále nastavíme „výchozí“ stav pro naše uživatelské rozhraní pro vyhledávání (vše v záhlaví nebo horní části uživatelského rozhraní označujeme jako „uživatelské rozhraní vyhledávání“).

/ui/pages/index/index.js

import ui from '@joystick.js/ui';

const Index = ui.component({
  state: {
    search: '',
    category: 'house',
    status: 'forSale',
    hasGarage: false,
    hasCentralAir: false,
    hasPool: false,
  },
  css: `...`,
  render: ({ state }) => {
    return `
      <div class="search">
        <header>
          <input type="text" name="search" value="${state.search}" placeholder="Search listings..." />
          <select name="category" value="${state.category}">
            <option value="house" ${state.category === 'house' ? 'selected' : ''}>House</option>
            <option value="apartment" ${state.category === 'apartment' ? 'selected' : ''}>Apartment</option>
            <option value="condo" ${state.category === 'condo' ? 'selected' : ''}>Condo</option>
            <option value="land" ${state.category === 'land' ? 'selected' : ''}>Land</option>
          </select>        
          <select name="status" value="${state.status}">
            <option value="forSale" ${state.status === 'forSale' ? 'selected' : ''}>For Sale</option>
            <option value="forRent" ${state.status === 'forRent' ? 'selected' : ''}>For Rent</option>
            <option value="sold" ${state.status === 'sold' ? 'selected' : ''}>Sold</option>
          </select>
          <div class="options">
            <label><input type="checkbox" name="hasGarage" ${state?.hasGarage ? 'checked' : ''} /> Garage</label>
            <label><input type="checkbox" name="hasCentralAir" ${state?.hasCentralAir ? 'checked' : ''} /> Central Air</label>
            <label><input type="checkbox" name="hasPool" ${state?.hasPool ? 'checked' : ''} /> Pool</label>
          </div>
          <a href="#" class="clear">Clear</a>
        </header>
        <div class="listings">
          <ul>
            <li>
              <a href="/listings/123"></a>
              <div class="listing-image">
                <img src="/house.jpg" alt="House" />
              </div>
              <div class="listing-metadata">
                <h2 class="price">$350,000</h2>
                <p class="address">1234 Fake St. Winter, MA 12345</p>
                <p class="rooms">3br, 2ba, 2,465 sqft</p>
              </div>
            </li>
          </ul>
        </div>
      </div>
    `;
  },
});

export default Index;

Na komponentě joysticku můžeme předat state možnost, která je přiřazena objektu vlastností, které chceme standardně přiřadit vnitřnímu stavu naší komponenty (tj. když se komponenta poprvé načte). Zde vytváříme některá výchozí nastavení, která chceme použít pro naše uživatelské rozhraní vyhledávání.

Důležitá část je zde zpět v render() funkce je, že jsme přidali argument do našeho render() Funkce, u které předpokládáme, že je objekt, který můžeme destrukovat, abychom „vytrhli“ specifické vlastnosti a přiřadili je stejnojmenným proměnným v aktuálním rozsahu/kontextu. Objekt, který zde očekáváme, je component instance (což znamená komponentu, kterou aktuálně vytváříme, protože existuje v paměti).

V tomto případě očekáváme, že budeme mít přístup k aktuálnímu state hodnota. „Stav“ v tomto případě odkazuje na vizuální stav našeho uživatelského rozhraní. Hodnoty na state objekt jsou zamýšleny jako prostředek pro rozšíření tohoto vizuálního stavu za běhu.

Zde vezmeme state objekt odkazovat na hodnoty k naplnění našeho uživatelského rozhraní vyhledávání. V našem uživatelském rozhraní máme tři typy vstupů:

  1. input což je prostý textový vstup používaný pro zadávání řetězce hledaného textu.
  2. select který se používá pro naše vstupy „kategorie“ a „stav“.
  3. checkbox který se používá pro zaškrtávací políčka pro naše vybavení.

Níže v našem HTML odkazujeme na tyto hodnoty pomocí interpolace řetězců JavaScript (funkce na jazykové úrovni pro vkládání/vyhodnocování JavaScriptu do řetězce). Můžeme to udělat, protože hodnota, kterou vracíme z render() naší komponenty funkce je řetězec.

V závislosti na typu vstupu, který vykreslujeme, využíváme odpovídající hodnotu stavu mírně odlišně. Pro náš prostý textový vyhledávací vstup stačí nastavit value atribut rovný hodnotě state.search .

Pro náš výběr <select> oba vstupy nastavíme value atribut na hlavní <select> tag a také podmíněný selected atribut u každé možnosti v této <select> seznam (což je důležité, protože pokud to neuděláme, aktuální hodnota vstupu se bez tohoto atributu nebude zobrazovat jako vybraná).

Nakonec pro naše zaškrtávací pole podmíněně přidáme checked hodnota atributu na základě odpovídajícího state hodnotu pro každý vstup.

To nám dává základy našeho uživatelského rozhraní. Nyní jsme připraveni zaznamenat změny v našem uživatelském rozhraní vyhledávání a uložit je jako parametry dotazu v naší adrese URL.

Zachycení filtrů vyhledávání jako parametrů dotazu

Nyní, když máme nastavené základní uživatelské rozhraní, můžeme začít spravovat parametry dotazu. Abychom to mohli udělat, přidáme do našeho uživatelského rozhraní některé posluchače událostí JavaScriptu, abychom mohli získat nejnovější hodnoty, jak jsou nastaveny uživatelem:

/ui/pages/index/index.js

import ui from '@joystick.js/ui';
import queryString from 'query-string';

const Index = ui.component({
  state: { ... },
  methods: {
    handleUpdateQueryParams: (param = '', value = '') => {
      const existingQueryParams = queryString.parse(location.search);
      const updatedQueryParams = queryString.stringify({
        ...existingQueryParams,
        [param]: value,
      });

      window.history.pushState('', '', `?${updatedQueryParams}`);
    },
    handleClearQueryParams: (component = {}) => {
      window.history.pushState('', '', `${location.origin}${location.pathname}`);
      component.methods.handleSetStateFromQueryParams();
    },
  },
  css: `...`,
  events: {
    'keyup [name="search"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('search', event.target.value);
    },
    'change [name="category"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('category', event.target.value);
    },
    'change [name="status"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams('status', event.target.value);
    },
    'change [type="checkbox"]': (event, component = {}) => {
      component.methods.handleUpdateQueryParams(event.target.name, event.target.checked);
    },
    'click .clear': (event, component = {}) => {
      event.preventDefault();
      component.methods.handleClearQueryParams();
    },
  },
  render: ({ state }) => {
    return `
      <div class="search">
        ...
      </div>
    `;
  },
});

export default Index;

Výše jsme přidali dvě nové vlastnosti do možností naší komponenty:events a methods . Zaměřuji se na events , zde nám Joystick pomáhá naslouchat událostem JavaScript DOM na prvcích vykreslených naší komponentou. Každá událost je definována jako vlastnost objektu předaná do events kde název vlastnosti je řetězec popisující typ události DOM, které se má naslouchat, a prvek uvnitř naší komponenty, který má událost naslouchat on .

Vlastnosti přiřadíme funkci, která by měla být volána, když je tato událost detekována na zadaném prvku. Zde jsme přidali posluchače pro každý z našich vstupů souvisejících s vyhledáváním (kromě vstupů zaškrtávacích políček, které pouze obecně posloucháme na vstupech s typem checkbox ).

Všimněte si, že tu zvláštní kachnu je search zadávání textu. Zde chceme poslouchat keyup událost na vstupu, protože chceme zachytit každou změnu na vstupu (pokud nasloucháme change událost jako my ostatní, se spustí až poté, co uživatel "rozmaže" nebo klikne ze vstupu).

Uvnitř všech posluchačů událostí (kromě toho posledního, kterému se budeme trochu věnovat) voláme na component.methods.handleUpdateQueryParams() . Do funkce zpětného volání posluchače události předává joystick dvě hodnoty:event a component . event je nezpracovaná událost DOM JavaScriptu, která se spustila, a component je aktuální instancí komponenty (podobně tomu, co jsme viděli v render() ) – = {} část za component zde definujeme výchozí hodnotu – základní funkci JavaScriptu – ke které se vrátíme v případě, že component není definováno (toto nikdy nebude pravda, protože je to automatické – zvažte to přidání síly zvyku).

Z component chceme přistupovat k metodě definované na methods objekt (kde můžeme ukládat různé metody na naší instanci komponenty). Zde voláme metodu definovanou výše, handleUpdateQueryParams() .

Nahoru jsme přidali import queryString balíček, který jsme nainstalovali dříve, který nám pomůže analyzovat existující parametry dotazu v adrese URL a připravit naše hodnoty pro přidání na adresu URL.

Uvnitř handleUpdateQueryParams() , potřebujeme předvídat existující parametry dotazu v naší adrese URL, kterou přidáváme, takže začneme tím, že vezmeme všechny existující parametry dotazu a analyzujeme je do objektu s queryString.parse() . Zde location.search je globální hodnota prohlížeče, která obsahuje aktuální řetězec dotazu jako ?someParam=value . Když tuto hodnotu předáme do queryString.parse() dostaneme zpět objekt JavaScriptu jako { someParam: 'value' } .

Tím vytvoříme další proměnnou updatedQueryParams který je nastaven na volání queryString.stringify() a předali objekt, který chceme převést zpět na řetězec dotazu jako ?someParam=value .

Na tomto objektu pomocí JavaScriptu ... spread, nejprve „rozbalíme“ nebo rozložíme všechny existující parametry dotazu a poté je ihned následujeme s [param]: value kde param je název parametru, který chceme aktualizovat (předán jako první argument do handleUpdateQueryParams() ) a value je to hodnota, kterou chceme nastavit pro tento parametr – nastavený pomocí druhého argumentu předaného na handleUpdateQueryParams() . [param] syntaxe zde používá JavaScriptovou závorkovou notaci, která říká „dynamicky nastavte název vlastnosti na hodnotu param argument."

Pokud se podíváme dolů do našich obslužných programů událostí, abychom viděli, jak se tomu říká, předáme param buď jako řetězec, nebo v případě našich zaškrtávacích polí jako event.target.name hodnotu nebo name atribut zaškrtávacího políčka spouštějící událost.

S updatedQueryParams zkompilovaný, abychom aktualizovali naši adresu URL, zavoláme globální window.history.pushState() předání aktualizace, kterou chceme použít na adresu URL. Zde history.pushState() je funkce, která aktualizuje historii našeho prohlížeče ale nespustí aktualizaci prohlížeče (jak bychom očekávali, kdybychom ručně nastavili location.search hodnotu přímo).

Je pravda, že API pro history.pushState() je trochu matoucí (jak je uvedeno v tomto článku MDN o této funkci zde). U prvních dvou hodnot pouze předáme prázdné řetězce (viz předchozí odkaz na MDN, pokud vás zajímá, k čemu to jsou) a u třetího argumentu předáme URL, kterou chceme „nastrčit“ do historie prohlížeče.

V tomto případě nechceme upravovat samotnou adresu URL, pouze parametry dotazu, takže předáme řetězec obsahující ? což označuje začátek parametrů dotazu v adrese URL a hodnotu vrácenou queryString.stringify() v updatedQueryParams .

A je to. Nyní, když začneme provádět změny v našem uživatelském rozhraní, měli bychom vidět, jak se naše adresa URL začíná dynamicky aktualizovat pomocí vstupních hodnot našeho uživatelského rozhraní vyhledávání.

Než budeme pokračovat, opravdu rychle a upozorněte na click .clear posluchač události a následné volání na methods.handleClearQueryParams() , zde děláme to, co navrhuje kód:vymažeme všechny parametry dotazu, které jsme nastavili pro adresu URL, když uživatel klikne na odkaz „Vymazat“ na konci našeho uživatelského rozhraní pro vyhledávání.

Abychom to udělali, nakonec zavoláme history.pushState() , tentokrát s kombinací aktuálního location.origin (např. http://localhost:2600 ) s aktuálním location.pathname (např. / nebo /listings/123 ). Tím efektivně vymažete všechny parametry dotazu v adrese URL a odstraníte ji pouze na základní adresu URL pro aktuální stránku.

Poté voláme další metodu, kterou ještě musíme definovat:methods.handleSetStateFromQueryParams() . Uvidíme, jak se to zformuje v další – a poslední – sekci.

Opětovné načtení vyhledávacích filtrů při načtení stránky

Tato část je poměrně přímočará. Nyní, když máme parametry dotazu v naší adrese URL, chceme tyto parametry zohlednit při každém načtení naší stránky. Pamatujte, že chceme mít možnost opustit tuto stránku, vrátit se a nechat naše uživatelské rozhraní pro vyhledávání „znovu načíst“ hodnoty vyhledávání uživatele z adresy URL.

/ui/pages/index/index.js

import ui from '@joystick.js/ui';
import queryString from 'query-string';

const Index = ui.component({
  state: { ... },
  lifecycle: {
    onMount: (component = {}) => {
      component.methods.handleSetStateFromQueryParams();
    },
  },
  methods: {
    handleSetStateFromQueryParams: (component = {}) => {
      const queryParams = queryString.parse(location.search);
      component.setState({
        search: queryParams?.search || '',
        category: queryParams?.category || 'house',
        status: queryParams?.status || 'forSale',
        hasGarage: queryParams?.hasGarage && queryParams?.hasGarage === 'true' || false,
        hasCentralAir: queryParams?.hasCentralAir && queryParams?.hasCentralAir === 'true' || false,
        hasPool: queryParams?.hasPool && queryParams?.hasPool === 'true' || false,
      });
    },
    handleUpdateQueryParams: (param = '', value = '') => { ... },
    handleClearQueryParams: (component = {}) => {
      window.history.pushState('', '', `${location.origin}${location.pathname}`);
      component.methods.handleSetStateFromQueryParams();
    },
  },
  css: `...`,
  events: { ... },
  render: ({ state }) => {
    return `
      <div class="search">
        ...
      </div>
    `;
  },
});

export default Index;

Poslední část. Výše jsme přidali další vlastnost do možností komponent lifecycle a na objektu, který mu byl předán, jsme definovali funkci onMount s použitím component instance jako první argument.

Zde říkáme „když se tato komponenta připojí (načte) v prohlížeči, zavolejte na methods.handleSetStateFromQueryParams() funkce. Myšlenka je taková, jakou byste očekávali:načíst aktuální sadu parametrů dotazu z adresy URL zpět do stavu naší komponenty, když se stránka načte.

Zaměření na handleSetStateFromQueryParams() , práce je zde velmi jednoduchá. Nejprve chceme získat parametry dotazu jako objekt queryParams voláním na číslo queryString.parse(location.search) . Je to podobné tomu, co jsme viděli dříve, s použitím ?someParam=value formulář našich parametrů dotazu a jeho převod na objekt JavaScript, jako je { someParam: 'value' } .

S tímto objektem queryParams , zavoláme na component.setState() dynamicky aktualizovat stav naší součásti. Zde nastavujeme každou z hodnot, které jsme zadali ve výchozím nastavení naší komponenty state dříve. Pro každou hodnotu se snažíme získat přístup k tomuto parametru z queryParams objekt. Pokud existuje, použijeme jej, a pokud ne, použijeme JavaScript nebo || operátor říct "použij místo toho tuto hodnotu." Zde se „místo“ vrací zpět na stejné hodnoty, jaké jsme nastavili na výchozí stav dříve.

A je to! Nyní, když nastavíme nějaké hodnoty vyhledávání a aktualizujeme stránku, naše parametry dotazu zůstanou a automaticky se nastaví zpět v našem uživatelském rozhraní, pokud stránku obnovíme. Pokud klikneme na falešný záznam v našem seznamu, abychom přešli na jeho podrobnou stránku, a poté v prohlížeči klikneme na „zpět“, naše parametry dotazu budou stále existovat v adrese URL a budou načteny zpět do uživatelského rozhraní.

Zabalení

V tomto tutoriálu jsme se naučili, jak dynamicky nastavovat parametry dotazu v prohlížeči. Naučili jsme se, jak vytvořit jednoduché, dynamické vyhledávací uživatelské rozhraní, které ukládá parametry vyhledávání uživatele do adresy URL, a jak při opětovném načítání stránky načíst tyto parametry z adresy URL zpět do našeho uživatelského rozhraní. Abychom toho dosáhli, naučili jsme se používat různé funkce komponenty Joystick ve spojení s query-string balíček, který nám pomůže zakódovat a dekódovat parametry dotazu v naší adrese URL.