跳到正文

边输入边搜索 ​

机器翻译

本页由英文原文机器翻译而来,尚未经过母语审校,欢迎在 GitHub 上提出修改。内容如有出入,以英文原文为准。

任务: 一个图书搜索字段,在你输入时更新列表,而且没有 JavaScript 也能用。

yaml
# Recipe: a search field that refreshes the results while you type.
paths:
  components: ./components
  migrations: ./migrations

datasources:
  db:
    driver: sqlite
    database: ./data/library.db
sql
CREATE TABLE books (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    author TEXT NOT NULL
);

INSERT INTO books (title, author) VALUES
    ('Dom Casmurro', 'Machado de Assis'),
    ('Quincas Borba', 'Machado de Assis'),
    ('Vidas Secas', 'Graciliano Ramos'),
    ('Grande Sertão: Veredas', 'João Guimarães Rosa');

搜索是一个 GET 参数(?q=),由页面自己的查询读取。字段上的 search="results" 在每次输入停顿后请求同一个页面,只替换 id="results" 的元素;URL 也随之更新, 所以结果可以分享或刷新。

xml
<q:component name="Library">
  <!-- The search is the URL's ?q=; the page's own query does the searching. -->
  <q:set name="term" value="{query.q}" default="" />
  <q:query name="found" datasource="db">
    SELECT title, author FROM books
    WHERE title LIKE :pattern OR author LIKE :pattern
    ORDER BY title
    <q:param name="pattern" value="%{term}%" type="string" />
  </q:query>

  <ui:window title="Library">
    <!-- search="results": after a pause in typing, the page is asked again
         with ?q=… and only #results is swapped. Enter works without JavaScript. -->
    <ui:input bind="q" value="{term}" search="results" placeholder="Title or author" />
    <ui:vbox id="results">
      <ui:text>{found_result.recordCount} books</ui:text>
      <ui:list source="{found}" as="b">
        <ui:item><ui:text>{b.title} — {b.author}</ui:text></ui:item>
      </ui:list>
    </ui:vbox>
  </ui:window>
</q:component>
xml
<q:test name="every book before a search" page="/">
  <test:visit />
  <test:expect text="4 books" />
</q:test>

<q:test name="a title or an author" page="/">
  <test:visit q="machado" />
  <test:expect text="2 books" />
  <test:expect text="Quincas Borba — Machado de Assis" />
  <test:expect no-text="Vidas Secas" />
</q:test>

<q:test name="nothing found" page="/">
  <test:visit q="tolstoy" />
  <test:expect text="0 books" />
</q:test>
text
tests/search.test.q
  PASS  every book before a search
  PASS  a title or an author
  PASS  nothing found
3 passed, 0 failed

参见 UI-12。

MIT 许可证 · 使用 VitePress 构建