diff --git a/demo/js/base/tip/demo.toast.js b/demo/js/base/tip/demo.toast.js index d5cda36fc..9d0352a6f 100644 --- a/demo/js/base/tip/demo.toast.js +++ b/demo/js/base/tip/demo.toast.js @@ -31,7 +31,8 @@ Demo.Toast = BI.inherit(BI.Widget, { height: 30, handler: function () { BI.Msg.toast("这是一条非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长的数据", { - level: "warning" + level: "warning", + autoClose: false }); } } diff --git a/dist/base.css b/dist/base.css index 7e4dca748..7aa6f9854 100644 --- a/dist/base.css +++ b/dist/base.css @@ -862,6 +862,19 @@ li.CodeMirror-hint-active { .bi-message-close { font-size: 25px; } +.bi-message-animate { + -webkit-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -moz-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -o-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; +} +.bi-message-enter { + opacity: 1; +} +.bi-message-leave { + opacity: 0; + transform: translateY(-100%); +} .bi-message-title { font-size: 16px; cursor: pointer; diff --git a/dist/base.js b/dist/base.js index 8498bf5ce..57b42600c 100644 --- a/dist/base.js +++ b/dist/base.js @@ -14768,6 +14768,7 @@ $.extend(BI, { var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose; var toast = BI.createWidget({ type: "bi.toast", + cls: "bi-message-animate bi-message-leave", level: level, autoClose: autoClose, text: message @@ -14782,10 +14783,13 @@ $.extend(BI, { }] }); toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2}); - toast.element.show(); + toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); + autoClose && BI.delay(function () { - toast.element.hide(); - toast.destroy(); + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + BI.delay(function () { + toast.destroy(); + }, 1000); }, 5000); }, _show: function (hasCancel, title, message, callback) { diff --git a/dist/bundle.css b/dist/bundle.css index a89403918..42f3532b7 100644 --- a/dist/bundle.css +++ b/dist/bundle.css @@ -2909,6 +2909,19 @@ li.CodeMirror-hint-active { .bi-message-close { font-size: 25px; } +.bi-message-animate { + -webkit-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -moz-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -o-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; +} +.bi-message-enter { + opacity: 1; +} +.bi-message-leave { + opacity: 0; + transform: translateY(-100%); +} .bi-message-title { font-size: 16px; cursor: pointer; diff --git a/dist/bundle.js b/dist/bundle.js index 60777edef..fe40a5443 100644 --- a/dist/bundle.js +++ b/dist/bundle.js @@ -40467,6 +40467,7 @@ $.extend(BI, { var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose; var toast = BI.createWidget({ type: "bi.toast", + cls: "bi-message-animate bi-message-leave", level: level, autoClose: autoClose, text: message @@ -40481,13 +40482,14 @@ $.extend(BI, { }] }); toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2}); - toast.element.slideDown(500, function () { - autoClose && BI.delay(function () { - toast.element.slideUp(500, function () { - toast.destroy(); - }); - }, 5000); - }); + toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); + + autoClose && BI.delay(function () { + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + BI.delay(function () { + toast.destroy(); + }, 1000); + }, 5000); }, _show: function (hasCancel, title, message, callback) { $mask = $("
").css({ diff --git a/dist/demo.js b/dist/demo.js index 9ff8f2246..8a5304139 100644 --- a/dist/demo.js +++ b/dist/demo.js @@ -1627,7 +1627,8 @@ BI.shortcut("demo.title", Demo.Title);Demo.Toast = BI.inherit(BI.Widget, { height: 30, handler: function () { BI.Msg.toast("这是一条非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长非常长的数据", { - level: "warning" + level: "warning", + autoClose: false }); } } @@ -10692,7 +10693,9 @@ BI.shortcut("demo.tmp", Demo.Func); var model = Fix.define({ name: "原始属性", arr: [{ - n: "a" + n: { + ss: "a" + } }, { n: 0 }] @@ -10703,13 +10706,13 @@ BI.shortcut("demo.tmp", Demo.Func); return model; }, watch: { - "*.*.n": function () { - debugger - }, - "**": function () { - debugger - }, - "arr.1.*": function () { + // "*.*.n": function () { + // debugger + // }, + // "**": function () { + // debugger + // }, + "arr.*.n.*": function () { this.button.setText(this.model.name + "-" + this.model.arr[1].n); } }, @@ -10724,8 +10727,8 @@ BI.shortcut("demo.tmp", Demo.Func); self.button = this; }, handler: function () { - self.model.arr[0].n += 1; - self.model.arr[1].n += 1; + self.model.arr[0].n.ss += 1; + // self.model.arr[1].n += 1; }, text: this.model.name + "-" + this.model.arr[1].n } @@ -11206,6 +11209,11 @@ BI.shortcut("demo.tmp", Demo.Func); this.button.setText(this.model.b); } }, + + // 首先create demo.Fix,按stores数据流走,这样的话,会在原本的init调用前做一些工作,然后再原本的render前也做些工作。 + // 原本的render执行时会create return的内容,此时布局被create + // 布局不走store数据流,create时对items逐个addElement,即create每个item,然后add进父亲(此时确定父子关系) + // 对item的button进行create,button指定element进行create render: function () { var self = this; return { diff --git a/dist/fineui.css b/dist/fineui.css index 7384a260c..3d0c409b6 100644 --- a/dist/fineui.css +++ b/dist/fineui.css @@ -2909,6 +2909,19 @@ li.CodeMirror-hint-active { .bi-message-close { font-size: 25px; } +.bi-message-animate { + -webkit-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -moz-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -o-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; +} +.bi-message-enter { + opacity: 1; +} +.bi-message-leave { + opacity: 0; + transform: translateY(-100%); +} .bi-message-title { font-size: 16px; cursor: pointer; diff --git a/dist/fineui.js b/dist/fineui.js index cb68136c7..04ca5cf03 100644 --- a/dist/fineui.js +++ b/dist/fineui.js @@ -25907,6 +25907,8 @@ Data.Source = BISource = { function noop(a, b, c) {} + //程序自带的,二进制代码,无法看到方法体,显示的是native code + // alert(Array.prototype.sort) function isNative(Ctor) { return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); } @@ -25968,6 +25970,7 @@ Data.Source = BISource = { return; } var segments = path.split('.'); + // 把形如a.*.b中的b对应value拿到手 return function (obj) { for (var i = 0; i < segments.length; i++) { if (!obj) return; @@ -26005,8 +26008,8 @@ Data.Source = BISource = { setImmediate(nextTickHandler); }; } else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || - // PhantomJS - MessageChannel.toString() === '[object MessageChannelConstructor]')) { + // PhantomJS + MessageChannel.toString() === '[object MessageChannelConstructor]')) { var channel = new MessageChannel(); var port = channel.port2; channel.port1.onmessage = nextTickHandler; @@ -26014,19 +26017,19 @@ Data.Source = BISource = { port.postMessage(1); }; } else - /* istanbul ignore next */ - if (typeof Promise !== 'undefined' && isNative(Promise)) { - // use microtask in non-DOM environments, e.g. Weex - var p = Promise.resolve(); - timerFunc = function timerFunc() { - p.then(nextTickHandler); - }; - } else { - // fallback to setTimeout - timerFunc = function timerFunc() { - setTimeout(nextTickHandler, 0); - }; - } + /* istanbul ignore next */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + // use microtask in non-DOM environments, e.g. Weex + var p = Promise.resolve(); + timerFunc = function timerFunc() { + p.then(nextTickHandler); + }; + } else { + // fallback to setTimeout + timerFunc = function timerFunc() { + setTimeout(nextTickHandler, 0); + }; + } return function queueNextTick(cb, ctx) { var _resolve = void 0; @@ -26068,6 +26071,7 @@ Data.Source = BISource = { * directives subscribing to it. */ +// 订阅器 var Dep = function () { function Dep() { _classCallCheck(this, Dep); @@ -26084,6 +26088,7 @@ Data.Source = BISource = { remove(this.subs, sub); }; + //target是全局唯一的watcher对象,watcher对象的addDep会distinct地addSub当前Dep对象 Dep.prototype.depend = function depend() { if (Dep.target) { Dep.target.addDep(this); @@ -26200,7 +26205,7 @@ Data.Source = BISource = { if (isIE9Below) { var VBClassPool = {}; window.execScript([// jshint ignore:line - 'Function parseVB(code)', '\tExecuteGlobal(code)', 'End Function' //转换一段文本为VB代码 + 'Function parseVB(code)', '\tExecuteGlobal(code)', 'End Function' //转换一段文本为VB代码 ].join('\n'), 'VBScript'); var VBMediator = function VBMediator(instance, accessors, name, value) { @@ -26216,7 +26221,7 @@ Data.Source = BISource = { // jshint ignore:line var buffer = []; buffer.push('\tPrivate [$vbsetter]', '\tPublic [$accessors]', '\tPublic Default Function [$vbthis](ac' + timeBucket + ', s' + timeBucket + ')', '\t\tSet [$accessors] = ac' + timeBucket + ': set [$vbsetter] = s' + timeBucket, '\t\tSet [$vbthis] = Me', //链式调用 - '\tEnd Function'); + '\tEnd Function'); //添加普通属性,因为VBScript对象不能像JS那样随意增删属性,必须在这里预先定义好 var uniq = { $vbthis: true, @@ -26229,19 +26234,19 @@ Data.Source = BISource = { uniq[name] = true; } } - //添加访问器属性 + //添加访问器属性 for (name in accessors) { if (uniq[name]) { continue; } uniq[name] = true; buffer.push( - //由于不知对方会传入什么,因此set, let都用上 - '\tPublic Property Let [' + name + '](val' + timeBucket + ')', //setter - '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Set [' + name + '](val' + timeBucket + ')', //setter - '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Get [' + name + ']', //getter - '\tOn Error Resume Next', //必须优先使用set语句,否则它会误将数组当字符串返回 - '\t\tSet[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tIf Err.Number <> 0 Then', '\t\t[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tEnd If', '\tOn Error Goto 0', '\tEnd Property'); + //由于不知对方会传入什么,因此set, let都用上 + '\tPublic Property Let [' + name + '](val' + timeBucket + ')', //setter + '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Set [' + name + '](val' + timeBucket + ')', //setter + '\t\tCall [$vbsetter](Me, [$accessors], "' + name + '", val' + timeBucket + ')', '\tEnd Property', '\tPublic Property Get [' + name + ']', //getter + '\tOn Error Resume Next', //必须优先使用set语句,否则它会误将数组当字符串返回 + '\t\tSet[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tIf Err.Number <> 0 Then', '\t\t[' + name + '] = [$vbsetter](Me, [$accessors],"' + name + '")', '\tEnd If', '\tOn Error Goto 0', '\tEnd Property'); } for (name in properties) { @@ -26259,7 +26264,7 @@ Data.Source = BISource = { className = makeHashCode('VBClass'); window.parseVB('Class ' + className + body); window.parseVB(['Function ' + className + 'Factory(acc, vbm)', //创建实例并传入两个关键的参数 - '\tDim o', '\tSet o = (New ' + className + ')(acc, vbm)', '\tSet ' + className + 'Factory = o', 'End Function'].join('\r\n')); + '\tDim o', '\tSet o = (New ' + className + ')(acc, vbm)', '\tSet ' + className + 'Factory = o', 'End Function'].join('\r\n')); VBClassPool[body] = className; } var ret = window[className + 'Factory'](accessors, VBMediator); //得到其产品 @@ -26293,14 +26298,18 @@ Data.Source = BISource = { */ var Observer = function () { + //传入想要构造成ob对象的{} function Observer(value) { _classCallCheck(this, Observer); + // value, dep, vmCount三个私有属性 this.value = value; this.dep = new Dep(); this.vmCount = 0; + //处理数组类型 if (_.isArray(value)) { var augment = hasProto ? protoAugment : copyAugment; + //替换数组中的原型方法 augment(value, arrayMethods, arrayKeys); this.model = this.observeArray(value); } else { @@ -26342,16 +26351,23 @@ Data.Source = BISource = { } } + //将正常的对象变成ob对象 + // value为parentKey对应初始值,parentOb为Observer对象(对应想要构造成Ob的obj),parentKey为obj重的key function observe(value, parentObserver, parentKey) { + //value不是对象的话没有必要把他也ob化 if (!_.isObject(value)) { return; } var ob = void 0; + //如果value已经Ob化 if (value.__ob__ instanceof Observer) { ob = value.__ob__; + //observerState.shouldConvert默认为true,貌似也没有谁改过他 } else if (observerState.shouldConvert && (_.isArray(value) || isPlainObject(value))) { + //数组或者对象,递归以value创建Ob ob = new Observer(value); } + //建立子到父的映射 ob.parent = parentObserver || ob.parent; ob.parentKey = parentKey; return ob; @@ -26387,6 +26403,8 @@ Data.Source = BISource = { } } + //@1再Observer构造函数中调用walk的时候调用此函数的情况 + //@1 obj为传入Observer构造函数的plainObj, observer为当前构造的Observer对象的引用,调用walk时shallow并没有传递 function defineReactive(obj, observer, shallow) { var props = {}; var model = void 0; @@ -26438,12 +26456,17 @@ Data.Source = BISource = { // }) // } _.each(obj, function (val, key) { + //跳过对象中的_ob_ if (key in $$skipArray) { return; } + //给当前obj的每个子属性也添加dep(子属性也要ob化),以__dep+key的形式确定当前key是否已经ob化 var dep = observer && observer['__dep' + key] || new Dep(); + //赋予当前observer以__dep+key属性,对应为新建或者之前已将添加过的Dep对象 observer && (observer['__dep' + key] = dep); + //@1 必走observe,如果value是非对象,直接出来 var childOb = !shallow && observe(val, observer, key); + //属性转化成存取器属性 props[key] = { enumerable: true, configurable: true, @@ -26612,6 +26635,7 @@ Data.Source = BISource = { // vm._watchers || (vm._watchers = []) // vm._watchers.push(this) // options + // user初始默认为true,其他是undefined if (options) { this.deep = !!options.deep; this.user = !!options.user; @@ -26630,6 +26654,7 @@ Data.Source = BISource = { this.newDepIds = new Set(); this.expression = ''; // parse expression for getter + //形如a.*.b的正则那么传进来的就是function if (typeof expOrFn === 'function') { this.getter = expOrFn; } else { @@ -26675,6 +26700,7 @@ Data.Source = BISource = { } }; + //交换newXXX和XXX,并清空newXXX Watcher.prototype.cleanupDeps = function cleanupDeps() { var i = this.deps.length; while (i--) { @@ -26708,10 +26734,10 @@ Data.Source = BISource = { if (this.active) { var value = this.get(); if (value !== this.value || - // Deep watchers and watchers on Object/Arrays should fire even - // when the value is the same, because the value may - // have mutated. - _.isObject(value) || this.deep) { + // Deep watchers and watchers on Object/Arrays should fire even + // when the value is the same, because the value may + // have mutated. + _.isObject(value) || this.deep) { // set new value var oldValue = this.value; this.value = value; @@ -26812,7 +26838,7 @@ Data.Source = BISource = { } function routeToRegExp(route) { - route = route.replace(/\*./g, '[a-zA-Z0-9_]+.'); + route = route.replace(/\*/g, '[a-zA-Z0-9_]+'); return '^' + route + '$'; } @@ -26895,35 +26921,45 @@ Data.Source = BISource = { }); return; } - if (/\*\*$|\*$/.test(exp)) { - throw new Error('not support'); - } + // if (/\*\*$|\*$/.test(exp)) { + // throw new Error('not support'); + // } //其他含有*的情况,如*.a,*.*.a,a.*.a if (/\*/.test(exp)) { var currentModel = model; //先获取到能获取到的对象 - var paths = exp.split("."); - for (var _i = 0, len = paths.length; _i < len; _i++) { - if (paths[_i] === "*") { - break; - } - currentModel = model[paths[_i]]; - } - exp = exp.substr(exp.indexOf("*")); - //补全路径 - var parent = currentModel.__ob__.parent, - root = currentModel.__ob__; - while (parent) { - exp = '*.' + exp; - root = parent; - parent = parent.parent; - } + // var paths = exp.split("."); + // //当前model中一层层剥取,尽量取到接近监听字符串的叶子 + // //比如arr.*.n model就剥到arr那一层 + // for (var _i = 0, len = paths.length; _i < len; _i++) { + // if (paths[_i] === "*") { + // break; + // } + // currentModel = model[paths[_i]]; + // } + // exp = exp.substr(exp.indexOf("*")); + // //补全路径 + // //初始父亲为当前剥取到的model的父亲,根为剥去到的model所在Ob(parent也是为了找根,辅助用的) + // var parent = currentModel.__ob__.parent, + // root = currentModel.__ob__; + // while (parent) { + // //用*来补全剥去的路径 + // exp = '*.' + exp; + // //向上溯源 + // root = parent; + // parent = parent.parent; + // } + var root = currentModel.__ob__; var regStr = routeToRegExp(exp); var _dep = new Dep(); + //Ob的构造函数中是没有_globalDeps的,初始化 root._globalDeps || (root._globalDeps = {}); root._globalDeps[regStr] = _dep; var _w = new Watcher(currentModel, function () { + //调用将_dep加入到全局Dep.target(此时是_w)的sub队列中 + //_dep的队列中将会有_w,_w会记录当前_dep在自己的属性中 + //双向绑定 _dep.depend(); return NaN; }, function (newValue, oldValue) { @@ -27178,11 +27214,14 @@ Data.Source = BISource = { var watch$$1 = this.watch; var actions = this.actions; var keys = _.keys(this.$$model).concat(_.keys(state)).concat(_.keys(computed)).concat(context || []); + // 为model对象添加model defineProps(this, keys); childContext && defineContext(this, childContext); this.$$model && (this.model.__ob__ = this.$$model.__ob__); this._init(); + //state中return的对象被包装成ob对象后,ob的model赋值给model的$$state initState(this, state); + //model中添加$$computed对象,里面的属性是存取器属性 initComputed(this, computed); initWatch(this, watch$$1); initMethods(this, actions); @@ -27257,20 +27296,25 @@ Data.Source = BISource = { exports.__esModule = true; });;(function () { + // vm 当前组件 watch 组件中定义的watch function initWatch (vm, watch) { + vm._watchers || (vm._watchers = []); for (var key in watch) { var handler = watch[key]; + // 居然还能是funtion 数组? if (BI.isArray(handler)) { for (var i = 0; i < handler.length; i++) { vm._watchers.push(createWatcher(vm, key, handler[i])); } } else { + // watch的各项存入数组 vm._watchers.push(createWatcher(vm, key, handler)); } } } + // vm 当前组件 key 组件中定义的watch的key值 handler key对应的方法回调 function createWatcher (vm, keyOrFn, handler) { return Fix.watch(vm.model, keyOrFn, _.bind(handler, vm), { store: vm.store @@ -27302,7 +27346,10 @@ Data.Source = BISource = { } var oldWatch = Fix.watch; + + //model 当前组件的model, exp为watch key值 cb为方法回调 options中有当前store Fix.watch = function (model, expOrFn, cb, options) { + // 为sync的传递服务 if (BI.isPlainObject(cb)) { options = cb; cb = cb.handler; @@ -27312,6 +27359,7 @@ Data.Source = BISource = { } return oldWatch.call(this, model, expOrFn, function () { options && options.store && pushTarget(options.store); + //每次watch调用前先将store压栈,之后再出栈 var res = cb.apply(this, arguments); options && options.store && popTarget(); return res; @@ -27348,18 +27396,26 @@ Data.Source = BISource = { }; var _init = BI.Widget.prototype._init; + //以老王的布局穿插理论来看,父子组件间的布局走着玩意是无视store啥的 + //另外,只有init的组件有element的在create时就指定了父亲 BI.Widget.prototype._init = function () { var self = this; var needPop = false; if (window.Fix && this._store) { + // @1.形如{type: "xxx"} 无context为null,此时返回null var store = findStore(this.options.element || context); if (store) { pushTarget(store); needPop = true; } + //widget中指定的store或者model this.store = this._store(); + + //@1则不走 needPop && popTarget(); needPop = false; + + //@1则赋值与全局target作为当前target(环境),入栈是在render入栈 为什么不在此处压栈? pushTarget(this.store); if (this.store instanceof Fix.Model) { this.model = this.store.model; @@ -27368,19 +27424,28 @@ Data.Source = BISource = { } needPop = true; } + //@2进入 _init.apply(this, arguments); + + //为true则必然之前将当前组件环境推进栈中,完成后出来时候要pop,以回到初始化当前组件前(父组件)所在状态,同@3,needPop也与3同步 + //对于没有render的组件,这个会直接执行,之后再搞子组件,而不是像render递归到最后 needPop && popTarget(); }; var _render = BI.Widget.prototype._render; + + // @2_init中走render BI.Widget.prototype._render = function () { var needPop = false; if (window.Fix && this._store) { needPop = true; + //入栈,可以想见,init中指定了全局的target,而这边会依据此target,将此target压入栈中 pushTarget(this.store); initWatch(this, this.watch); } + //子组件来一遍 _render.apply(this, arguments); + //@3如果当前组件没有指定store,加入数据流,那么他初始化完成的时候不应该去做出栈操作 needPop && popTarget(); }; @@ -42231,6 +42296,7 @@ $.extend(BI, { var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose; var toast = BI.createWidget({ type: "bi.toast", + cls: "bi-message-animate bi-message-leave", level: level, autoClose: autoClose, text: message @@ -42245,13 +42311,14 @@ $.extend(BI, { }] }); toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2}); - toast.element.slideDown(500, function () { - autoClose && BI.delay(function () { - toast.element.slideUp(500, function () { - toast.destroy(); - }); - }, 5000); - }); + toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); + + autoClose && BI.delay(function () { + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + BI.delay(function () { + toast.destroy(); + }, 1000); + }, 5000); }, _show: function (hasCancel, title, message, callback) { $mask = $("
").css({ diff --git a/src/base/foundation/message.js b/src/base/foundation/message.js index 95172132e..82b05e6a0 100644 --- a/src/base/foundation/message.js +++ b/src/base/foundation/message.js @@ -25,6 +25,7 @@ $.extend(BI, { var autoClose = BI.isNull(options.autoClose) ? true : options.autoClose; var toast = BI.createWidget({ type: "bi.toast", + cls: "bi-message-animate bi-message-leave", level: level, autoClose: autoClose, text: message @@ -39,10 +40,13 @@ $.extend(BI, { }] }); toast.element.css({"margin-left": -1 * toast.element.outerWidth() / 2}); - toast.element.show(); + toast.element.removeClass("bi-message-leave").addClass("bi-message-enter"); + autoClose && BI.delay(function () { - toast.element.hide(); - toast.destroy(); + toast.element.removeClass("bi-message-enter").addClass("bi-message-leave"); + BI.delay(function () { + toast.destroy(); + }, 1000); }, 5000); }, _show: function (hasCancel, title, message, callback) { diff --git a/src/css/base/foundation/bi.css b/src/css/base/foundation/bi.css index 173116c05..ed7cdec87 100644 --- a/src/css/base/foundation/bi.css +++ b/src/css/base/foundation/bi.css @@ -17,3 +17,16 @@ .bi-message-close { font-size: 25px; } +.bi-message-animate { + -webkit-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -moz-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + -o-transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; + transition: opacity 0.3s, transform 0.4s, -webkit-transform 0.4s; +} +.bi-message-enter { + opacity: 1; +} +.bi-message-leave { + opacity: 0; + transform: translateY(-100%); +} diff --git a/src/less/base/foundation/bi.message.less b/src/less/base/foundation/bi.message.less index fe8993067..53692cbe1 100644 --- a/src/less/base/foundation/bi.message.less +++ b/src/less/base/foundation/bi.message.less @@ -16,4 +16,18 @@ .bi-message-close { font-size: 25px; +} + +.bi-message-animate { + @val: opacity .3s, transform .4s, -webkit-transform .4s; + .transition(@val); +} + +.bi-message-enter { + opacity: 1; +} + +.bi-message-leave { + opacity: 0; + transform: translateY(-100%); } \ No newline at end of file