diff --git a/changelog.md b/changelog.md index 8c8bb9ba5..a8520e128 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,6 @@ # 更新日志 2.0(2021-07) +- 新增bi.virtual_group_list组件 - layout支持forceUpdate刷新方式 - width属性支持calc() - 修改了颜色选择器交互 diff --git a/examples/dev.html b/examples/dev.html index d499ed483..3b11585b5 100644 --- a/examples/dev.html +++ b/examples/dev.html @@ -2,8 +2,9 @@ - - + + +
diff --git a/src/base/list/virtualgrouplist.js b/src/base/list/virtualgrouplist.js new file mode 100644 index 000000000..510ade0d8 --- /dev/null +++ b/src/base/list/virtualgrouplist.js @@ -0,0 +1,155 @@ +/** + * 同时用于virtualGroup和virtualList特性的虚拟列表 + * + * Created by GUY on 2017/5/22. + * @class BI.VirtualList + * @extends BI.Widget + */ +BI.VirtualGroupList = BI.inherit(BI.Widget, { + props: function () { + return { + baseCls: "bi-virtual-group-list", + overscanHeight: 100, + blockSize: 10, + scrollTop: 0, + rowHeight: "auto", + items: [] + }; + }, + + init: function () { + var self = this; + this.renderedIndex = -1; + }, + + render: function () { + var self = this, o = this.options; + return { + type: "bi.vertical", + items: [{ + type: "bi.layout", + ref: function () { + self.topBlank = this; + } + }, { + type: "bi.virtual_group", + height: o.rowHeight * o.items.length, + ref: function () { + self.container = this; + }, + layouts: [{ + type: "bi.vertical", + scrolly: false + }] + }, { + type: "bi.layout", + ref: function () { + self.bottomBlank = this; + } + }], + element: this + }; + }, + + // mounted之后绑定事件 + mounted: function () { + var self = this, o = this.options; + this._populate(); + this.element.scroll(function (e) { + o.scrollTop = self.element.scrollTop(); + self._calculateBlocksToRender(); + }); + BI.ResizeDetector.addResizeListener(this, function () { + self._calculateBlocksToRender(); + }); + }, + + _isAutoHeight: function () { + return this.options.rowHeight === "auto"; + }, + + _renderMoreIf: function () { + var self = this, o = this.options; + var height = this.element.height(); + var minContentHeight = o.scrollTop + height + o.overscanHeight; + var index = (this.renderedIndex + 1) * o.blockSize, cnt = this.renderedIndex + 1; + var lastHeight; + var getElementHeight = function () { + return self.container.element.height() + self.topBlank.element.height() + self.bottomBlank.element.height(); + }; + while ((lastHeight = getElementHeight()) < minContentHeight && index < o.items.length) { + var items = o.items.slice(index, index + o.blockSize); + this.container.addItems(items, this); + var addedHeight = getElementHeight() - lastHeight; + this.tree.set(cnt, addedHeight); + this.renderedIndex = cnt; + cnt++; + index += o.blockSize; + } + }, + + _calculateBlocksToRender: function () { + var o = this.options; + this._isAutoHeight() && this._renderMoreIf(); + var height = this.element.height(); + var minContentHeightFrom = o.scrollTop - o.overscanHeight; + var minContentHeightTo = o.scrollTop + height + o.overscanHeight; + var start = this.tree.greatestLowerBound(minContentHeightFrom); + var end = this.tree.leastUpperBound(minContentHeightTo); + var items = []; + var topHeight = this.tree.sumTo(Math.max(-1, start - 1)); + this.topBlank.setHeight(topHeight); + if (this._isAutoHeight()) { + for (var i = (start < 0 ? 0 : start); i <= end && i <= this.renderedIndex; i++) { + var index = i * o.blockSize; + for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { + items.push(o.items[j]); + } + } + this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))); + this.container.element.height(this.container.element.height()); + this.container.populate(items); + this.container.element.height("auto"); + } else { + for (var i = (start < 0 ? 0 : start); i <= end; i++) { + var index = i * o.blockSize; + for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { + items.push(o.items[j]); + } + } + this.container.element.height(o.rowHeight * o.items.length - topHeight); + this.container.populate(items); + } + }, + + _populate: function (items) { + var o = this.options; + if (items && this.options.items !== items) { + this.options.items = items; + } + this.tree = BI.PrefixIntervalTree.uniform(Math.ceil(o.items.length / o.blockSize), this._isAutoHeight() ? 0 : o.rowHeight * o.blockSize); + + this._calculateBlocksToRender(); + try { + this.element.scrollTop(o.scrollTop); + } catch (e) { + } + }, + + restore: function () { + this.renderedIndex = -1; + this.options.scrollTop = 0; + // 依赖于cache的占位元素也要初始化 + this.topBlank.setHeight(0); + this.bottomBlank.setHeight(0); + }, + + populate: function (items) { + if (items && this.options.items !== items) { + this.restore(); + } + this._populate(items); + } +}); +BI.shortcut("bi.virtual_group_list", BI.VirtualGroupList); + diff --git a/src/base/list/virtuallist.js b/src/base/list/virtuallist.js index 28f2d54d3..f5208cc49 100644 --- a/src/base/list/virtuallist.js +++ b/src/base/list/virtuallist.js @@ -1,5 +1,5 @@ /** - * 表示当前对象 + * 虚拟列表 * * Created by GUY on 2017/5/22. * @class BI.VirtualList @@ -64,8 +64,7 @@ BI.VirtualList = BI.inherit(BI.Widget, { var self = this, o = this.options; var height = this.element.height(); var minContentHeight = o.scrollTop + height + o.overscanHeight; - var index = (this.cache[this.renderedIndex] && (this.cache[this.renderedIndex].index + o.blockSize)) || 0, - cnt = this.renderedIndex + 1; + var index = (this.renderedIndex + 1) * o.blockSize, cnt = this.renderedIndex + 1; var lastHeight; var getElementHeight = function () { return self.container.element.height() + self.topBlank.element.height() + self.bottomBlank.element.height(); @@ -94,7 +93,7 @@ BI.VirtualList = BI.inherit(BI.Widget, { var minContentHeightTo = o.scrollTop + height + o.overscanHeight; var start = this.tree.greatestLowerBound(minContentHeightFrom); var end = this.tree.leastUpperBound(minContentHeightTo); - var needDestroyed = []; + var needDestroyed = [], needMount = []; for (var i = 0; i < start; i++) { var index = this.cache[i].index; if (!this.cache[i].destroyed) { @@ -125,7 +124,8 @@ BI.VirtualList = BI.inherit(BI.Widget, { } if (this.cache[i].destroyed === true) { for (var j = index; j < index + o.blockSize && j < o.items.length; j++) { - var w = this.container._addElement(j, BI.extend({root: true}, BI.stripEL(o.items[j])), this); + var w = this.container._addElement(j, o.items[j], this); + needMount.push(w); currentFragment.appendChild(w.element[0]); } this.cache[i].destroyed = false; @@ -135,6 +135,9 @@ BI.VirtualList = BI.inherit(BI.Widget, { this.container.element.append(lastFragment); this.topBlank.setHeight(this.tree.sumTo(Math.max(-1, start - 1))); this.bottomBlank.setHeight(this.tree.sumTo(this.renderedIndex) - this.tree.sumTo(Math.min(end, this.renderedIndex))); + BI.each(needMount, function (i, child) { + child && child._mount(); + }); BI.each(needDestroyed, function (i, child) { child && child._destroy(); }); @@ -179,7 +182,8 @@ BI.VirtualList = BI.inherit(BI.Widget, { }, destroyed: function () { - this.restore(); + this.cache = {}; + this.renderedIndex = -1; } }); BI.shortcut("bi.virtual_list", BI.VirtualList); diff --git a/src/less/core/utils/common.less b/src/less/core/utils/common.less index 2eef73c56..22832e25f 100644 --- a/src/less/core/utils/common.less +++ b/src/less/core/utils/common.less @@ -500,6 +500,23 @@ display: none; } + //& .bi-hover-visible-item { + // display: none; + //} + //&:hover .bi-hover-visible-item { + // display: block; + // &.bi-f-h, &.bi-f-v, &.bi-f-s-h, &.bi-f-s-v { + // display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ + // display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ + // display: -ms-flexbox; /* TWEENER - IE 10 */ + // display: -webkit-flex; /* NEW - Chrome */ + // display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ + // } + // &.i-item { + // display: inline-block; + // } + //} + & .bi-hover-visible-item { visibility: hidden; }