V-Model is a model plugin for Vue.js, like ng-resource. based on axios, path-to-regexp, and bluebird.
The V-Model provides interaction support with RESTful services, can work with Vue.js 1.x and 2.x.
See more about ng-resource
> npm i -S v-model
import Model from 'v-model'; // set baseURL Model.http.defaults.baseURL = '//api.laoshu133.com'; // install Vue.use(Model);
import Vue from 'vue'; import Model from 'v-model'; // set baseURL Model.http.defaults.baseURL = '//api.laoshu133.com'; // install plugin Vue.use(Model); const PostModel = Model.extend('/posts/:id', { publish: { method: 'POST' } }, { EDITING: 0, PUBLISHED: 1 }); const app = new Vue({ el: '#app', data: { post: new PostModel({ status: PostModel.EDITING, content: '', title: '' }) }, methods: { load(id) { this.post = PostModel.get({ id: id }); return this.post.$promise; }, save(data) { return this.post.$save(data); } } });
Before you can create model(s), you need to generate a Model.
Model.extend(url, actions, staticProps, options);
An Express-style path string, e.g /posts/:id.
Hash with declaration of custom actions.
{
action1: {method:?, params:?, isArray:?, headers:?, ...},
action2: {method:?, params:?, isArray:?, hasPagination:?, ...}
}
Default actions:
{
get: { method: 'GET' },
save: { method: 'POST' },
update: { method: 'PUT' },
delete: { method: 'DELETE' },
query: { method: 'GET', isArray:true }
};
Where:
action{String} The name of action.method{String} Case insensitive HTTP method (e.g. GET, POST, PUT, DELETE, JSONP, etc).params{Object} Optional set of pre-bound parameters for this action.headers{Object} Optional set of pre-bound request headers for this action.timeout{Number} timeout in milliseconds.isArray{Boolean} If true then the returned object for this action is an array.hasPagination{Boolean} Only work withisArray: true, if true then tranform the request result to{items: requestResult, pagination: {num: ?, size: ?, total: ?}}
Hash with declaration of static properties.
Model.extend('/posts/:id', null, {
EDITING: 0,
PUBLISHED: 1
});
Set http request default settings for.
Where:
baseURLwill be prepended tourlunlessurlis absolute.headersare custom headers to be sent
See more axios config
With static method:
// get single post const post = PostModel.get({ id: 1 }); // get post list const posts = PostModel.query({ status: PostModel.PUBLISHED }); // update const post = PostModel.update({ id: 1, title: 'New post title' }); // delete PostModel.delete({ id: 1 });
With instance method:
// create/save let post = new PostModel(); let promise = post.$save({ title: 'Post title' }) // update let post = new PostModel({ id: 1, title: 'Post title' }); let promise = post.$update({ title: 'New post title' });
V-Model support pagination via reponse headers X-Pagination.
Some http request:
> GET /posts?page_num=1&page_size=20 HTTP/1.1
> Host: api.laoshu133.com
> User-Agent: curl/7.49.1
>
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< X-Pagination: {"num":1,"size":20,"total":44}
[{"id":1,"title":"Post title","content":"content..."}]
Usage:
const PostModel = Model.extend('/posts/:id', { query: { method: 'get', hasPagination: true } }); let postsData = PostModel.query({ page_size: 20, page_num: 1 }); postsData.$promise.then(data => { console.log(data === postsData); // true console.log(postsData); // { "pagination":{"num":1,"size":20,"total":44}, "items": [...]} });
Sometimes we need to abort the request, such as quick switch page number.
Usage:
import Model from 'v-model'; import Pormise from 'bluebird'; // enable bluebird cancellation Promise.config({ cancellation: true }); const PostModel = Model.extend('/posts/:id', { query: { method: 'get', hasPagination: true } }); new Vue({ data() { return { query: { page_num: 1 }, itemsData: { pagination: { num: 1, size: 20, total: 0 }, items: [] } } }, methods: { load() { // Cancel the last request // If it has not responded yet let promise = this.itemsData.$promise; if(promise) { promise.cancel(); } // make a new request this.itemsData = PostModel.query(query); } }, watch: { query() { this.load(); } }, created() { this.load(); } });
The V-Model instance/result has a $resolved flag.
Can be used for loading status.
Usage:
<template> <div class="main"> <div class="list"> <div v-if="!itemsData.$resolved" class="loading">Loading...</div> <ul v-else> <li v-for="item in itemsData.items">{{item.id}}</li> </ul> </div> <div class="pagination" v-if="itemsData.$resolved">...</div> </div> </template> <script> import Model from 'v-model'; const PostModel = Model.extend('/posts/:id', { query: { method: 'get', hasPagination: true } }); export default { data() { return { itemsData: { pagination: { num: 1, size: 20, total: 0 }, items: [] } }; }, created() { this.itemsData = PostModel.query({ page_num: 1 }); } }; </script>
You can intercept requests or responses.
// global interceptor
const http = PostModel.http;
// request
http.interceptors.request.use(beforeSend, requestError);
// response
http.interceptors.response.use(afterSend, responseError);
See more axios Interceptors
> npm test
MIT