一步步编写avalon组件04:GRID组件

更新于 2016-08-05  约 15 分钟

grid组件(表格)是非常常用的组件,尤其是后台系统。它的制定也是五花八门的。因此jQuery有大量的grid组件,每个都庞大无比,集成各种功能,复杂得像Excel。但即便是这样,我们的产品经理总是能提出一些需求,让你死去活来。因此有时我们不需要一个功能丰富的grid,而是一个扩展性极好的grid。

avalon2强大的组件机制就此而生。

我们分析一下grid的结构。通常就是一个表头,表头固定。表身,放数据。表尾,总是一个分页栏或是汇总栏。因此,我们的grid写成这样就行了,其他都使用slot传进来,其可制性极强。

avalon.component('ms-grid', {
    template: heredoc(function () {
        /*
         <div class="grid">
         <div><slot name="header"/></div>
         <div><slot name="tbody"/></div>
         <div class="pager"><slot name="pager" /></div>
         </div>
         */
    }),
    defaults: {  }
 })

分页栏,我们使用之前的分析就好了。于是组件容器里写成这样:

<xmp :widget="{is:'ms-grid'}">
        <table slot='header' class="header">
            <tr>
                <td :for="el in @header" style="width:200px" >
                    {{el}}
            </td>
        </tr>
    </table>
    <table slot="tbody" class="tbody">
        <tr :for="obj in @data |limitBy(@count, @start)">
            <td :for="el in obj | selectBy(@header)" style="width:200px">{{el}}</td>
        </tr>
    </table> 
    <ms-pager slot="pager" :widget="{onReady:@aaa}" />
</xmp>

对于这个grid本身而言,最难的部分就是使用limitBy与selectBy这两个过滤器。limitBy要与分析栏进行联动。selectBy要与表头联动。

然后我们加一点随机数据与样式吧。

<!DOCTYPE html>

<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src='../../dist/avalon.js'></script>
        <script>
            function heredoc(fn) {
                return fn.toString().replace(/^[^\/]+\/\*!?\s?/, '').
                        replace(/\*\/[^\/]+$/, '').trim().replace(/>\s*</g, '><')
            }
            avalon.component('ms-grid', {
                template: heredoc(function () {
                    /*
                     <div class="grid">
                     <div><slot name="header"/></div>
                     <div><slot name="tbody"/></div>
                     <div class="pager"><slot name="pager" /></div>
                     </div>
                     */
                }),
                defaults: {  }
            })

            function genData(n) {
                var list = []
                for (var i = 0; i < n; i++) {
                    list.push({
                        aaa: new Date - i,
                        bbb: Math.random().toString(32).replace(/0\./, ""),
                        ccc: (Math.random() + "").replace(/0\./, ""),
                        ddd: i
                    })
                }
                return list
            }
            var vm = avalon.define({
                $id: 'widget1',
                header: ['aaa','bbb','ccc'],
                start: 0,
                count: 10,
                data: genData(300),
                aaa: function (e) {
                    e.vmodel.$watch('currentPage', function (a) {
                        vm.start = a - 1
                        console.log(vm.start)
                    })
                },
                ddd: 'bbb'
            })

            avalon.component("ms-pager", {
                template: heredoc(function(){
                    /*
                      <div class="pagination">
                        <ul>
                        <li :for="el in @pages" 
                           :class="[ el == @currentPage && 'active' ]">
                           <a href="javascript:void(0)" :click="@gotoPage(el, $event)">{{el}}</a>
                        </li>
                        </ul>
                      </div>
                     */
                }),
                defaults: {
                    totalPage: 25,
                    currentPage: 1,
                    showPage: 7,
                    pages: [1, 2, 3, 4, 5, 6, 7],
                    gotoPage: function (page, e) {
                        this.currentPage = page;
                        this.pages = this.getPages();
                    },
                    getPages: function () {
                        var pages = [];
                        var s = this.showPage, l = this.currentPage, r = this.currentPage, c = this.totalPage;
                        pages.push(l);
                        while (true) {
                            if (pages.length >= s) {
                                break;
                            }
                            if (l > 1) {
                                pages.unshift(--l);
                            }
                            if (pages.length >= s) {
                                break;
                            }
                            if (r < c) {
                                pages.push(++r);
                            }
                        }

                        return pages;
                    }
                }
            });
        </script>
    </head>
    <body>
        <style>
            .header {
                border:1px solid #000;
                width: 600px;
                border-collapse: collapse;
            }
            .header td{
                border:1px solid #000;
                text-align: center;
                font-weight: 700;
                height:30px;
                color: #607fa6;
                font-weight: 700;
            }
            .tbody{
                width: 600px;
                margin-top: -1px;
                border:1px solid #000;
                border-collapse: collapse;
            }
            .tbody td{
                border:1px solid #000;
                height: 30px;
            }
           
            .pagination ul{
                list-style: none;
                margin: 0;
                padding: 0;
            }
            .pagination li{
                float: left;
            }
            .pagination li a{
                text-decoration: none;
                display: inline-block;
                width:40px;
                height: 30px;
                line-height: 30px;
                text-align: center;
                background: #fafafa;
                color:#000;
               
            }
            .pagination .active a{
                background: #009a61;
                color:#fff;
            }
            .pager{
                width:600px;
                background: #fafafa;
            }
            .pager > *{
                float: right;
                
            }
        </style>
        <div ms-controller='widget1' >

        <xmp :widget="{is:'ms-grid'}">
                <table slot='header' class="header">
                    <tr>
                        <td :for="el in @header" style="width:200px" >
                            {{el}}
                    </td>
                </tr>
            </table>
            <table slot="tbody" class="tbody">
                <tr :for="obj in @data |limitBy(@count, @start)">
                    <td :for="el in obj | selectBy(@header)" style="width:200px">{{el}}</td>
                </tr>
            </table> 
            <ms-pager slot="pager" :widget="{onReady:@aaa}" />
        </xmp>

    </div>

</body>
</html>

clipboard.png

大家可以到这里下到它的源码

阅读 2.3k更新于 2016-08-05

推荐阅读
javascript魔法师
用户专栏

涉及我的学习心得与经验

1289 人关注
70 篇文章
专栏主页
目录