Skip to content

共享数据

由于插件是 分别独立对 *.mock.* 等文件作为单独入口进行编译的, 这导致了 mock 文件编译后的依赖关系不一致,每个 mock 文件拥有独立的作用域, 使得即使多个 *.mock.* 虽然引入了同一个 data.ts 文件,然而确是完全不同两份 data, 使得对 data 的操作,在不同的 *.mock.* 文件中并不能共享。

对于一些复杂场景,期望 接口 B 返回被 接口 A 修改过的数据,比如:

模拟 对 文章列表和文章的修改:

ts
const posts = [
  { id: 1, title: 'post1', content: '', author: 'Mark' },
  { id: 2, title: 'post2', content: '', author: 'John' },
]
  • /api/post/delete/:id 将会删除文章,
  • /api/post/update/:id 用于修改文章,
  • /api/post/list 获取所有文章列表

期望 调用 删除、修改文章的接口后,重新调用获取所有文章的接口能够返回已修改的内容。

如果对数据的操作比较简单,我们可以将 数据、模拟请求配置都放在 同一个 *.mock.ts 中编写:

ts
import { defineMock } from 'vite-plugin-mock-dev-server'

const posts = [
  { id: 1, title: 'post1', content: '', author: 'Mark' },
  { id: 2, title: 'post2', content: '', author: 'John' },
]

export default defineMock([
  {
    url: '/api/post/list',
    body: () => posts
  },
  {
    url: '/api/post/delete/:id',
    body: ({ params }) => {
      const index = posts.find(post => post.id === Number.parseInt(params.id))
      index !== -1 && posts.splice(index, 1)
      return { message: 'success' }
    }
  },
  {
    url: '/api/post/update/:id',
    body: ({ params, body }) => {
      const index = posts.find(post => post.id === Number.parseInt(params.id))
      index !== -1 && (posts[index] = { ...posts[index], ...body })
      return { message: 'success' }
    }
  }
])

而如果对于复杂场景,我们可能需要拆解为不同的文件来进行管理时:

ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/list',
  body: () => posts
})
ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/update/:id',
  body: ({ params, body }) => {
    const index = posts.findIndex(post => post.id === Number.parseInt(params.id))
    index !== -1 && (posts[index] = { ...posts[index], ...body })
    return { message: 'success' }
  }
})
ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/delete/:id',
  body: ({ params }) => {
    const index = posts.findIndex(post => post.id === Number.parseInt(params.id))
    index !== -1 && posts.splice(index, 1)
    return { message: 'success' }
  }
})
ts
export const posts = [
  { id: 1, title: 'post1', content: '', author: 'Mark' },
  { id: 2, title: 'post2', content: '', author: 'John' },
]

这时候,接口将不会按预期返回被修改的数据,这是由于每个 *.mock.ts 都是独立引入 data.ts进行单独编译的。 它们都有独立的作用域,使得对 data 的操作在不同的 *.mock.ts 中并不能共享。

解决方案

使用 defineMockData

为此,插件提供了一个 defineMockData(key, initialData) 来解决这类问题。

只需要将 data.ts 中的数据包装在 defineMockData 中即可。

ts
import { defineMockData } from 'vite-plugin-mock-dev-server'

export const posts = defineMockData('posts', [
  { id: 1, title: 'post1', content: '', author: 'Mark' },
  { id: 2, title: 'post2', content: '', author: 'John' },
])
ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/list',
  body: () => posts.value
})
ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/update/:id',
  body: ({ params, body }) => {
    const index = posts.value.findIndex(post => post.id === Number.parseInt(params.id))
    index !== -1 && (posts.value[index] = { ...posts.value[index], ...body })
    return { message: 'success' }
  }
})
ts
import { defineMock } from 'vite-plugin-mock-dev-server'
import { posts } from '../shared/data'

export default defineMock({
  url: '/api/post/delete/:id',
  body: ({ params }) => {
    const index = posts.value.findIndex(post => post.id === Number.parseInt(params.id))
    index !== -1 && posts.value.splice(index, 1)
    return { message: 'success' }
  }
})

defineMockData 将数据隔离到单独的共享作用域中,并通过 key 保证数据的唯一性。

说明

defineMockData 仅是基于 memory 提供的共享数据支持,如果需要做 mock 数据持久化,建议使用 nosql, 如 lowdblevel 等。

Released under the MIT License.