📜  mirage js 处理帖子 - Javascript (1)

📅  最后修改于: 2023-12-03 14:44:18.979000             🧑  作者: Mango

Mirage JS 处理帖子 - Javascript

目录:

  1. Mirage JS 是什么
  2. Mirage JS 中创建模型
  3. Mirage JS 中创建路由
  4. Mirage JS 中使用关系和带有 “后端”的功能
  5. Mirage JS 中的身份验证
  6. Mirage JS 如何在前端使用
  7. 示例代码
1. Mirage JS 是什么?

Mirage JS 是一个用于模拟前端 Api 数据的库,使开发过程中的调试工作更简单,可以减少开发员与后端服务器的耦合度。它支持构建可靠的测试数据,并具有路由、模型和更多的功能,可以帮助我们更快地开发和测试应用程序的前端部分。

2. Mirage JS 中创建模型

模型是一个与数据库中存储的表结构相关联的概念,它定义了数据的结构和验证行为。在 Mirage JS 中,模型用纯 JavaScript 实现。它可以定义模型字段,模型之间的关系以及他们之间的约束。

定义模型:

我们可以通过 Mirage JS 的 schema.create 方法来定义模型,

import { createServer, Model, Response } from "miragejs";

const server = createServer({
  models: {
    article: Model,
  },

  // some other options here
});

在这个例子中,我们定义了一个 article 模型。

定义模型约束:

你可以通过“属性”来定义一个字段的约束,例如:

const server = createServer({
  models: {
    article: Model.extend({
      title: attr("string"),
    }),
  },

  // some other options here
});

这里,我们定义了一个 article 模型,它具有一个 title 字段,该字段的类型为 “string”。

3. Mirage JS 中创建路由

在 Mirage JS 中,路由定义了一个 API 的实际接口,这是应用程序与后端服务器之间的接口。我们可以通过对路由及其处理程序的设置来模拟服务端的数据返回,这将使我们的应用程序在没有服务器的情况下运行,还可以在开发和测试过程中减少调试和开发时间,使开发过程高效和快速。

定义路由:

const server = createServer({
  routes() {
    this.get("/api/articles", () => ({
      articles: [
        { id: 1, title: "Article 1" },
        { id: 2, title: "Article 2" },
      ],
    }));
  },
});

在这段代码中,我们定义了一个路由,这个路由定义了参数,并给这个路由的处理程序返回两篇文章。

带参数的路由:

const server = createServer({
  routes() {
    this.get("/api/articles/:id", (schema, request) => {
      const id = request.params.id;
      const article = schema.articles.find(id);
      return { article };
    });
  },
});

在这个例子中,我们定义了一个带有参数的路由,它接受一个参数 id 作为输入,并返回与该 id 相关联的文章。

4. Mirage JS 中使用关系和带有 “后端”的功能

Mirage JS 支持通过 schema 定义各种关系,包括一对多、一对一和多对多关系。它还支持一些“后端”功能,例如使用 SQL 进行查询和分页。

定义关系:

const server = createServer({
  models: {
    user: Model,
    article: Model.extend({
      author: belongsTo(),
    }),
  },

  routes() {
    this.get("/api/users/:id", (schema, request) => {
      const userId = request.params.id;
      const user = schema.users.find(userId);
      const articles = schema.articles.where({ authorId: userId });
      return { user, articles };
    });
  },
});

在这个例子中,我们定义了一个 user 模型和一个 article 模型,article 模型还有一个与 user 模型的 1 对 1 关系,即 author属性,此模型还将我们定义 article 模型的路由处理程序返回文章与作者。

使用 Mirage JS 进行查询和分页

const server = createServer({
  models: {
    article: Model.extend({
      comments: hasMany(),
    }),
  },

  routes() {
    this.get("/api/articles", (schema, request) => {
      const { page, perPage } = request.queryParams;
      const totalCount = schema.articles.all().length;
      const articles = schema.articles
        .all()
        .slice((page - 1) * perPage, page * perPage);

      return {
        articles,
        meta: { page, perPage, totalCount },
      };
    });
  },
});

在这个例子中,我们定义了一个具有“hasMany”关系的文章模型,并定义了一个用于查询和分页的路由。该路由返回一些元数据,例如当前页,每页的文章数以及文章总数。

5. Mirage JS 中的身份验证

Mirage JS 还支持通过使用凭证和会话来实现身份验证,以帮助我们实现更安全的应用程序。

使用 Mock 凭证和会话

