diff --git a/changelog.md b/changelog.md
index fd7e96c5c..6574a00bf 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,4 +1,7 @@
# 更新日志
+2.0(2021-02)
+- 增加updateModel属性,可以配置自动模式,自动watch属性并响应变化
+
2.0(2021-01)
- 修改了日期下拉面板中的当前时间按钮的交互效果
- 新增年区间和年季度区间控件
diff --git a/dev.html b/dev.html
new file mode 100644
index 000000000..650cf45a6
--- /dev/null
+++ b/dev.html
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dist/fix/fix.compact.js b/dist/fix/fix.compact.js
index 2e00a6c1d..affb9a10b 100644
--- a/dist/fix/fix.compact.js
+++ b/dist/fix/fix.compact.js
@@ -183,6 +183,74 @@
needPop && popTarget();
};
+ BI.Widget.prototype._initElement = function () {
+ var self = this;
+ var render = BI.isFunction(this.options.render) ? this.options.render : this.render;
+ var els;
+ if (this.options.updateMode === "auto" && this._store) {
+ // 自动更新模式
+ var childComponents = {};
+ var rendered = false;
+ this._watchers.push(Fix.watch(this.model, function () {
+ if (rendered) {
+ var newEls = render && render.call(this);
+ BI.each(childComponents, function (i, childComponent) {
+ var nextProps = BI.get([newEls], childComponent.path);
+ if (nextProps) {
+ var shouldUpdate = childComponent.component.shouldUpdate && childComponent.component.shouldUpdate(nextProps);
+ childComponent.component._update(nextProps, shouldUpdate);
+ childComponent.props = BI.extend(childComponent.props, nextProps);
+ }
+ });
+ } else {
+ els = render && render.call(this);
+
+ function traverse (parent, path) {
+ BI.each(parent, function (i, child) {
+ const childPath = path.concat(i);
+ if (BI.isArray(child)) {
+ traverse(child, childPath);
+ } else if (BI.isPlainObject(child)) {
+ if (child.type) {
+ child.__ref = function (_ref) {
+ if (_ref) {
+ var comp = childComponents[this.getName()] = {};
+ comp.component = _ref;
+ comp.props = child;
+ comp.path = childPath;
+ } else {
+ delete childComponents[this.getName()];
+ }
+ };
+ }
+ traverse(child, childPath);
+ }
+ });
+ }
+
+ traverse([els], []);
+ rendered = true;
+ }
+ }));
+ } else {
+ els = render && render.call(this);
+ }
+ if (BI.isPlainObject(els)) {
+ els = [els];
+ }
+ if (BI.isArray(els)) {
+ BI.each(els, function (i, el) {
+ if (el) {
+ BI._lazyCreateWidget(el, {
+ element: self
+ });
+ }
+ });
+ }
+ // if (this._isRoot === true || !(this instanceof BI.Layout)) {
+ this._mount();
+ };
+
var unMount = BI.Widget.prototype.__d;
BI.Widget.prototype.__d = function () {
try {
diff --git a/src/base/single/button/button.basic.js b/src/base/single/button/button.basic.js
index 2bd82b17d..4a5d68a0c 100644
--- a/src/base/single/button/button.basic.js
+++ b/src/base/single/button/button.basic.js
@@ -389,11 +389,6 @@ BI.BasicButton = BI.inherit(BI.Single, {
return this.options.text;
},
- setValue: function (value) {
- BI.BasicButton.superclass.setValue.apply(this, arguments);
- this.options.setValue && this.options.setValue.call(this, value);
- },
-
_setEnable: function (enable) {
BI.BasicButton.superclass._setEnable.apply(this, arguments);
if (enable === true) {
diff --git a/src/base/single/button/buttons/button.js b/src/base/single/button/buttons/button.js
index 05819b04f..6db1349a3 100644
--- a/src/base/single/button/buttons/button.js
+++ b/src/base/single/button/buttons/button.js
@@ -1,4 +1,3 @@
-
/**
* 文字类型的按钮
* @class BI.Button
@@ -44,7 +43,10 @@ BI.Button = BI.inherit(BI.BasicButton, {
BI.Button.superclass._init.apply(this, arguments);
var o = this.options, self = this;
if (BI.isNumber(o.height) && !o.clear && !o.block) {
- this.element.css({height: o.height / BI.pixRatio + BI.pixUnit, lineHeight: (o.height - 2) / BI.pixRatio + BI.pixUnit});
+ this.element.css({
+ height: o.height / BI.pixRatio + BI.pixUnit,
+ lineHeight: (o.height - 2) / BI.pixRatio + BI.pixUnit
+ });
} else if (o.clear || o.block) {
this.element.css({lineHeight: o.height / BI.pixRatio + BI.pixUnit});
} else {
diff --git a/src/base/single/single.js b/src/base/single/single.js
index d2b51f0d0..c4d15291d 100644
--- a/src/base/single/single.js
+++ b/src/base/single/single.js
@@ -192,6 +192,7 @@ BI.Single = BI.inherit(BI.Widget, {
setValue: function (val) {
if (!this.options.readonly) {
this.options.value = val;
+ this.options.setValue && this.options.setValue(val);
}
},
@@ -199,11 +200,24 @@ BI.Single = BI.inherit(BI.Widget, {
return this.options.value;
},
+ update: function (props, shouldUpdate) {
+ if (BI.isObject(shouldUpdate)) {
+ props = shouldUpdate;
+ }
+ if ("value" in props) {
+ this.setValue(props.value);
+ }
+ if ("text" in props) {
+ this.setText && this.setText(props.text);
+ }
+ },
+
destroyed: function () {
if (BI.isNotNull(this.showTimeout)) {
clearTimeout(this.showTimeout);
this.showTimeout = null;
}
BI.Tooltips.remove(this.getName());
- },
+ }
});
+BI.shortcut("bi.single", BI.Single);
diff --git a/src/core/ob.js b/src/core/ob.js
index c4aacf624..9eab5d35a 100644
--- a/src/core/ob.js
+++ b/src/core/ob.js
@@ -72,6 +72,9 @@
// 获得一个当前对象的引用
_initRef: function () {
+ if (this.options.__ref) {
+ this.options.__ref.call(this, this);
+ }
if (this.options.ref) {
this.options.ref.call(this, this);
}
@@ -79,6 +82,10 @@
//释放当前对象
_purgeRef: function () {
+ if (this.options.__ref) {
+ this.options.__ref.call(null);
+ this.options.__ref = null;
+ }
if (this.options.ref) {
this.options.ref.call(null);
this.options.ref = null;
diff --git a/src/core/widget.js b/src/core/widget.js
index 3f2779c63..7b6b341f9 100644
--- a/src/core/widget.js
+++ b/src/core/widget.js
@@ -7,7 +7,7 @@
*/
!(function () {
- function callLifeHook(self, life) {
+ function callLifeHook (self, life) {
var hook = self.options[life] || self[life];
if (hook) {
var hooks = BI.isArray(hook) ? hook : [hook];
@@ -32,7 +32,8 @@
baseCls: "",
extraCls: "",
cls: "",
- css: null
+ css: null,
+ updateMode: "manual" // manual / auto
});
},
@@ -73,8 +74,11 @@
shouldUpdate: null,
- update: function () {
- },
+ update: null,
+
+ beforeUpdate: null,
+
+ updated: null,
beforeDestroy: null,
@@ -223,26 +227,59 @@
* @private
*/
_mount: function (force, deep, lifeHook, predicate) {
+ if (this.__beforeMount(force, deep, lifeHook, predicate)) {
+ this.__afterMount(lifeHook, predicate);
+ return true;
+ }
+ return false;
+ },
+
+ __beforeMount: function (force, deep, lifeHook, predicate) {
var self = this;
if (!force && (this._isMounted || !this.isVisible() || this.__asking === true || !(this._isRoot === true || (this._parent && this._parent._isMounted === true)))) {
return false;
}
lifeHook !== false && callLifeHook(this, "beforeMount");
this._isMounted = true;
- this._mountChildren && this._mountChildren();
BI.each(this._children, function (i, widget) {
!self.isEnabled() && widget._setEnable(false);
!self.isValid() && widget._setValid(false);
- widget._mount && widget._mount(deep ? force : false, deep, lifeHook, predicate);
+ widget.__beforeMount && widget.__beforeMount(deep ? force : false, deep, lifeHook, predicate);
+ });
+ this._mountChildren && this._mountChildren();
+ return true;
+ },
+
+ __afterMount: function (lifeHook, predicate) {
+ BI.each(this._children, function (i, widget) {
+ widget.__afterMount && widget.__afterMount(lifeHook, predicate);
});
lifeHook !== false && callLifeHook(this, "mounted");
this.fireEvent(BI.Events.MOUNT);
predicate && predicate(this);
- return true;
},
_mountChildren: null,
+ _update: function (nextProps, shouldUpdate) {
+ var o = this.options;
+ callLifeHook(this, "beforeUpdate");
+ if (shouldUpdate) {
+ var res = this.update && this.update(nextProps, shouldUpdate);
+ } else if (BI.isNull(shouldUpdate)) {
+ // 默认使用shallowCompare的方式进行更新
+ var nextChange = {};
+ BI.each(nextProps, function (key, value) {
+ if (o[key] !== value) {
+ nextChange[key] = value;
+ }
+ });
+ var res = this.update && BI.isNotEmptyObject(nextChange) && this.update(nextChange);
+ }
+ callLifeHook(this, "updated");
+ return res;
+ },
+
isMounted: function () {
return this._isMounted;
},
@@ -534,12 +571,12 @@
BI.Widget.context = context = contextStack.pop();
};
- function pushTarget(_current) {
+ function pushTarget (_current) {
if (current) currentStack.push(current);
BI.Widget.current = current = _current;
}
- function popTarget() {
+ function popTarget () {
BI.Widget.current = current = currentStack.pop();
}
diff --git a/src/core/wrapper/layout.js b/src/core/wrapper/layout.js
index 5d4fdc470..6b10e753d 100644
--- a/src/core/wrapper/layout.js
+++ b/src/core/wrapper/layout.js
@@ -268,19 +268,13 @@ BI.Layout = BI.inherit(BI.Widget, {
if (!child.shouldUpdate) {
return null;
}
- return child.shouldUpdate(this._getOptions(item)) === true;
+ return child.shouldUpdate(this._getOptions(item));
},
updateItemAt: function (index, item) {
if (index < 0 || index > this.options.items.length - 1) {
return;
}
-
- var child = this._children[this._getChildName(index)];
- var updated;
- if (updated = child.update(this._getOptions(item))) {
- return updated;
- }
var del = this._children[this._getChildName(index)];
delete this._children[this._getChildName(index)];
this.options.items.splice(index, 1);
@@ -367,7 +361,14 @@ BI.Layout = BI.inherit(BI.Widget, {
patchItem: function (oldVnode, vnode, index) {
var shouldUpdate = this.shouldUpdateItem(index, vnode);
- if (shouldUpdate === true || (shouldUpdate === null && !this._compare(oldVnode, vnode))) {
+ var child = this._children[this._getChildName(index)];
+ if (shouldUpdate) {
+ return child._update(this._getOptions(vnode), shouldUpdate);
+ }
+ if (shouldUpdate === null && !this._compare(oldVnode, vnode)) {
+ if (child.update) {
+ return child.update(this._getOptions(vnode));
+ }
return this.updateItemAt(index, vnode);
}
},