From 9588a6fae8b026dfb3f79b5d7971cb378c4c59e5 Mon Sep 17 00:00:00 2001 From: windy <1374721899@qq.com> Date: Thu, 16 Jan 2020 10:18:12 +0800 Subject: [PATCH] =?UTF-8?q?KERNEL-2905=20refactor:=20title=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E6=8C=82=E8=BD=BD=E5=88=B0body=E4=B8=8EnextTick?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dist/base.js | 3 +- dist/fix/fix.ie.js | 75 ++++++++++++++++++++++--------------- dist/fix/fix.js | 79 ++++++++++++++++++++++++--------------- src/base/single/single.js | 3 +- src/core/base.js | 48 +++++++++++++----------- 5 files changed, 124 insertions(+), 84 deletions(-) diff --git a/dist/base.js b/dist/base.js index 1c9a24b09..61e791521 100644 --- a/dist/base.js +++ b/dist/base.js @@ -348,7 +348,8 @@ BI.Single = BI.inherit(BI.Widget, { warningTitle: null, tipType: null, // success或warning value: null, - belowMouse: false // title是否跟随鼠标 + belowMouse: false, // title是否跟随鼠标 + container: "body" }); }, diff --git a/dist/fix/fix.ie.js b/dist/fix/fix.ie.js index 8ff72d857..058c1e930 100644 --- a/dist/fix/fix.ie.js +++ b/dist/fix/fix.ie.js @@ -45,7 +45,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons args[_key] = arguments[_key]; } - return originalMethods.splice.apply(this, args); + return originalMethods["splice"].apply(this, args); }; function noop(a, b, c) {} @@ -137,7 +137,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } else { result = model; } - return result; } @@ -147,7 +146,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons if (Array.isArray(obj)) { var result = [].concat(obj); if (obj.__ref__ !== undefined) result.__ref__ = obj.__ref__; - return result; } @@ -168,37 +166,55 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } } - // An asynchronous deferring mechanism. - // In pre 2.4, we used to use microtasks (Promise/MutationObserver) - // but microtasks actually has too high a priority and fires in between - // supposedly sequential events (e.g. #4521, #6690) or even between - // bubbling of the same event (#6566). Technically setImmediate should be - // the ideal choice, but it's not available everywhere; and the only polyfill - // that consistently queues the callback after all DOM events triggered in the - // same loop is by using MessageChannel. - /* istanbul ignore if */ - if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + // Here we have async deferring wrappers using microtasks. + // In 2.5 we used (macro) tasks (in combination with microtasks). + // However, it has subtle problems when state is changed right before repaint + // (e.g. #6813, out-in transitions). + // Also, using (macro) tasks in event handler would cause some weird behaviors + // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109). + // So we now use microtasks everywhere, again. + // A major drawback of this tradeoff is that there are some scenarios + // where microtasks have too high a priority and fire in between supposedly + // sequential events (e.g. #4521, #6690, which have workarounds) + // or even between bubbling of the same event (#6566). + + // The nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore next, $flow-disable-line */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); timerFunc = function timerFunc() { - setImmediate(nextTickHandler); + p.then(nextTickHandler); }; - } else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || - // PhantomJS - MessageChannel.toString() === '[object MessageChannelConstructor]')) { - var channel = new MessageChannel(); - var port = channel.port2; - channel.port1.onmessage = nextTickHandler; + } else if (!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]')) { + // Use MutationObserver where native Promise is not available, + // e.g. PhantomJS, iOS7, Android 4.4 + // (#6466 MutationObserver is unreliable in IE11) + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); timerFunc = function timerFunc() { - port.postMessage(1); + counter = (counter + 1) % 2; + textNode.data = String(counter); }; - /* istanbul ignore next */ - } else if (typeof Promise !== 'undefined' && isNative(Promise)) { - // use microtask in non-DOM environments, e.g. Weex - var p = Promise.resolve(); + } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + // Fallback to setImmediate. + // Technically it leverages the (macro) task queue, + // but it is still a better choice than setTimeout. timerFunc = function timerFunc() { - p.then(nextTickHandler); + setImmediate(nextTickHandler); }; } else { - // fallback to setTimeout + // Fallback to setTimeout. timerFunc = function timerFunc() { setTimeout(nextTickHandler, 0); }; @@ -231,7 +247,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons }(); function inherit(sb, sp, overrides) { - if (typeof sp === 'object') { + if (typeof sp === "object") { overrides = sp; sp = sb; sb = function temp() { @@ -246,7 +262,6 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons _$1.extend(sb.prototype, overrides, { superclass: sp }); - return sb; } @@ -916,7 +931,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons }); if (contextListeners.length !== 0 || asyncListeners.length !== 0) { nextTick(function () { - _$1.each(BI.uniqBy(contextListeners.reverse(), 'id').reverse(), function (listener) { + _$1.each(BI.uniqBy(contextListeners.reverse(), "id").reverse(), function (listener) { listener.cb(); }); _$1.each(asyncListeners, function (listener) { diff --git a/dist/fix/fix.js b/dist/fix/fix.js index 29a24673d..1a468c9ea 100644 --- a/dist/fix/fix.js +++ b/dist/fix/fix.js @@ -120,42 +120,59 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons } } - // An asynchronous deferring mechanism. - // In pre 2.4, we used to use microtasks (Promise/MutationObserver) - // but microtasks actually has too high a priority and fires in between - // supposedly sequential events (e.g. #4521, #6690) or even between - // bubbling of the same event (#6566). Technically setImmediate should be - // the ideal choice, but it's not available everywhere; and the only polyfill - // that consistently queues the callback after all DOM events triggered in the - // same loop is by using MessageChannel. - /* istanbul ignore if */ - if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + // Here we have async deferring wrappers using microtasks. + // In 2.5 we used (macro) tasks (in combination with microtasks). + // However, it has subtle problems when state is changed right before repaint + // (e.g. #6813, out-in transitions). + // Also, using (macro) tasks in event handler would cause some weird behaviors + // that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109). + // So we now use microtasks everywhere, again. + // A major drawback of this tradeoff is that there are some scenarios + // where microtasks have too high a priority and fire in between supposedly + // sequential events (e.g. #4521, #6690, which have workarounds) + // or even between bubbling of the same event (#6566). + + // The nextTick behavior leverages the microtask queue, which can be accessed + // via either native Promise.then or MutationObserver. + // MutationObserver has wider support, however it is seriously bugged in + // UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It + // completely stops working after triggering a few times... so, if native + // Promise is available, we will use it: + /* istanbul ignore next, $flow-disable-line */ + if (typeof Promise !== 'undefined' && isNative(Promise)) { + var p = Promise.resolve(); + timerFunc = function timerFunc() { + p.then(nextTickHandler); + }; + } else if (!isIE && typeof MutationObserver !== 'undefined' && (isNative(MutationObserver) || + // PhantomJS and iOS 7.x + MutationObserver.toString() === '[object MutationObserverConstructor]')) { + // Use MutationObserver where native Promise is not available, + // e.g. PhantomJS, iOS7, Android 4.4 + // (#6466 MutationObserver is unreliable in IE11) + var counter = 1; + var observer = new MutationObserver(nextTickHandler); + var textNode = document.createTextNode(String(counter)); + observer.observe(textNode, { + characterData: true + }); + timerFunc = function timerFunc() { + counter = (counter + 1) % 2; + textNode.data = String(counter); + }; + } else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) { + // Fallback to setImmediate. + // Technically it leverages the (macro) task queue, + // but it is still a better choice than setTimeout. timerFunc = function timerFunc() { setImmediate(nextTickHandler); }; - } else if (typeof MessageChannel !== 'undefined' && (isNative(MessageChannel) || - // PhantomJS - MessageChannel.toString() === '[object MessageChannelConstructor]')) { - var channel = new MessageChannel(); - var port = channel.port2; - channel.port1.onmessage = nextTickHandler; + } else { + // Fallback to setTimeout. timerFunc = function timerFunc() { - port.postMessage(1); + setTimeout(nextTickHandler, 0); }; - } 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); - }; - } + } return function queueNextTick(cb, ctx) { var _resolve = void 0; diff --git a/src/base/single/single.js b/src/base/single/single.js index c178bb0b9..c161ed65d 100644 --- a/src/base/single/single.js +++ b/src/base/single/single.js @@ -19,7 +19,8 @@ BI.Single = BI.inherit(BI.Widget, { warningTitle: null, tipType: null, // success或warning value: null, - belowMouse: false // title是否跟随鼠标 + belowMouse: false, // title是否跟随鼠标 + container: "body" }); }, diff --git a/src/core/base.js b/src/core/base.js index 1a663e765..21565d454 100644 --- a/src/core/base.js +++ b/src/core/base.js @@ -674,12 +674,12 @@ if (!_global.BI) { nextTick: (function () { var callbacks = []; var pending = false; - var timerFunc; + var timerFunc = void 0; - function nextTickHandler () { + function nextTickHandler() { pending = false; var copies = callbacks.slice(0); - callbacks = []; + callbacks.length = 0; for (var i = 0; i < copies.length; i++) { copies[i](); } @@ -687,45 +687,51 @@ if (!_global.BI) { if (typeof Promise !== "undefined") { var p = Promise.resolve(); - timerFunc = function () { + timerFunc = function timerFunc() { p.then(nextTickHandler); }; - } else - - /* istanbul ignore if */ - if (typeof MutationObserver !== "undefined") { + } else if (!BI.isIE() && typeof MutationObserver !== "undefined") { var counter = 1; var observer = new MutationObserver(nextTickHandler); - var textNode = document.createTextNode(counter + ""); + var textNode = document.createTextNode(String(counter)); observer.observe(textNode, { characterData: true }); - timerFunc = function () { + timerFunc = function timerFunc() { counter = (counter + 1) % 2; - textNode.data = counter + ""; + textNode.data = String(counter); + }; + } else if (typeof setImmediate !== "undefined") { + timerFunc = function timerFunc() { + setImmediate(nextTickHandler); }; } else { - timerFunc = function () { + // Fallback to setTimeout. + timerFunc = function timerFunc() { setTimeout(nextTickHandler, 0); }; } - return function queueNextTick (cb) { - var _resolve; - var args = [].slice.call(arguments, 1); + + return function queueNextTick(cb, ctx) { + var _resolve = void 0; callbacks.push(function () { if (cb) { - cb.apply(null, args); - } - if (_resolve) { - _resolve.apply(null, args); + try { + cb.call(ctx); + } catch (e) { + console.error(e); + } + } else if (_resolve) { + _resolve(ctx); } }); if (!pending) { pending = true; timerFunc(); } - if (!cb && typeof Promise !== "undefined") { - return new Promise(function (resolve) { + // $flow-disable-line + if (!cb && typeof Promise !== 'undefined') { + return new Promise(function (resolve, reject) { _resolve = resolve; }); }