v-model

    0.0.9 • Public • Published

    V-Model

    npm version build status

    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

    Installation

    > npm i -S v-model
    
    import Model from 'v-model';
     
    // set baseURL
    Model.http.defaults.baseURL = '//api.laoshu133.com';
     
    // install
    Vue.use(Model);

    Usage

    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);
            }
        }
    });

    Model Factory

    Before you can create model(s), you need to generate a Model.

    Model.extend(url, actions, staticProps, options);

    url

    An Express-style path string, e.g /posts/:id.

    actions

    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 with isArray: true, if true then tranform the request result to {items: requestResult, pagination: {num: ?, size: ?, total: ?}}

    staticProps

    Hash with declaration of static properties.

    Model.extend('/posts/:id', null, {
        EDITING: 0,
        PUBLISHED: 1
    });
    

    options

    Set http request default settings for.

    Where:

    • baseURL will be prepended to url unless url is absolute.
    • headers are custom headers to be sent

    See more axios config

    API

    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'
    });

    Pagination

    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": [...]}
    });

    Cancellation

    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();
        }
    });

    $resolved flag

    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> 

    Interceptors

    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

    Running tests

    > npm test
    

    License

    MIT

    Install

    npm i v-model

    DownloadsWeekly Downloads

    14

    Version

    0.0.9

    License

    MIT

    Unpacked Size

    34.3 kB

    Total Files

    11

    Last publish

    Collaborators

    • laoshu133