欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue 与 dot 渲染表格 时间复杂度分析

程序员文章站 2022-04-04 10:06:42
...

    doT.js,用过的都知道,渲染表格贼快。doT.js特点是快,小,无依赖其他插件。压缩版仅有4K大小。

  1. dot的基本语法:
    {{= }} for interpolation
    {{ }} for evaluation
    {{~ }} for array iteration
    {{? }} for conditionals
    {{! }} for interpolation with encoding
    {{# }} for compile-time evaluation/includes and partials
    {{## #}} for compile-time defines
    是不是看着和vue有点像?
  2. dot的基本用法(基本上分为三个部分你就能运用到项目中):
    在.cshtml中:
    <script id="staticTable_Tmp" type="text/x-dot-template">
    <table class="fund-table">
    <thead>
    <tr style="line-height:40px">
    <td style="padding-left:20px !important; width:100px">功能分类</td>
    <td style="padding-left:20px !important; width:90px">登录跳转次数</td>
    <td style="text-align:right;width: 84px!important;">频次</td>
    <td style="text-align:right; width: 80px!important;">百分比</td>
    </tr>
    </thead>
    </table>
    <div class="tableScrollContainer" style="">
    <table class="fund-table">
    <tbody>
    {{ if(it.length>0 ) { }}
    {{ for(prop in it){ }}
    <tr style="height:33px;line-height:32px">
    <td style="padding-left:20px !important; width:100px">
    {{? it[prop].Category.length <= 28 }}
    <a href="{{= it[prop].Url }}" target="_blank" class="stockName detailJump" title="{{= it[prop].Url }}">{{= it[prop].Category }}</a>
    {{??}}
    <a href="{{= it[prop].Url }}" target="_blank" class="stockName detailJump" title="{{= it[prop].Url }}">{{! it[prop].Category.substring(0,26)+'..' }}</a>
    {{?}}
    </td>
    <td style="text-align:right;cursor: default;width: 98px!important;">{{= it[prop].FromLogin }}</td>
    <td style="text-align:right;cursor: default;width: 90px!important;">
    {{?it[prop].CountLink.length>0}}
    <a href="{{= it[prop].CountLink }}" target="_blank">{{= it[prop].Frequency }}</a>
    {{??}}
    {{= it[prop].Frequency }}
    {{?}}
    </td>
    <td style="text-align:right;cursor: default;width: 80px!important;">{{= it[prop].Percent }}</td>
    </tr>
    {{ } }}
    {{ } else{ }}
    <tr>
    <td>无数据</td>
    </tr>
    {{ } }}
    </tbody>
    </table>
    </div>
    </script>

    这部分就是单纯的写在一个js标签中,看着上面的id,必须为ID。然后,在你需要布局的地方写下
    <div class="staticTableHook ">
    </div>

    这里就是挂载上面模板的地方
    最后的就是在我们js获取数据源的地方,将请求过来的json数据与模板绑定到dot上
     var interText = doT.template($("#" + tmpName).text());
                        $("." + className).html(interText(res));

这样就能够渲染到界面上了,但dot里面没有排序,插件,搜索,就单单的渲染一个表格。
3. 同样的,用vue也做了一个表格渲染的模板,代码如下:

define(['Vue'], function(Vue){
    Vue.component('tra-common',{
        props:['it','list'],
        template: `
        <div class='componentContainer' v-if="it != null">
            <div class='fund-panel'>
            <div class="title">
                <span class="fund-title-inline">交易申请表</span>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">所属产品</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.FundName}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">交易方式</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.TransactionMeans}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">证券名称</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.SecurityName}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">发行人性质</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.IssuerNature}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">发行期代码</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.IssuingCode||"--"}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">正式代码</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.SecurityCode||"--"}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">资产类别</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.AssetClass}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">主体评级</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.IssuerRating}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">债券属性</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.WindIndustry}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">债券评级</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.DebtRating||"--"}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">票面利率</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.CouponRate}}</span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">存续期限</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.RemainTerm}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">发行规模(亿元)</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.IssueScale}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">买卖方向</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.TransactionDirection}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">预计交易时间</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.EstimatedTransactionTime}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">交易平台</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.TradingPlatform}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">预计交易价格(元)</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.TransactionPriceMin}}-{{it.TransactionPriceMax}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5 ">预计交易规模(万元)</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.TransactionVolume}} </span>
                    </div>
                </div>
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5 ">收益率</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.YtmMin}}-{{it.YtmMax}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">代持方式</div>
                    <div class="fund-col-7 spanStyle">
                        <span>{{it.AgreementMeans}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-6">
                    <div class="fund-selpanel-title fund-label fund-col-5">其他需要载明的事项</div>
                    <div class="fund-col-7 spanStyle ">
                        <span>{{it.Remarks}} </span>
                    </div>
                </div>
            </div>
            <div class="fund-row">
                <div class="fund-col-12">
                    <div class="fund-selpanel-title fund-label" style='width:210px;float:left'>附件</div>
                    <div class="fund-col-7 spanStyle">
                        <div>
                            <span v-if="list[0]==='--'">
                                {{list[0]}}
                            </span>
                            <span style = "margin-bottom:8px;display:inline-block" v-for="(item,index) in list" :key='index'>
                                <a class="fund-link" :href ="'/FileManage/FilePreview?fileid='+item.FileId"> {{item.FileName }}</a>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class='fund-panel' style='margin-top:10px'>
            <div class="fund-row">
                <div class="title">
                    <span class="fund-title-inline">审核明细</span>
                </div>
            </div>
            <div v-if="it.ApplicationOperList.length>0">
                <div v-for="item in it.ApplicationOperList">
                    <div class="fund-row">
                        <div class="fund-col-6">
                            <div class="fund-selpanel-title fund-label fund-col-5 ">审核人</div>
                            <div class="fund-col-7 spanStyle">
                                <span>{{item.Operator}} </span>
                            </div>
                        </div>
                        <div class="fund-col-6">
                            <div class="fund-selpanel-title fund-label fund-col-5 ">审核时间</div>
                            <div class="fund-col-7 spanStyle">
                                <span>{{item.OperationTime}}</span>
                            </div>
                        </div>
                    </div>
                    <div class="fund-row">
                        <div class="fund-col-6">
                            <div class="fund-selpanel-title fund-label fund-col-5 ">审核结果</div>
                            <div class="fund-col-7 spanStyle">
                                <span>{{item.AuditResult}} </span>
                            </div>
                        </div>
                    </div>
                    <div class="fund-row">
                        <div class="fund-col-12">
                            <div class="fund-selpanel-title fund-label fund-col-2 ">审核意见</div>
                            <div class="fund-col-9 spanStyle" style='padding-left:42px'>
                                <span>{{item.AuditOpinion}}</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div v-else>暂无审核意见</span></div>
        </div>
    </div>
    `
    }),
    Vue.component('fix-thead-table',{
        props:['datatable'],
        computed: {
            col:function(){
                return this.datatable.thead.length;
            },
            field:function(){
                return this.datatable.fields;
            },
            thead:function(){
                return this.datatable.thead;
            },
            tbody:function(){
                return this.datatable.tbody
            },
            theadWidth:function (param) {
                var Twidth=null;
                $.each(this.datatable.thead,function(index,value){
                    if(value.width){
                        Twidth +=value.width.split('p')[0]-0+10;
                    }   
                })
                return (Twidth+30)+"px"
            }
        },
        beforeCreate:function() {
            console.time("vue")
            console.time("Updata-vue")  
        },
        mounted:function () {
            console.timeEnd("vue")  
            console.log(1)
        },
        updated() {
            console.log(2)
            console.timeEnd("Updata-vue")  
        },
        template:`
        <div>
            <table class="fund-table thead" :style="{width:theadWidth}">
                <thead :class=''>
                    <tr>
                        <td v-for="item in thead" :style="{textAlign:item.align,width:item.width}">
                            {{item.title}}
                        </td>
                    </tr>
                </thead>
            </table>
            <div :style="{overflow:'auto',height:datatable.height,width:theadWidth,overflowX: 'hidden' }">
                <table class="fund-table tbody" :style="{width:theadWidth}">
                    <tbody>
                        //注意这里(第一种)↓
                        <tr v-for='item in tbody'>
                            <td> 
                             {{item.Category}}
                            </td><td> 
                            {{item.FromLogin}}
                           </td><td> 
                           {{item.Frequency}}
                          </td><td> 
                          {{item.Percent}}
                         </td>
                        </tr>
                        //注意这里↑
                        //注意这里(第二种)↓
                        <tr v-for='item in tbody'>
                        <td v-for = '(i,index) in thead' 
                        :style="{width:i.width,textAlign:i.align,overflow:'hidden',whiteSpace:'nowrap',textOverflow:'ellipsis'}">
                            <a v-if='item[i.link]↓↓▩' :href="item[i.link]">
                                {{item[i.field]}}
                            </a>
                            <span v-else>
                                {{item[i.field]}}
                            </span>
                        </td>
                    </tr>
                         //注意这里↑
                    </tbody>
                </table>
            </div>
        </div>
        `
    })
})

这是一个公用组件,写的是一个固定表头的table,传入一个表格的基本数据,然后渲染出来。没什么大问题,原来设想的是做一个datatables组件一样的东西,传入一些基本的数据就可以,实现自定义的配置出一个表格。比如td的宽度,text-align,thead,link地址。后来说是第二种方法双层循环会不会渲染很慢?后来就展开了一系列表格性能检测,先顺便展示一下vue生成表格的核心方法。

var app = new Vue({
                el:'#app',
                data:{
                    datatable:[{
                        thead:[{
                            title:'功能分类',
                            align:'left',
                            field:'Category',
                            width:"110px",
                            link :'Url'
                        },
                        {
                            title:'登录跳转次数',
                            align:'right',
                            field:'FromLogin',
                            width:"90px",
                        },
                        {
                            title:'频次',
                            align:'right',
                            field:'Frequency',
                            width:"105px",
                            link :'CountLink'
                        },{
                            title:'百分比',
                            align:'right',
                            field:'Percent',
                            width:"120px"
                        }],
                        tbody:{},
                        height:'264px'
                    }],
                        tbody:{}
                    }]
                },
                beforeCreate() {
                    console.time("data")
                },
                mounted() {
                    console.timeEnd("data")
                },
            })

这里的title就是表格的头部显示。field就是第一种方法中我们循环的时候需要的字段。通过
<tr v-for='item in tbody'>
<td v-for = '(i,index) in thead'
:style="{width:i.width,textAlign:i.align,overflow:'hidden',whiteSpace:'nowrap',textOverflow:'ellipsis'}">
<a v-if='item[i.link]↓↓▩' :href="item[i.link]">
{{item[i.field]}}
</a>
<span v-else>
{{item[i.field]}}
</span>
</td>
</tr>

双层循环动态的生成td,这样我们只需要配置好一个表格的基本属性,就可以动态的生成不定列表格。同样双层循环渲染td也带来了很大的时间消耗。

beforeCreate:function() {
            console.time("vue")
            console.time("Updata-vue")  
        },
        mounted:function () {
            console.timeEnd("vue")  
        },
        beforUpdata(){
            console.time("Updata2")  
        },
        updated() {
            console.timeEnd("Updata-vue")  
            console.timeEnd("Updata2")  
        },

这里就是说创建组件到挂载成功,以及更新数据渲染成功,分别打印出时间。
vue 与 dot 渲染表格 时间复杂度分析
可以看到当加载组件是vue:1.9 ms,然后更新完data以后,重新渲染表格Updata-vue:56.7ms.我们再来看看dot的渲染时间:

 renderList: function (tmpName, className, res) {

                    return new Promise(function (resolve, reject) {
                        console.time("dot")
                        var interText = doT.template($("#" + tmpName).text());
                        $("." + className).html(interText(res));
                        $(".behaviorAnalysis").unblock();
                        resolve();
                        console.timeEnd("dot")
                    });

                },

代码是上面的,运行结果:vue 与 dot 渲染表格 时间复杂度分析
这不是偶然结果,我运行了很多次,vue在挂载组件的时候可能很快,但按照我这样写的双循环去渲染td的时候就是很消耗时间了。但请看到最后–>

  • vue重点是在组件复用,数据交互,我同时应用了三次组件在一个el:#app下,同样,我也调用了dot的模板,做了三次表格渲染。界面数据条数是不一样的:vue 与 dot 渲染表格 时间复杂度分析
    -这个是运行的结果
    vue 与 dot 渲染表格 时间复杂度分析
    数据的多少对dot结果有影响,但这里我就有点不懂了
    vue 与 dot 渲染表格 时间复杂度分析
    最后那个是beforeupdate-updated的时间。
    可以清楚的看到dot渲染的时间和数据列有关系,但对于vue来说,组件挂载了一次以后,后面的时间都成了0ms,可能是对vue了解的不多。 updata2都是0,这一点我以为它会每个组件渲染的时候都回去执行一次呢!!而且可以看到三个表格,结构都是不一样的。这是我这次code中不理解的地方,先记录下来。如果有哪位有耐心读到这里,多谢帮忙解惑!
  • 疑问的地方:vue的这个监听器我是可以理解,就是created到mounted,但后面的那两次vue:0ms是怎么回事,如果说组件只创建一次的话,那怎么就跑了三次监听器?也就是第一个红方框的那三个数据。
  • 还有后面的update-vue后面的两个怎么是0ms
  • updata-vue 这里时间这么长是代码写的有问题,还是vue这样用就需要这么长的时间?
  • //注意这里(第一种)↓
    <tr v-for='item in tbody'>
    <td>
    {{item.Category}}
    </td><td>
    {{item.FromLogin}}
    </td><td>
    {{item.Frequency}}
    </td><td>
    {{item.Percent}}
    </td>
    </tr>
    //注意这里↑

    我曾把渲染的过程先用字段代替,不走双循环,需要的时间同样也是50多ms.