因为很忙,InfyniDock也不太需要用户系统, 所以我其实并没有真正的花时间去写用户系统,但是在做一个后台管理系统的时候,没有用户密码来登录又不太现实.
所以我只是简单的模拟一下,在后台手写一个用户名与密码,简单认证,前台发送固定的用户名密码到后端去认证.
现在看一下,Qwik是怎么处理前端cookie的.
第一步,处理Qwik的onRequest函数:
src/routes/layouts.tsx (必须写在这个文件里)
export const onRequest: RequestHandler = async ({next, sharedMap, cookie,redirect,url }) => {
const user = loadUserFromCookie(cookie);
// 如果当前是login页面,不做处理,正常渲染页面
if (url.pathname === '/login/'){
await next();
return
}
// 其它页面,如果没有用户登录信息,则重定向到登录页面
if ( !user ) {
throw redirect(308, '/login')
}
sharedMap.set('user', user as User)
await next();
};
从cookie里处理数据
function loadUserFromCookie(cookie: Cookie): User | null {
const username = cookie.get('username')?.value;
if (username) {
return {
username: username,
email: `infyniclick@gmail.com`,
};
} else {
return null;
}
}
处理完以上的基础部分之后,我们来写一个简单的登录页面看看:
routes/login/index.tsx
import { component$, $, useStore } from "@builder.io/qwik"
import { server$, useNavigate } from "@builder.io/qwik-city"
const requestLogin = server$(async function (
username: string,
password: string
) {
if (password) {
this.cookie.delete("username")
this.cookie.delete("user")
this.cookie.set("username", username, { path: "/" })
this.cookie.set("user", { username: username }, { path: "/" })
this.sharedMap.set("user", { username: username })
return true
}
return false
})
export default component$(() => {
// 前端状态
const store = useStore({ username: "test", password: "123456" })
const nav = useNavigate()
// 点击登录按钮之后的处理函数
const login$ = $(async () => {
// 调用服务端接口,处理登录后续事件
const result = await requestLogin(store.username, store.password)
if (result) {
await nav("/dashboard/")
}
})
return (
<>
<div>login in page</div>
<button onClick$={async () => await login$()}> login </button>
</>
)
})
点击一下login, 看看后端是不是真正的接收到了用户名和密码:
通过以上的简单的代码,就实现了前后端的登录认证通讯.
最后, 普及Qwik的一些知识点:
一、server$
是在服务器端执行的代码,你可以看到它的console.log是在后端进行输出,不是在浏览器输出;像我们上面的例子,就可以在requestLogin里,查询数据库,并校验密码与用户名,再返回给前端. 以后再用prisma来查询数据库.
二、useVisibleTask$
是在浏览器端执行的代码,如果你需要明确的在浏览器端处理的UI任务,就需要放在useVisibleTask$里处理.
三、sharedMap
看一下官方的解释:
Use `sharedMap` as a way to share data between middleware functions. The `sharedMap` is scoped to HTTP request. A common use case is to use `sharedMap` to store user details so that it can be used by other middleware functions, `routeLoader$()` or components.
shareMap 可以在后端写入数据,然后在routeLoader$()取出来.比如我们可以这样子取值:
src/routes/layouts.tsx (必须写在这个文件里)
export const useUser = routeLoader$(({ sharedMap }) => {
return sharedMap.get('user') as User;
});
然后就可以显示出来:
import { component$ } from "@builder.io/qwik"
import type { DocumentHead } from "@builder.io/qwik-city"
import { useUser } from "./layout"
export default component$(() => {
const log = useUser()
return (
<>
<h1>
Hi 👋 {log.value.username} {log.value.email}
</h1>
<p>
Can't wait to see what you build with qwik!
<br />
Happy coding.
</p>
</>
)
})
暂时先这样.下一章写查询数据