datagent
Version:
一个用于模块化管理前端请求的工具
277 lines (217 loc) • 9.22 kB
Markdown
# Datagent
[](https://www.npmjs.com/package/datagent)
[](https://travis-ci.org/lpreterite/datagent)
`Datagent`是一个用于前端Ajax请求的模块化工具,提供字段定义,方法扩展,切换源等功能。在如React, Vue, Angular等现代前端框架下不同UI层面通信的数据我们称为视图模型(ViewModel)。现在互联网常用于客户端与服务器间通信都是基于RESTful方式设计的持久化服务,这种基于持久化的设计可以借助`Datagent`将通信数据表示为数据模型(DataModel)。数据模型管理着数据字段和通信服务,同时为编排业务代码提供相关方法的钩子进行预处理或后处理。
> 你可以马上尝试在`codepen`上的[例子](https://codepen.io/packy1980/pen/OEpNWW/)。
## 安装
npm
```sh
npm install datagent
```
yarn
```sh
yarn add datagent
```
## 远端、链接、数据模型
这三种定义的关系就如标题一样,链接和数据模型都是建立在远端之上。远端可以是一个服务,而链接管理着远端,在数据模型需要操作数据时就必须使用链接取得远端才能完成通信。
以下是三种常用类:
- 远端 Remote
- 链接 Contact
- 数据模型 DataModel
用`Datagent`快速创建一个包含远端的链接:
```js
import axios from "axios"
import Datagent from "datagent"
const contact = Datagent.Contact({
base: axios.create({ baseURL: '/api' })
})
```
数据模型实例化时把链接作为参数传入:
```js
const UserModel = Datagent.Model({ name: 'user' })
const $user = new UserModel({ contact })
```
尝试请求数据:
```js
$user.find({id:1}).then(data=>{
// [GET] /api/user
// => { status:200, data: { id:1, nickname:'Tony' } }
console.log(data);
})
```
## 数据模型
```js
// api/user.js
import axios from "axios"
import { HOST } from "./config"
export function getUsers(params){
return axios.get(`${HOST}/api/user`, { params })
}
export function getUserById(id){
return axios.get(`${HOST}/api/user/${id}`)
}
export function createUser(data){
return axios.post(`${HOST}/api/user`, data)
}
export function updateUser(data){
return axios.put(`${HOST}/api/user/${data.id}`, data)
}
export function deleteUserById(id){
return axios.delete(`${HOST}/api/user/${data.id}`)
}
```
上面是常见的基于`Restful`接口代码,随着项目持续发展这类代码只会越来越多。当需要修改时不能直观知道接口请求参数和返回数据,则不是那么容易降低出错的可能,这将会带来较多的麻烦。使用`Datagent`定义数据模型能减少较多的手写代码冗余。
```js
// models/user.model.js
import Datagent from "datagent"
const UserModel = Datagent.Model({ name: "user" })
```
## 定义字段
字段是数据模型的有效描述。在数据模型中定义的字段,虽然在请求(或提交)数据时并不会进行过滤或格式化,这钟功能将在钩子以可选的方式提供设置。
其次的作用在于为你的项目提高可读性,为接口部分提供更多的描述。一目了然的代码使同事能更快的加入项目。
```js
// models/user.model.js
import Datagent from "datagent"
const UserModel = Datagent.Model({
name: "user",
fields: {
id: { type: Number, default: null },
name: { type: String, default: '' },
disabled: { type: String, default: '' },
}
})
```
## 模型的使用
`Datagent`通讯部分是基于`Restful`的方式,数据模型则提供统一的处理数据的方法:
- fetch:请求多份数据,发送`[GET] /user`请求。
- find:根据`id`请求单份数据,发送`[GET] /user/:id`请求。
- save:根据`id`提交数据。`id`不存在则新增数据,发送`[POST] /user`请求;`id`存在则更新数据,发送`[PUT] /user`请求。
- destroy:根据`id`请求销毁数据,发送`[DELETE] /user/:id`请求。
```js
// test.js
import contact from "contact"
const $user = new UserModel({ contact })
$user.fetch({ disabled: 0 }).then(users=>{
// [GET] /api/user?disabled=0
// => { status: 200, data: [] }
console.log(users)
})
$user.find({id:1}).then(user=>{
// [GET] /api/user/1
// => { status: 200, data: { id:1, name:"Tony", disabled: 1 } }
console.log(user)
})
$user.save({ name:"Ben", disabled: 0 }).then(res=>{
// [POST] /api/user | { name:"Ben", disabled: 0 }
// => { status: 200, data: { id:2, name:"Ben", disabled: 0 } }
console.log(res)
})
$user.save({ id:1, name:"Tony", disabled: 1 }).then(res=>{
// [PUT] /api/user/1 | { id:1, name:"Tony", disabled: 1 }
// => { status: 200, data: { id:1, name:"Tony", disabled: 1 } }
console.log(res)
})
// 发送带id的DELETE请求
$user.destroy({id:2}).then(res=>{
// [DELETE] /api/user/2
// => { status: 200, data: { id:2, name:"Ben", disabled: 0 } }
console.log(res)
})
```
除了自带方法之外,还可以根据业务的需要添加方法。
```js
// models/user.model.js
import Datagent from "datagent"
const UserModel = Datagent.Model({
name: "user",
fields: {
id: { type: Number, default: null },
name: { type: String, default: '' },
disabled: { type: String, default: '' },
},
methods: {
login(account){
return this.remote().post(this._url + '/login', account)
},
logout(){
return this.remote().get(this._url + '/logout')
}
}
})
const $user = new UserModel()
$user.login({ email: 'tony1990@qq.com', password: '******' }).then(res=>{
// [POST] /api/user/login | { email: 'tony1990@qq.com', password: '******' }
// => { status: 200 }
})
$user.logout().then(res=>{
// [GET] /api/user/logout
// => { status: 200 }
})
```
模型实例提供`remote()`方法获得远端服务,再使用远端服务发送信息至服务器登录,关于远端的使用可以参看[API参考 - Remote](./API.md#Remote)
## 钩子
钩子是数据模型的方法使用前后的预设方法,用于处理数据的一种设计。
目前钩子只有两种:`before`, `after`。
钩子能在定义数据模型时设置:
```js
import axios from 'axios'
import Datagent from "datagent"
const { respondData } = Datagent.Hooks
const contact = Datagent.Contact({
base: axios.create({ baseURL: 'localhost/api' })
})
const UserModel = Datagent.Model({
name: 'user',
hooks: {
fetch: { after:[respondData()] }
}
})
const $user = new UserModel({ contact })
$user.fetch().then(data=>console.log)
// [GET] localhost/api/user
// respond => { status: 200, data: [{id:1, name:'Tony'},{id:2, name:'Ben'}] }
// respondData => [{id:1, name:'Tony'},{id:2, name:'Ben'}]
```
也能在调用方法时进行设置:
```js
$user.fetch({}, {
hooks:{ after: [ respondData() ] }
}).then(data=>console.log)
// [GET] localhost/api/user
// respond => { status: 200, data: [{id:1, name:'Tony'},{id:2, name:'Ben'}] }
// respondData => [{id:1, name:'Tony'},{id:2, name:'Ben'}]
```
`respondData`方法为我们把返回的`resquest.data`抽出来,再传递至下一个方法。钩子支持设置`fetch`, `find`, `save`, `delete`等模型自身或定义的方法,让一些业务代码或者额外的处理写在方法调用前,达到减少冗余代码的目的。
目前`Datagent`提供了以下一些钩子处理的方法:
- [`respondData()`](./docs/API.md#respondData)
- [`format()`](./docs/API.md#format)
- [`formatFor()`](./docs/API.md#formatFor)
- [`filter()`](./docs/API.md#filter)
- [`filterFor()`](./docs/API.md#filterFor)
钩子方法并不多,需要各位多提供意见及时完善满足更多需求,暂时没能满足你需要的欢迎在这里提issue。
有时候一些处理需在所有钩子生效,比如以下状况:
```js
import Datagent from "datagent";
const Model = Datagent.Model({
hooks: {
fetch: { after: [respondData(), format()]},
find: { after: [respondData(), format()]},
save: { before: [format()], after: [respondData()]},
delete: {after: [respondData()]},
publish: {after: [respondData()]}
}
}
```
这种例子较为常见,这里提供两个处理函数方便钩子的设置:
```js
import Datagent from "datagent";
const Model = Datagent.Model({
hooks: {
// 只设置发送数据前的钩子,save:before
...Datagent.mapSendHook([format()]),
// 设置接收数据后的钩子,包括:fetch:after, find:after
...Datagent.mapReceiveHook([respondData(), requestHandle(), format()])
}
}
```
经过上面的例子相信对`Datagent`的使用有了一定的兴趣。`Datagent`提供的数据模型还有字段、方法、钩子等功能在后面再一一细说。如果想了解得更多,可以阅读[API参考](docs/API.md)或源代码。