跳到正文

重定向并说明发生了什么 ​

机器翻译

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

任务: 表单提交之后,把浏览器带到一个页面,并告诉它发生了什么,只说一次。

yaml
# Recipe: after a POST, send the browser to a page and tell it what happened.
paths:
  components: ./components
  migrations: ./migrations

datasources:
  db:
    driver: sqlite
    database: ./data/notes.db
sql
CREATE TABLE notes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    text TEXT NOT NULL,
    done INTEGER NOT NULL DEFAULT 0
);

q:redirect 结束动作。它的 flash 接受表达式,并成为下一个渲染的页面上的 flash, 同时 flashType 设为 success。如果要另一种消息,q:flash type="warning" 在重定向 之前设置这两者。URL 可以是应用中的任何页面。

xml
<q:component name="Notes">
  <q:action name="add" method="POST">
    <q:param name="text" required="true" maxlength="200" />
    <q:query name="added" datasource="db">
      INSERT INTO notes (text) VALUES (:text)
      <q:param name="text" value="{text}" type="string" />
    </q:query>
    <!-- The flash accepts expressions; its type is "success". -->
    <q:redirect url="/" flash="Added: {text}" />
  </q:action>

  <q:action name="clear" method="POST">
    <q:query name="finished" datasource="db">
      UPDATE notes SET done = 1 WHERE done = 0
    </q:query>
    <q:if condition="finished_result.recordCount == 0">
      <!-- A flash of another kind: q:flash sets both, the redirect keeps them. -->
      <q:flash type="warning">There was nothing to clear.</q:flash>
      <q:redirect url="/" />
    </q:if>
    <q:redirect url="/done" flash="Cleared {finished_result.recordCount} notes." />
  </q:action>

  <q:query name="notes" datasource="db">
    SELECT id, text FROM notes WHERE done = 0 ORDER BY id
  </q:query>

  <ui:window title="Notes">
    <!-- flash and flashType exist on every page, '' when there is none;
         a flash shows on the next page rendered, once. -->
    <q:if condition="flash">
      <ui:alert variant="{flashType}">{flash}</ui:alert>
    </q:if>
    <ui:form on-submit="add">
      <ui:hbox gap="sm">
        <ui:input bind="text" placeholder="A note" grow="true" />
        <ui:button variant="primary">Add</ui:button>
      </ui:hbox>
    </ui:form>
    <q:loop query="notes">
      <ui:text>{notes.text}</ui:text>
    </q:loop>
    <ui:button on-click="clear">Clear all</ui:button>
  </ui:window>
</q:component>
xml
<q:component name="Done">
  <ui:window title="All clear">
    <q:if condition="flash">
      <ui:alert variant="{flashType}">{flash}</ui:alert>
    </q:if>
    <ui:link to="/">Back to the notes</ui:link>
  </ui:window>
</q:component>

第二个测试在重定向后再次打开页面:提示消息已经消失,flash 为 ''。

xml
<q:test name="adding a note redirects back with a success flash" page="/">
  <test:submit action="add" text="Buy bread" />
  <test:expect status="302" redirect="/" flash="Added: Buy bread" />
  <test:expect var="flashType" value="success" />
  <test:expect text="Buy bread" />
</q:test>

<q:test name="the flash shows once" page="/">
  <test:submit action="add" text="Buy bread" />
  <test:expect text="Added: Buy bread" />
  <test:visit />
  <test:expect no-text="Added: Buy bread" />
  <test:expect var="flash" value="" />
</q:test>

<q:test name="clearing sends the browser to another page" page="/">
  <test:given table="notes" text="Buy bread" />
  <test:given table="notes" text="Call Ana" />
  <test:submit action="clear" />
  <test:expect redirect="/done" flash="Cleared 2 notes." />
  <test:expect text="All clear" />
  <test:expect table="notes" count="0" where="done = 0" />
</q:test>

<q:test name="nothing to clear is a warning, on the same page" page="/">
  <test:submit action="clear" />
  <test:expect redirect="/" flash="There was nothing to clear." />
  <test:expect var="flashType" value="warning" />
</q:test>
text
tests/notes.test.q
  PASS  adding a note redirects back with a success flash
  PASS  the flash shows once
  PASS  clearing sends the browser to another page
  PASS  nothing to clear is a warning, on the same page
4 passed, 0 failed

参见 ACT-3。

MIT 许可证 · 使用 VitePress 构建