const server = createServer({
  routes() {
    this.post("/api/login", (schema, request) => {
      const { email, password } = JSON.parse(request.requestBody);
      const user = schema.users.findBy({ email, password });

      if (user) {
        return { token: "abc123" };
      } else {
        return new Response(401, {}, { error: "Invalid credentials" });
      }
    });

    this.get("/api/user", (schema, request) => {
      const apiKey = request.headers.Authorization.split(" ")[1];
      const user = schema.users.findBy({ apiKey });

      if (user) {
        return user;
      } else {
        return new Response(401, {}, { error: "Unauthorized" });
      }
    });
  },
});

在这个例子中,我们定义了两个路由,一个是用于模拟用户登录的路由,另一个用于模拟 API 资源中的用户信息。在这个例子中,我们模拟了身份验证、会话和凭证的概念。

6. Mirage JS 如何在前端使用

要在前端使用 Mirage JS,您需要先将 Mirage JS 导入您的项目。通常,您可以在“测试”或“开发”阶段使用 Mirage JS。

将 Mirage JS 导入项目

import { createServer } from "miragejs";

createServer({
  // your routes and models here
});

再使用了上面的 Mirage JS 的代码后,你可以在 Vue 或 React 的生命周期方法中使用 migratedRoutes 例如。

在 Vue 中使用 Mirage JS

import { createServer } from "miragejs";

export default {
  data() {
    return { articles: [] };
  },

  async created() {
    if (process.env.NODE_ENV === "development") {
      createServer({
        routes() {
          this.get("/api/articles", () => ({
            articles: [
              { id: 1, title: "Article 1" },
              { id: 2, title: "Article 2" },
            ],
          }));
        },
      });
    }

    // Fetch data from /api/articles
    const response = await fetch("/api/articles");
    const { articles } = await response.json();
    this.articles = articles;
  },
};

在 React 中使用 Mirage JS

import React, { useState, useEffect } from "react";
import { createServer } from "miragejs";

function ArticleList() {
  const [articles, setArticles] = useState([]);

  useEffect(() => {
    if (process.env.NODE_ENV === "development") {
      createServer({
        routes() {
          this.get("/api/articles", () => ({
            articles: [
              { id: 1, title: "Article 1" },
              { id: 2, title: "Article 2" },
            ],
          }));
        },
      });
    }

    fetch("/api/articles")
      .then((response) => response.json())
      .then((data) => setArticles(data.articles));
  }, []);

  return (
    <ul>
      {articles.map((article) => (
        <li key={article.id}>{article.title}</li>
      ))}
    </ul>
  );
}
7. 示例代码
import { createServer, Model, Response } from "miragejs";

const server = createServer({
  models: {
    article: Model.extend({
      author: belongsTo(),
      comments: hasMany(),
    }),
    user: Model,
    comment: Model.extend({
      article: belongsTo(),
    }),
  },

  routes() {
    this.get("/api/articles", (schema) => schema.articles.all());

    this.post("/api/articles", (schema, request) => {
      const attrs = JSON.parse(request.requestBody).article;
      const author = schema.users.create(attrs.author);
      const article = schema.articles.create({ ...attrs, author });
      return article;
    });

    this.get("/api/articles/:id", (schema, request) => {
      const id = request.params.id;
      const article = schema.articles.find(id);
      const comments = server.schema.comments.all().filter((c) => c.articleId === id);
      return { id: article.id, ...article.attrs, comments };
    });

    this.patch("/api/articles/:id", (schema, request) => {
      const id = request.params.id;
      const attrs = JSON.parse(request.requestBody);
      const article = schema.articles.find(id);
      return article.update(attrs);
    });

    this.delete("/api/articles/:id", (schema, request) => {
      const id = request.params.id;
      const article = schema.articles.find(id);
      return article.destroy();
    });

    this.get("/api/users/:id", (schema, request) => {
      const userId = request.params.id;
      const user = schema.users.find(userId);
      const articles = schema.articles.where({ authorId: userId });
      return { user, articles };
    });

    this.post("/api/login", (schema, request) => {
      const { email, password } = JSON.parse(request.requestBody);
      const user = schema.users.findBy({ email, password });

      if (user) {
        return { token: "abc123" };
      } else {
        return new Response(401, {}, { error: "Invalid credentials" });
      }
    });

    this.get("/api/user", (schema, request) => {
      const apiKey = request.headers.Authorization.split(" ")[1];
      const user = schema.users.findBy({ apiKey });

      if (user) {
        return user;
      } else {
        return new Response(401, {}, { error: "Unauthorized" });
      }
    });
  },
});

// eslint-disable-next-line no-console
console.log(server.db.dump());