第 6 部分 - 关系
这个应用程序中还有一个功能 - 列表。如果您点击提醒面板左侧的按钮,将打开一个侧边栏,显示应用程序中的不同列表。
但现在,我们在控制台中只看到一个错误,因为应用程序期望从 /api/lists
获取列表。让我们模拟这个端点。
首先,我们将在服务器顶部的 list
模型中定义一个新模型。
models: {
list: Model,
reminder: Model,
}
我们还将为 GET 到 /api/lists
添加一个新的路由处理程序,该处理程序返回所有列表。
this.get("/api/lists", (schema, request) => {
return schema.lists.all()
})
Mirage 现在响应 200,但没有列表。让我们在 seeds()
中创建一些列表。
seeds(server) {
server.create("reminder", { text: "Walk the dog" });
server.create("reminder", { text: "Take out the trash" });
server.create("reminder", { text: "Work out" });
server.create("list", { name: "Home" });
server.create("list", { name: "Work" });
}
现在当我们打开侧边栏时,我们看到我们的两个新列表“主页”和“工作”被渲染。
尝试点击一个列表。您将看到一个错误,因为我们的应用程序期望另一个 API 端点存在:/api/lists/1/reminders
。这就是它如何获取特定列表的提醒。让我们看看如何模拟它。
在 Mirage 中模拟处理关系数据的端点的最简单方法是使用 关联。我们将从使用 Mirage 的关联助手来模拟此数据开始。
在这个应用程序中,列表和提醒之间存在一对多关系(一个列表可以有多个提醒),因此我们将使用 hasMany
和 belongsTo
助手来定义这种关系。
导入助手并更新您的模型以定义这种关系。
import { createServer, Model, hasMany, belongsTo } from "miragejs"
export default function () {
createServer({
models: {
list: Model.extend({
reminders: hasMany(),
}),
reminder: Model.extend({
list: belongsTo(),
}),
},
// rest of server
})
}
现在 Mirage 知道 list.reminders
和 reminder.list
属性是关系,因此我们可以在路由处理程序中开始使用它们。
让我们使用新的关系模拟 /api/lists/:id/reminders
。此端点应查找相应的列表,并返回属于该列表的所有提醒。
以下是代码。
this.get("/api/lists/:id/reminders", (schema, request) => {
let listId = request.params.id
let list = schema.lists.find(listId)
return list.reminders
})
我们使用 :id
的动态片段,它对应于我们点击的列表。然后我们使用该 ID 在 Mirage 的数据层中查找相应的列表。最后,我们返回与该列表相关的提醒。
将此路由处理程序复制到 Mirage 服务器定义中,并尝试点击每个列表。您应该不再看到错误。但您也看不到任何提醒。这是因为我们创建的提醒还没有与任何列表相关联 - 我们只是单独创建了它们。
要为特定列表创建提醒,我们可以使用新的关系。
seeds(server) {
// Unassociated reminders
server.create("reminder", { text: "Walk the dog" });
server.create("reminder", { text: "Take out the trash" });
server.create("reminder", { text: "Work out" });
let homeList = server.create("list", { name: "Home" });
server.create("reminder", { list: homeList, text: "Do taxes" });
let workList = server.create("list", { name: "Work" });
server.create("reminder", { list: workList, text: "Visit bank" });
}
现在,点击“主页”应显示“缴税”提醒。如果您点击“全部”,应用程序将点击 /api/reminders
端点,该端点仍将返回系统中的所有提醒 - 那些与列表相关的和那些独立的。
最后,尝试在 UI 中为特定列表制作新的提醒。点击“工作”,然后添加一个提醒“回复吉尔”。如果您点击应用程序周围,您将看到它已正确地与“工作”列表相关联。(它显示在“工作”和“全部”中,但不显示在“主页”中)。
这是因为我们的 UI 在我们在列表中创建提醒时已经发送了 { listId }
。要查看这一点,让我们在现有的 POST 路由处理程序中添加一个日志来检查来自请求的 attrs。
this.post("/api/reminders", (schema, request) => {
let attrs = JSON.parse(request.requestBody)
console.log(attrs)
return schema.reminders.create(attrs)
})
创建未关联的任务时,attrs 为 { text: "New todo" }
,但关联的任务有类似 { text: "Respond to Jill", listId: "2" }
的 attrs。
当我们定义关系时,Mirage 在我们的模型上设置了称为外键的特殊属性。这些属性是它跟踪哪些模型相互关联的方式。设置类似 listId
或 reminderIds: []
的外键就足以更新关系并使其反映在所有 Mirage 路由处理程序中。
因此,我们不必更新 POST 处理程序以适应 UI 的列表功能,因为 listId
已经传递到 reminders.create()
中。
Mirage 的关联助手足够灵活,可以模拟几乎任何数据场景,这使得您在模拟处理关系的端点时更容易。
要点
- Mirage 允许您定义和访问关系数据。
- 使用
belongsTo
和hasMany
助手在您的模型上定义命名关系。 - 在路由处理程序中使用关系以返回与其他模型关联的模型或集合。
- Mirage 使用简单的外键来跟踪关系数据。