RubyLouvre / avalon

an elegant efficient express mvvm framework
http://avalonjs.coding.me/
Other
5.8k stars 1.42k forks source link

组件onViewChange事件,无限触发bug #1482

Closed areyouse7en closed 8 years ago

areyouse7en commented 8 years ago

/! built in 2016-6-15:18 version 2.09 by 司徒正美 /

问题描述:当点击分页页码,第三次时候,会无限触发onViewChage事件,导致浏览器卡死,可以看console。 排摸下来,当我改变lists的时候会发生这个,但lists并不是component里面的属性,而且ViewChange不是监听组件的html变化么。 求解决,这个组件离成功只差一步了。。。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>avalon test</title>
    <link rel="stylesheet" type="text/css" href="http://cdn.amazeui.org/amazeui/2.7.0/css/amazeui.min.css">
    <style type="text/css" media="screen">
    .am-pagination-input {
        display: inline-block;
        width: 30px;
        text-align: center;
        padding: .5em 0;
        line-height: 1.2;
        background-color: #fff;
        border: 1px solid #ddd;
        margin-bottom: 5px;
        margin-left: 5px;
        margin-right: 5px;
    }
    </style>
    <script src="avalon.js"></script>
    <script src="pager.js"></script>
    <script>
    var vm = avalon.define({
        $id: "test",
        lists: [],
        getData: function(page, pager) {
            // ajax
            setTimeout(function() {
                // callback
                vm.lists = ['列表项1', '列表项2'];
                pager.totalPages = 20;
                pager.totalItems = 200;
            }, 100);
        }
    });
    </script>
</head>

<body>
    <div class="am-container am-padding" ms-controller="test">
        <ul class="am-list">
            <li ms-for="el in @lists">{{el}}</li>
        </ul>
        <hr>
        <ms-pagination ms-widget="{getData:@getData}"></ms-pagination>
    </div>
</body>

</html>

js代码

'use strict';
/**分页组件
 *样式基于amazeui http://cdn.amazeui.org/amazeui/2.7.0/css/amazeui.min.css
 */

// html编译成string
function html2str(fn) {
    return fn.toString().replace(/^[^\/]+\/\*!?\s?/, '').
    replace(/\*\/[^\/]+$/, '').trim().replace(/>\s*</g, '><')
}

var pagetpl = html2str(function() {
    /*
    <div class="am-g">
        <div class="am-u-md-4">
            <p class="am-margin am-text-sm">共 {{@totalItems}} 条记录,{{@totalPages}} 页</p>
        </div>
        <div class="am-u-md-8">
            <ul class="am-pagination am-pagination-right am-text-xs" ms-visible="@totalPages > 0">
                <li ms-class="{'am-disabled' : @curPage == 1}" ms-if="@standardMode"><a href="javascript:;" ms-click="@getList(1)">首页</a></li>
                <li ms-class="{'am-disabled' : @curPage == 1}"><a href="javascript:;" ms-click="@getList(@curPage-1)"><span class="am-icon-angle-double-left"></span></a></li>
                <li ms-for="el in @pageItems" ms-class="{'am-active' : @curPage==el}">
                    <a href="javascript:;" ms-click="@getList(el)">{{el}}</a>
                    <span class="am-hide">{{@curPage}}</span>
                </li>
                <li ms-class="{'am-disabled' : @curPage == @totalPages}"><a href="javascript:;" ms-click="@getList(@curPage + 1)"><span class="am-icon-angle-double-right"></span></a></li>
                <li ms-class="{'am-disabled' : @curPage == @totalPages}" ms-if="@standardMode"><a href="javascript:;" ms-click="@getList(@totalPages)">尾页</a></li>
                <li class="am-margin-horizontal-sm" ms-if="@standardMode">跳至<input type="text" class="am-pagination-input" ms-duplex-number="@targetPage">页</li>
                <li ms-if="@standardMode"><a href="javascript:;" ms-click="@getList(@targetPage)">Go</a></li>
            </ul>
        </div>
    </div>
    */
});

avalon.component('ms-pagination', {
    template: pagetpl,
    defaults: {
        curPage: 1,
        targetPage: 1,
        totalItems: 0,
        totalPages: 0,
        pageItems: [1],
        standardMode: true,
        getData: function(page, pager) {
            console.log('自定义函数');
        },
        getList: function(page) {
            if (!page || page > this.totalPages && this.totalPages != 0) {
                return;
            }
            this.curPage = page;
            var pager = this;
            this.getData(page, pager);
        },
        onInit: function(a) {
            console.log('init');
        },
        onReady: function(a) {
            console.log('ready');
            this.getList(1);
        },
        onViewChange: function(a) {
            console.log('html changed');
            if (this.totalPages <= 5) {
                this.pageItems = avalon.range(1, this.totalPages + 1);
            } else {
                if (this.curPage < 4) {
                    this.pageItems = avalon.range(1, 6);
                } else if (this.curPage > 3 && this.curPage < this.totalPages - 1) {
                    this.pageItems = avalon.range(this.curPage - 2, this.curPage + 3);
                } else {
                    this.pageItems = avalon.range(this.totalPages - 4, this.totalPages + 1);
                }
            }
        }
    }
});
areyouse7en commented 8 years ago

用这个版本 /! built in 2016-6-16:11 version 2.09 by 司徒正美 /

无限触发的问题没了,但是点击页码第二次以后,会多次次渲染。 xxx

RubyLouvre commented 8 years ago

好了,终于好了

RubyLouvre commented 8 years ago

这是逻辑问题,你不断改页面数,当然不断触发viewchange 回调

areyouse7en commented 8 years ago

分页无非就是监听当前页和总页数的变化,然后对页码进行重构。component给出的四个方法,只有onViewChange能用啊。给我指条明路吧大大。。 源码里看viewChange监听的是html的变化,那我就把当前页隐藏在html里,用来当总页数不变的时候触发页码事件;如果是像文档说的,监听的是子属性节点的变化的,那么能把改变的属性告诉我是哪个么,我判断一下就可以避免不必要的操作。 现在的问题都出在渲染,出在ms-class,ms-for,有时候还报ms-effect的错。

RubyLouvre commented 8 years ago

在getList 里面做