1. API 使用进阶
在过去的作业中,我们了解了 fetch 函数的 GET 方法。
与 API 交互所使用的函数均为 fetch (无论是采用 GET,POST 还是别的任何方法)。
一个通用的 fetch 函数案例:
fetch(`https://cs571.org/api/f23/hw6/messages?chatroom=${props.name}`,{
method:"POST",
credentials:"include",
headers: {
"X-CS571-ID": CS571.getBadgerId(),
"Content-Type":"application/json"
},
body: JSON.stringify({
"title":tit,
"content":cnt
})
}).then(res=>res.json())
.then(res=>{
console.log(res);
alert(res.msg);
loadMessages();
})
对于非 GET 类型的请求,必须在代码开头标注 method:"POST"
(或是PUT / DELETE)
四种基本请求操作:GET 读取,POST 创建,PUT 更新,DELETE 删除
返回码
使用 res.status
方法来读取(请与 res.json()
作出区分,res.json()
是将返回值转为 JS object 的函数,而 res.status
是一个数值。
以下是常见的返回码:
HTTP Code | Response Type |
---|---|
200s | 成功 |
300s | 重定向消息 |
400s | 用户端出现问题 |
500s | 服务器出现问题 |
HTTP Code | Response |
---|---|
200 | OK |
304 | 已在本地有缓存 |
400 | Bad Request(例如body中内容格式不符合要求) |
401 | 未授权(例如没有Badger ID) |
404 | Not Found |
409 | 冲突(例如试图 POST 已有的内容) |
413 | 请求长度超标 |
500 | 内部服务器错误 |
注意事项
- 如果需要调取登陆状态进行需要权限的操作,则需要添加
credentials:"include"
一行 - 虽然传输的 body 本质是一个 JSON,但是它只接受字符串形式,所以使用
JSON.stringfy()
- 在含有 body 的请求当中,需要在 headers 里边注明 Content-Type 表示客户端传送内容的数据类型。例如:
"Content-Type":"application/json"
。
2. 非受控组件
使用 useRef 方法。useref 是一个对不需要渲染的值的引用。
const remosk=useRef();
<Form.Control ref="remosk"></Form.Control>
remosk.current.value//获取当前输入框的值
头文件包含在 "react" 中,需要引入 "useRef" 属性。
非受控组件适合用于戳按钮后再一次提交,受控组件适合动态更新的场景(例如搜索框,随时根据当前的文本内容更新搜索建议)。
受控组件在效率上“似乎”要低于非受控组件,但实质上影响不大,因为受控组件只会修改虚拟 DOM 而不会修改真实 DOM,没有重新渲染的操作。因此 React 官方推荐使用受控组件。
3. Cookie
什么是Cookie?
HTTP 最大的特点是无连接无状态。Cookie 的作用是让浏览器在一段时间内认识你。
Cookie 是浏览一个网站时,由 Web 服务器存储在你的机器硬盘上的一个小的文本文件。当再次来到该网站时,浏览器会先检查有无对应的 Cookie 。如果有,浏览器会自动带上 Cookie 发送到服务端。
注:为什么我们需要显式地写上
credentials:"include"
CS571.org 和 localhost 是不同的域名。通常情况下,浏览器不允许 http 请求跨域携带 cookies 所以需要特殊标明
HTTP-Only 的 Cookie
如果该 Cookie 被设置为 HTTP-Only 则它只能在服务端修改,客户端的 JS 脚本无法访问或修改它。
HW6:登录状态
在 HW6 中,我们需要实现这样一个功能:检测登录状态,如果在线则在导航栏内显示“登出”,如果离线,显示“登入”。
由于 HTTP-Only 不能被 JS 看到,所以需要使用 sessionStorage 配合 ContextProvider 来记录登陆状态。
4. 细节知识
1. 模板字符串
使用 `` 括起来。
内部可以使用$表示转义字符
示例代码:
fetch(`https://cs571.org/api/f23/hw6/messages?chatroom=${props.name}`,{})
2. HW6:页面强制刷新
在 submit 完修改后立刻调用一次 loadMessages
3. HW6:“不同聊天室” 的实现
导航栏:使用 Navbar 组件
下拉菜单:使用 NavDropdown 组件
HW6 在 BrowserRouter 部分的结构如下:
<BrowserRouter>
<Routes>
<Route path="/" element={<BadgerLayout chatrooms={chatrooms} />}>
<Route index element={<BadgerChatHome />} />
<Route path="/login" element={<BadgerLogin />}></Route>
<Route path="/register" element={<BadgerRegister />}></Route>
<Route path="/logout" element={<BadgerLogout />}></Route>
{
chatrooms.map(chatroom => {
return <Route key={chatroom} path={`chatrooms/${chatroom}`} element={<BadgerChatroom name={chatroom} />} />
})
}
<Route path="*" element={<BadgerNoMatch />} />
</Route>
</Routes>
</BrowserRouter>
可以看到,不同 Chatroom 的链接虽然不同,但使用的 React 组件是一致的,仅在传入的 props.name 上作区分。因此,在 Chatroom 间切换,页面不会重新加载。
故使用 useEffect(loadMessages, [props]);
而非 useEffect(loadMesages,[])