ReactANU.js 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574
  1. /**
  2. * by 司徒正美 Copyright 2017-10-23
  3. * IE9+
  4. */
  5. (function (global, factory) {
  6. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  7. typeof define === 'function' && define.amd ? define(factory) :
  8. (global.React = factory());
  9. }(this, (function () {
  10. var innerHTML = "dangerouslySetInnerHTML";
  11. var emptyArray = [];
  12. var emptyObject = {};
  13. function deprecatedWarn(methodName) {
  14. if (!deprecatedWarn[methodName]) {
  15. //eslint-disable-next-line
  16. console.error(methodName + " is deprecated");
  17. deprecatedWarn[methodName] = 1;
  18. }
  19. }
  20. /**
  21. * 复制一个对象的属性到另一个对象
  22. *
  23. * @param {any} obj
  24. * @param {any} props
  25. * @returns
  26. */
  27. function extend(obj, props) {
  28. for (var i in props) {
  29. if (props.hasOwnProperty(i)) {
  30. obj[i] = props[i];
  31. }
  32. }
  33. return obj;
  34. }
  35. var __type = Object.prototype.toString;
  36. /**
  37. * 一个空函数
  38. *
  39. * @export
  40. */
  41. function noop() {}
  42. /**
  43. * 类继承
  44. *
  45. * @export
  46. * @param {any} SubClass
  47. * @param {any} SupClass
  48. */
  49. function inherit(SubClass, SupClass) {
  50. function Bridge() {}
  51. Bridge.prototype = SupClass.prototype;
  52. var fn = SubClass.prototype = new Bridge();
  53. // 避免原型链拉长导致方法查找的性能开销
  54. extend(fn, SupClass.prototype);
  55. fn.constructor = SubClass;
  56. return fn;
  57. }
  58. var lowerCache = {};
  59. /**
  60. * 小写化的优化
  61. *
  62. * @export
  63. * @param {any} s
  64. * @returns
  65. */
  66. function toLowerCase(s) {
  67. return lowerCache[s] || (lowerCache[s] = s.toLowerCase());
  68. }
  69. function clearArray(a) {
  70. return a.splice(0, a.length);
  71. }
  72. /**
  73. *
  74. *
  75. * @param {any} obj
  76. * @returns
  77. */
  78. function isFn(obj) {
  79. return __type.call(obj) === "[object Function]";
  80. }
  81. var rword = /[^, ]+/g;
  82. function oneObject(array, val) {
  83. if (array + "" === array) {
  84. //利用字符串的特征进行优化,字符串加上一个空字符串等于自身
  85. array = array.match(rword) || [];
  86. }
  87. var result = {},
  88. //eslint-disable-next-line
  89. value = val !== void 666 ? val : 1;
  90. for (var i = 0, n = array.length; i < n; i++) {
  91. result[array[i]] = value;
  92. }
  93. return result;
  94. }
  95. function getChildContext(instance, parentContext) {
  96. if (instance.getChildContext) {
  97. var context = instance.getChildContext();
  98. if (context) {
  99. parentContext = Object.assign({}, parentContext, context);
  100. }
  101. }
  102. return parentContext;
  103. }
  104. function getContextByTypes(curContext, contextTypes) {
  105. var context = {};
  106. if (!contextTypes || !curContext) {
  107. return context;
  108. }
  109. for (var key in contextTypes) {
  110. if (contextTypes.hasOwnProperty(key)) {
  111. context[key] = curContext[key];
  112. }
  113. }
  114. return context;
  115. }
  116. var rcamelize = /[-_][^-_]/g;
  117. function camelize(target) {
  118. //提前判断,提高getStyle等的效率
  119. if (!target || target.indexOf("-") < 0 && target.indexOf("_") < 0) {
  120. return target;
  121. }
  122. //转换为驼峰风格
  123. var str = target.replace(rcamelize, function (match) {
  124. return match.charAt(1).toUpperCase();
  125. });
  126. return firstLetterLower(str);
  127. }
  128. function firstLetterLower(str) {
  129. return str.charAt(0).toLowerCase() + str.slice(1);
  130. }
  131. var options = {
  132. dirtyComponents: [],
  133. queue: [],
  134. beforeUnmount: noop,
  135. beforeRender: noop,
  136. beforePatch: noop,
  137. afterRender: noop,
  138. afterPatch: noop,
  139. afterMount: noop,
  140. afterUpdate: noop
  141. };
  142. var numberMap = {
  143. //null undefined IE6-8这里会返回[object Object]
  144. "[object Boolean]": 2,
  145. "[object Number]": 3,
  146. "[object String]": 4,
  147. "[object Function]": 5,
  148. "[object Symbol]": 6,
  149. "[object Array]": 7
  150. };
  151. // undefined: 0, null: 1, boolean:2, number: 3, string: 4, function: 5, symbol:6, array: 7, object:8
  152. function typeNumber(data) {
  153. if (data === null) {
  154. return 1;
  155. }
  156. if (data === void 666) {
  157. return 0;
  158. }
  159. var a = numberMap[__type.call(data)];
  160. return a || 8;
  161. }
  162. var recyclables = {
  163. "#text": []
  164. };
  165. //fix 0.14对此方法的改动,之前refs里面保存的是虚拟DOM
  166. function getDOMNode() {
  167. return this;
  168. }
  169. var pendingRefs = [];
  170. window.pendingRefs = pendingRefs;
  171. var Refs = {
  172. currentOwner: null,
  173. clearElementRefs: function clearElementRefs() {
  174. var callback = this.fireRef;
  175. var refs = pendingRefs.splice(0, pendingRefs.length);
  176. for (var i = 0, n = refs.length; i < n; i += 2) {
  177. var vnode = refs[i];
  178. var data = refs[i + 1];
  179. callback(vnode, data);
  180. }
  181. },
  182. detachRef: function detachRef(lastVnode, nextVnode, dom) {
  183. if (lastVnode.ref === nextVnode.ref) {
  184. return;
  185. }
  186. if (lastVnode._hasRef) {
  187. this.fireRef(lastVnode, null);
  188. }
  189. if (nextVnode._hasRef && dom) {
  190. pendingRefs.push(nextVnode, dom);
  191. }
  192. },
  193. fireRef: function fireRef(vnode, dom) {
  194. var ref = vnode.ref;
  195. if (typeof ref === "function") {
  196. return ref(dom);
  197. }
  198. var owner = vnode._owner;
  199. if (!owner) {
  200. throw "ref位置错误";
  201. }
  202. if (dom) {
  203. if (dom.nodeType) {
  204. dom.getDOMNode = getDOMNode;
  205. }
  206. owner.refs[ref] = dom;
  207. } else {
  208. delete owner.refs[ref];
  209. }
  210. }
  211. };
  212. /**
  213. * 创建虚拟DOM
  214. *
  215. * @param {string} type
  216. * @param {object} props
  217. * @param {array} ...children
  218. * @returns
  219. */
  220. function createElement(type, config) {
  221. for (var _len = arguments.length, children = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
  222. children[_key - 2] = arguments[_key];
  223. }
  224. var props = {},
  225. checkProps = 0,
  226. vtype = 1,
  227. key = null,
  228. ref = null,
  229. argsLen = children.length;
  230. if (type && type.call) {
  231. vtype = type.prototype && type.prototype.render ? 2 : 4;
  232. } else if (type + "" !== type) {
  233. console.error("createElement第一个参数类型错误"); // eslint-disable-line
  234. }
  235. if (config != null) {
  236. for (var i in config) {
  237. var val = config[i];
  238. if (i === "key") {
  239. if (val !== void 0) {
  240. key = val + "";
  241. }
  242. } else if (i === "ref") {
  243. if (val !== void 0) {
  244. ref = val;
  245. }
  246. } else if (i === "children") {
  247. props[i] = val;
  248. } else {
  249. checkProps = 1;
  250. props[i] = val;
  251. }
  252. }
  253. }
  254. if (argsLen === 1) {
  255. props.children = children[0];
  256. // : EMPTY_CHILDREN;
  257. } else if (argsLen > 1) {
  258. props.children = children;
  259. }
  260. var defaultProps = type.defaultProps;
  261. if (defaultProps) {
  262. for (var propName in defaultProps) {
  263. if (props[propName] === void 666) {
  264. checkProps = 1;
  265. props[propName] = defaultProps[propName];
  266. }
  267. }
  268. }
  269. return new Vnode(type, key, ref, props, vtype, checkProps);
  270. }
  271. function Vnode(type, key, ref, props, vtype, checkProps) {
  272. this.type = type;
  273. this.props = props;
  274. this.vtype = vtype;
  275. this._owner = Refs.currentOwner;
  276. if (key) {
  277. this.key = key;
  278. }
  279. if (vtype === 1) {
  280. this.checkProps = checkProps;
  281. }
  282. var refType = typeNumber(ref);
  283. if (refType === 3 || refType === 4 || refType === 5) {
  284. //number, string, function
  285. this._hasRef = true;
  286. this.ref = ref;
  287. }
  288. /*
  289. this._hostNode = null
  290. this._instance = null
  291. */
  292. }
  293. Vnode.prototype = {
  294. getDOMNode: function getDOMNode() {
  295. return this._hostNode || null;
  296. },
  297. $$typeof: 1
  298. };
  299. function flattenChildren(vnode) {
  300. var arr = emptyArray,
  301. c = vnode.props.children;
  302. if (c !== null) {
  303. arr = _flattenChildren(c, true);
  304. if (arr.length === 0) {
  305. arr = emptyArray;
  306. }
  307. }
  308. return vnode.vchildren = arr;
  309. }
  310. function _flattenChildren(original, convert) {
  311. var children = [],
  312. unidimensionalIndex = 0,
  313. lastText = void 0,
  314. child = void 0,
  315. isMap = convert === "",
  316. iteractorFn = void 0,
  317. temp = Array.isArray(original) ? original.slice(0) : [original];
  318. while (temp.length) {
  319. if ((child = temp.shift()) && (child.shift || (iteractorFn = getIteractor(child)))) {
  320. //比较巧妙地判定是否为子数组
  321. if (iteractorFn) {
  322. //兼容Immutable.js, Map, Set
  323. child = callIteractor(iteractorFn, child);
  324. iteractorFn = false;
  325. temp.unshift.apply(temp, child);
  326. continue;
  327. }
  328. if (isMap) {
  329. if (!child._prefix) {
  330. child._prefix = "." + unidimensionalIndex;
  331. unidimensionalIndex++; //维护第一层元素的索引值
  332. }
  333. for (var i = 0; i < child.length; i++) {
  334. if (child[i]) {
  335. child[i]._prefix = child._prefix + ":" + i;
  336. }
  337. }
  338. }
  339. temp.unshift.apply(temp, child);
  340. } else {
  341. var childType = typeNumber(child);
  342. if (childType < 3) {
  343. // 0, 1, 2
  344. if (convert) {
  345. continue;
  346. } else {
  347. child = null;
  348. }
  349. } else if (childType < 6) {
  350. if (lastText && convert) {
  351. //false模式下不进行合并与转换
  352. lastText.text += child;
  353. continue;
  354. }
  355. if (convert) {
  356. child = {
  357. type: "#text",
  358. text: child + "",
  359. vtype: 0
  360. };
  361. unidimensionalIndex++;
  362. }
  363. lastText = child;
  364. } else {
  365. if (isMap && !child._prefix) {
  366. child._prefix = "." + unidimensionalIndex;
  367. unidimensionalIndex++;
  368. }
  369. if (!child.type) {
  370. throw Error("这不是一个虚拟DOM");
  371. }
  372. lastText = false;
  373. }
  374. children.push(child);
  375. }
  376. }
  377. return children;
  378. }
  379. var REAL_SYMBOL = typeof Symbol === "function" && Symbol.iterator;
  380. var FAKE_SYMBOL = "@@iterator";
  381. function getIteractor(a) {
  382. if (typeNumber(a) > 7) {
  383. var iteratorFn = REAL_SYMBOL && a[REAL_SYMBOL] || a[FAKE_SYMBOL];
  384. if (iteratorFn && iteratorFn.call) {
  385. return iteratorFn;
  386. }
  387. }
  388. }
  389. function callIteractor(iteratorFn, children) {
  390. var iterator = iteratorFn.call(children),
  391. step,
  392. ret = [];
  393. if (iteratorFn !== children.entries) {
  394. while (!(step = iterator.next()).done) {
  395. ret.push(step.value);
  396. }
  397. } else {
  398. //Map, Set
  399. while (!(step = iterator.next()).done) {
  400. var entry = step.value;
  401. if (entry) {
  402. ret.push(entry[1]);
  403. }
  404. }
  405. }
  406. return ret;
  407. }
  408. function cloneElement(vnode, props) {
  409. if (!vnode.vtype) {
  410. return extend({}, vnode);
  411. }
  412. var owner = vnode._owner,
  413. lastOwn = Refs.currentOwner,
  414. old = vnode.props,
  415. configs = {};
  416. if (props) {
  417. Object.assign(configs, old, props);
  418. configs.key = props.key !== void 666 ? props.key : vnode.key;
  419. if (props.ref !== void 666) {
  420. configs.ref = props.ref;
  421. owner = lastOwn;
  422. } else if (vnode._hasRef) {
  423. configs.ref = vnode.ref;
  424. }
  425. } else {
  426. configs = old;
  427. }
  428. Refs.currentOwner = owner;
  429. var args = [].slice.call(arguments, 0),
  430. argsLength = args.length;
  431. args[0] = vnode.type;
  432. args[1] = configs;
  433. if (argsLength === 2 && configs.children) {
  434. args.push(configs.children);
  435. }
  436. var ret = createElement.apply(null, args);
  437. Refs.currentOwner = lastOwn;
  438. return ret;
  439. }
  440. var Children = {
  441. only: function only(children) {
  442. //only方法接受的参数只能是一个对象,不能是多个对象(数组)。
  443. if (children && children.vtype) {
  444. return children;
  445. }
  446. throw new Error("expect only one child");
  447. },
  448. count: function count(children) {
  449. if (children == null) {
  450. return 0;
  451. }
  452. return _flattenChildren(children, false).length;
  453. },
  454. map: function map(children, callback, context) {
  455. if (children == null) {
  456. return children;
  457. }
  458. var ret = [];
  459. _flattenChildren(children, "").forEach(function (old, index) {
  460. var el = callback.call(context, old, index);
  461. if (el === null) {
  462. return;
  463. }
  464. if (el.vtype) {
  465. //如果返回的el等于old,还需要使用原来的key, _prefix
  466. var key = computeKey(old, el, index);
  467. ret.push(cloneElement(el, { key: key }));
  468. } else if (el.type) {
  469. ret.push(extend({}, el));
  470. } else {
  471. ret.push(el);
  472. }
  473. });
  474. return ret;
  475. },
  476. forEach: function forEach(children, callback, context) {
  477. if (children != null) {
  478. _flattenChildren(children, false).forEach(callback, context);
  479. }
  480. },
  481. toArray: function toArray(children) {
  482. if (children == null) {
  483. return [];
  484. }
  485. return Children.map(children, function (el) {
  486. return el;
  487. });
  488. }
  489. };
  490. var rthimNumer = /\d+\$/;
  491. function computeKey(old, el, index) {
  492. var curKey = el && el.key != null ? escapeKey(el.key) : null;
  493. var oldKey = old && old.key != null ? escapeKey(old.key) : null;
  494. var oldFix = old && old._prefix,
  495. key = void 0;
  496. if (oldKey && curKey) {
  497. key = oldFix + "$" + oldKey;
  498. if (oldKey !== curKey) {
  499. key = curKey + "/" + key;
  500. }
  501. } else {
  502. key = curKey || oldKey;
  503. if (key) {
  504. if (oldFix) {
  505. key = oldFix + "$" + key;
  506. }
  507. } else {
  508. key = oldFix || "." + index;
  509. }
  510. }
  511. return key.replace(rthimNumer, "$");
  512. }
  513. function escapeKey(key) {
  514. return String(key).replace(/[=:]/g, escaperFn);
  515. }
  516. var escaperLookup = {
  517. "=": "=0",
  518. ":": "=2"
  519. };
  520. function escaperFn(match) {
  521. return escaperLookup[match];
  522. }
  523. //用于后端的元素节点
  524. function DOMElement(type) {
  525. this.nodeName = type;
  526. this.style = {};
  527. this.children = [];
  528. }
  529. var NAMESPACE = {
  530. svg: "http://www.w3.org/2000/svg",
  531. xmlns: "http://www.w3.org/2000/xmlns/",
  532. xlink: "http://www.w3.org/1999/xlink",
  533. math: "http://www.w3.org/1998/Math/MathML",
  534. xhtml: "http://www.w3.org/1999/xhtml",
  535. html: "https://www.w3.org/TR/html4/"
  536. };
  537. var fn = DOMElement.prototype = {
  538. contains: Boolean
  539. };
  540. String("replaceChild,appendChild,removeAttributeNS,setAttributeNS,removeAttribute,setAttribute" + ",getAttribute,insertBefore,removeChild,addEventListener,removeEventListener,attachEvent" + ",detachEvent").replace(/\w+/g, function (name) {
  541. fn[name] = function () {
  542. console.log("fire " + name); // eslint-disable-line
  543. };
  544. });
  545. //用于后端的document
  546. var fakeDoc = new DOMElement();
  547. fakeDoc.createElement = fakeDoc.createElementNS = fakeDoc.createDocumentFragment = function (type) {
  548. return new DOMElement(type);
  549. };
  550. fakeDoc.createTextNode = fakeDoc.createComment = Boolean;
  551. fakeDoc.documentElement = new DOMElement("html");
  552. fakeDoc.nodeName = "#document";
  553. fakeDoc.textContent = "";
  554. try {
  555. var w = window;
  556. var b = !!w.alert;
  557. } catch (e) {
  558. b = false;
  559. w = {
  560. document: fakeDoc
  561. };
  562. }
  563. var win = w;
  564. var document = w.document || fakeDoc;
  565. var isStandard = "textContent" in document;
  566. var fragment = document.createDocumentFragment();
  567. function emptyElement(node) {
  568. var child;
  569. while (child = node.firstChild) {
  570. emptyElement(child);
  571. node.removeChild(child);
  572. }
  573. }
  574. function removeElement(node) {
  575. if (node.nodeType === 1) {
  576. if (isStandard) {
  577. node.textContent = "";
  578. } else {
  579. emptyElement(node);
  580. }
  581. node.__events = null;
  582. } else if (node.nodeType === 3) {
  583. //只回收文本节点
  584. if (recyclables["#text"].length < 100) {
  585. recyclables["#text"].push(node);
  586. }
  587. }
  588. fragment.appendChild(node);
  589. fragment.removeChild(node);
  590. }
  591. var versions = {
  592. 88: 7, //IE7-8 objectobject
  593. 80: 6, //IE6 objectundefined
  594. "00": NaN, // other modern browsers
  595. "08": NaN
  596. };
  597. /* istanbul ignore next */
  598. var msie = document.documentMode || versions[typeNumber(document.all) + "" + typeNumber(XMLHttpRequest)];
  599. var modern = /NaN|undefined/.test(msie) || msie > 8;
  600. function insertElement(container, target, insertPoint) {
  601. if (insertPoint) {
  602. container.insertBefore(target, insertPoint);
  603. } else {
  604. container.appendChild(target);
  605. }
  606. }
  607. function createElement$1(vnode, vparent) {
  608. var type = vnode.type;
  609. if (type === "#text") {
  610. //只重复利用文本节点
  611. var node = recyclables[type].pop();
  612. if (node) {
  613. node.nodeValue = vnode.text;
  614. return node;
  615. }
  616. return document.createTextNode(vnode.text);
  617. }
  618. if (type === "#comment") {
  619. return document.createComment(vnode.text);
  620. }
  621. var check = vparent || vnode;
  622. var ns = check.namespaceURI;
  623. if (type === "svg") {
  624. ns = NAMESPACE.svg;
  625. } else if (type === "math") {
  626. ns = NAMESPACE.math;
  627. } else if (check.type.toLowerCase() === "foreignobject" || !ns || ns === NAMESPACE.html || ns === NAMESPACE.xhtml) {
  628. return document.createElement(type);
  629. }
  630. try {
  631. vnode.namespaceURI = ns;
  632. return document.createElementNS(ns, type);
  633. //eslint-disable-next-line
  634. } catch (e) {
  635. return document.createElement(type);
  636. }
  637. }
  638. var globalEvents = {};
  639. var eventPropHooks = {}; //用于在事件回调里对事件对象进行
  640. var eventHooks = {}; //用于在元素上绑定特定的事件
  641. //根据onXXX得到其全小写的事件名, onClick --> click, onClickCapture --> click,
  642. // onMouseMove --> mousemove
  643. var eventLowerCache = {
  644. onClick: "click",
  645. onChange: "change",
  646. onWheel: "wheel"
  647. };
  648. /**
  649. * 判定否为与事件相关
  650. *
  651. * @param {any} name
  652. * @returns
  653. */
  654. function isEventName(name) {
  655. return (/^on[A-Z]/.test(name)
  656. );
  657. }
  658. var isTouch = "ontouchstart" in document;
  659. function dispatchEvent(e, type, end) {
  660. //__type__ 在injectTapEventPlugin里用到
  661. e = new SyntheticEvent(e);
  662. if (type) {
  663. e.type = type;
  664. }
  665. var bubble = e.type;
  666. var hook = eventPropHooks[bubble];
  667. if (hook && false === hook(e)) {
  668. return;
  669. }
  670. var paths = collectPaths(e.target, end || document);
  671. var captured = bubble + "capture";
  672. options.async = true;
  673. if (options.async) {
  674. var cur = options.queue;
  675. if (cur !== options.dirtyComponents) {
  676. options.queue = options.dirtyComponents;
  677. options.queue.last = cur;
  678. }
  679. }
  680. triggerEventFlow(paths, captured, e);
  681. if (!e._stopPropagation) {
  682. triggerEventFlow(paths.reverse(), bubble, e);
  683. }
  684. options.async = false;
  685. options.flushUpdaters();
  686. }
  687. function collectPaths(from, end) {
  688. var paths = [];
  689. do {
  690. if (from === end) {
  691. break;
  692. }
  693. var events = from.__events;
  694. if (events) {
  695. paths.push({ dom: from, events: events });
  696. }
  697. } while ((from = from.parentNode) && from.nodeType === 1);
  698. // target --> parentNode --> body --> html
  699. return paths;
  700. }
  701. function triggerEventFlow(paths, prop, e) {
  702. for (var i = paths.length; i--;) {
  703. var path = paths[i];
  704. var fn = path.events[prop];
  705. if (isFn(fn)) {
  706. e.currentTarget = path.dom;
  707. fn.call(path.dom, e);
  708. if (e._stopPropagation) {
  709. break;
  710. }
  711. }
  712. }
  713. }
  714. function addGlobalEvent(name) {
  715. if (!globalEvents[name]) {
  716. globalEvents[name] = true;
  717. addEvent(document, name, dispatchEvent);
  718. }
  719. }
  720. function addEvent(el, type, fn, bool) {
  721. if (el.addEventListener) {
  722. el.addEventListener(type, fn, bool || false);
  723. } else if (el.attachEvent) {
  724. el.attachEvent("on" + type, fn);
  725. }
  726. }
  727. var rcapture = /Capture$/;
  728. function getBrowserName(onStr) {
  729. var lower = eventLowerCache[onStr];
  730. if (lower) {
  731. return lower;
  732. }
  733. var camel = onStr.slice(2).replace(rcapture, "");
  734. lower = camel.toLowerCase();
  735. eventLowerCache[onStr] = lower;
  736. return lower;
  737. }
  738. eventPropHooks.click = function (e) {
  739. return !e.target.disabled;
  740. };
  741. /* IE6-11 chrome mousewheel wheelDetla 下 -120 上 120
  742. firefox DOMMouseScroll detail 下3 上-3
  743. firefox wheel detlaY 下3 上-3
  744. IE9-11 wheel deltaY 下40 上-40
  745. chrome wheel deltaY 下100 上-100 */
  746. /* istanbul ignore next */
  747. var fixWheelType = "onmousewheel" in document ? "mousewheel" : document.onwheel !== void 666 ? "wheel" : "DOMMouseScroll";
  748. var fixWheelDelta = fixWheelType === "mousewheel" ? "wheelDetla" : fixWheelType === "wheel" ? "deltaY" : "detail";
  749. eventHooks.wheel = function (dom) {
  750. addEvent(dom, fixWheelType, function (e) {
  751. var delta = e[fixWheelDelta] > 0 ? -120 : 120;
  752. var deltaY = ~~dom.__wheel + delta;
  753. dom.__wheel = deltaY;
  754. e = new SyntheticEvent(e);
  755. e.type = "wheel";
  756. e.deltaY = deltaY;
  757. dispatchEvent(e);
  758. });
  759. };
  760. var fixFocus = {};
  761. "blur,focus".replace(/\w+/g, function (type) {
  762. eventHooks[type] = function () {
  763. if (!fixFocus[type]) {
  764. fixFocus[type] = true;
  765. addEvent(document, type, dispatchEvent, true);
  766. }
  767. };
  768. });
  769. /**
  770. *
  771. DOM通过event对象的relatedTarget属性提供了相关元素的信息。这个属性只对于mouseover和mouseout事件才包含值;
  772. 对于其他事件,这个属性的值是null。IE不支持realtedTarget属性,但提供了保存着同样信息的不同属性。
  773. 在mouseover事件触发时,IE的fromElement属性中保存了相关元素;
  774. 在mouseout事件出发时,IE的toElement属性中保存着相关元素。
  775. 但fromElement与toElement可能同时都有值
  776. */
  777. function getRelatedTarget(e) {
  778. if (!e.timeStamp) {
  779. e.relatedTarget = e.type === "mouseover" ? e.fromElement : e.toElement;
  780. }
  781. return e.relatedTarget;
  782. }
  783. function contains(a, b) {
  784. if (b) {
  785. while (b = b.parentNode) {
  786. if (b === a) {
  787. return true;
  788. }
  789. }
  790. }
  791. return false;
  792. }
  793. String("mouseenter,mouseleave").replace(/\w+/g, function (type) {
  794. eventHooks[type] = function (dom, name) {
  795. var mark = "__" + name;
  796. if (!dom[mark]) {
  797. dom[mark] = true;
  798. var mask = name === "mouseenter" ? "mouseover" : "mouseout";
  799. addEvent(dom, mask, function (e) {
  800. var t = getRelatedTarget(e);
  801. if (!t || t !== dom && !contains(dom, t)) {
  802. var common = getLowestCommonAncestor(dom, t);
  803. //由于不冒泡,因此paths长度为1
  804. dispatchEvent(e, name, common);
  805. }
  806. });
  807. }
  808. };
  809. });
  810. function getLowestCommonAncestor(instA, instB) {
  811. var depthA = 0;
  812. for (var tempA = instA; tempA; tempA = tempA.parentNode) {
  813. depthA++;
  814. }
  815. var depthB = 0;
  816. for (var tempB = instB; tempB; tempB = tempB.parentNode) {
  817. depthB++;
  818. }
  819. // If A is deeper, crawl up.
  820. while (depthA - depthB > 0) {
  821. instA = instA.parentNode;
  822. depthA--;
  823. }
  824. // If B is deeper, crawl up.
  825. while (depthB - depthA > 0) {
  826. instB = instB.parentNode;
  827. depthB--;
  828. }
  829. // Walk in lockstep until we find a match.
  830. var depth = depthA;
  831. while (depth--) {
  832. if (instA === instB) {
  833. return instA;
  834. }
  835. instA = instA.parentNode;
  836. instB = instB.parentNode;
  837. }
  838. return null;
  839. }
  840. if (isTouch) {
  841. eventHooks.click = noop;
  842. eventHooks.clickcapture = noop;
  843. }
  844. function createHandle(name, fn) {
  845. return function (e) {
  846. if (fn && fn(e) === false) {
  847. return;
  848. }
  849. dispatchEvent(e, name);
  850. };
  851. }
  852. var changeHandle = createHandle("change");
  853. var doubleClickHandle = createHandle("doubleclick");
  854. //react将text,textarea,password元素中的onChange事件当成onInput事件
  855. eventHooks.changecapture = eventHooks.change = function (dom) {
  856. if (/text|password/.test(dom.type)) {
  857. addEvent(document, "input", changeHandle);
  858. }
  859. };
  860. eventHooks.doubleclick = eventHooks.doubleclickcapture = function () {
  861. addEvent(document, "dblclick", doubleClickHandle);
  862. };
  863. function SyntheticEvent(event) {
  864. if (event.nativeEvent) {
  865. return event;
  866. }
  867. for (var i in event) {
  868. if (!eventProto[i]) {
  869. this[i] = event[i];
  870. }
  871. }
  872. if (!this.target) {
  873. this.target = event.srcElement;
  874. }
  875. this.fixEvent();
  876. this.timeStamp = new Date() - 0;
  877. this.nativeEvent = event;
  878. }
  879. var eventProto = SyntheticEvent.prototype = {
  880. fixEvent: function fixEvent() {}, //留给以后扩展用
  881. preventDefault: function preventDefault() {
  882. var e = this.nativeEvent || {};
  883. e.returnValue = this.returnValue = false;
  884. if (e.preventDefault) {
  885. e.preventDefault();
  886. }
  887. },
  888. fixHooks: function fixHooks() {},
  889. stopPropagation: function stopPropagation() {
  890. var e = this.nativeEvent || {};
  891. e.cancelBubble = this._stopPropagation = true;
  892. if (e.stopPropagation) {
  893. e.stopPropagation();
  894. }
  895. },
  896. persist: noop,
  897. stopImmediatePropagation: function stopImmediatePropagation() {
  898. this.stopPropagation();
  899. this.stopImmediate = true;
  900. },
  901. toString: function toString() {
  902. return "[object Event]";
  903. }
  904. };
  905. /* istanbul ignore next */
  906. var eventSystem = extend({
  907. eventPropHooks: eventPropHooks,
  908. eventHooks: eventHooks,
  909. eventLowerCache: eventLowerCache,
  910. isEventName: isEventName,
  911. isTouch: isTouch,
  912. dispatchEvent: dispatchEvent,
  913. addGlobalEvent: addGlobalEvent,
  914. addEvent: addEvent,
  915. getBrowserName: getBrowserName,
  916. createHandle: createHandle,
  917. SyntheticEvent: SyntheticEvent
  918. });
  919. //为了兼容yo
  920. var check = function check() {
  921. return check;
  922. };
  923. check.isRequired = check;
  924. var PropTypes = {
  925. array: check,
  926. bool: check,
  927. func: check,
  928. number: check,
  929. object: check,
  930. string: check,
  931. any: check,
  932. arrayOf: check,
  933. element: check,
  934. instanceOf: check,
  935. node: check,
  936. objectOf: check,
  937. oneOf: check,
  938. oneOfType: check,
  939. shape: check
  940. };
  941. /**
  942. *组件的基类
  943. *
  944. * @param {any} props
  945. * @param {any} context
  946. */
  947. function Component(props, context) {
  948. //防止用户在构造器生成JSX
  949. Refs.currentOwner = this;
  950. this.context = context;
  951. this.props = props;
  952. this.refs = {};
  953. this.state = null;
  954. }
  955. Component.prototype = {
  956. constructor: Component, //必须重写constructor,防止别人在子类中使用Object.getPrototypeOf时找不到正确的基类
  957. replaceState: function replaceState() {
  958. deprecatedWarn("replaceState");
  959. },
  960. setState: function setState(state, cb) {
  961. debounceSetState(this.updater, state, cb);
  962. },
  963. isMounted: function isMounted() {
  964. deprecatedWarn("isMounted");
  965. return !!(this.updater || emptyObject)._hostNode;
  966. },
  967. forceUpdate: function forceUpdate(cb) {
  968. debounceSetState(this.updater, true, cb);
  969. },
  970. render: function render() {}
  971. };
  972. function debounceSetState(updater, state, cb) {
  973. if (!updater) {
  974. return;
  975. }
  976. if (updater._didUpdate) {
  977. //如果用户在componentDidUpdate中使用setState,要防止其卡死
  978. setTimeout(function () {
  979. updater._didUpdate = false;
  980. setStateImpl(updater, state, cb);
  981. }, 300);
  982. return;
  983. }
  984. setStateImpl(updater, state, cb);
  985. }
  986. function setStateImpl(updater, state, cb) {
  987. if (isFn(cb)) {
  988. updater._pendingCallbacks.push(cb);
  989. }
  990. if (state === true) {
  991. //forceUpdate
  992. updater._forceUpdate = true;
  993. } else {
  994. //setState
  995. updater._pendingStates.push(state);
  996. }
  997. if (updater._lifeStage == 0) {
  998. //组件挂载期
  999. //componentWillUpdate中的setState/forceUpdate应该被忽略
  1000. if (updater._hydrating) {
  1001. //在render方法中调用setState也会被延迟到下一周期更新.这存在两种情况,
  1002. //1. 组件直接调用自己的setState
  1003. //2. 子组件调用父组件的setState,
  1004. updater._renderInNextCycle = true;
  1005. }
  1006. } else {
  1007. //组件更新期
  1008. if (updater._receiving) {
  1009. //componentWillReceiveProps中的setState/forceUpdate应该被忽略
  1010. return;
  1011. }
  1012. updater._renderInNextCycle = true;
  1013. if (options.async) {
  1014. //在事件句柄中执行setState会进行合并
  1015. options.enqueueUpdater(updater);
  1016. return;
  1017. }
  1018. if (updater._hydrating) {
  1019. // 在componentDidMount里调用自己的setState,延迟到下一周期更新
  1020. // 在更新过程中, 子组件在componentWillReceiveProps里调用父组件的setState,延迟到下一周期更新
  1021. return;
  1022. }
  1023. // 不在生命周期钩子内执行setState
  1024. var last = options.queue;
  1025. var cur = options.queue = [updater];
  1026. cur.last = last;
  1027. options.flushUpdaters(cur);
  1028. options.queue = cur.last || [];
  1029. }
  1030. }
  1031. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  1032. /**
  1033. * 为了兼容0.13之前的版本
  1034. */
  1035. var NOBIND = {
  1036. render: 1,
  1037. shouldComponentUpdate: 1,
  1038. componentWillReceiveProps: 1,
  1039. componentWillUpdate: 1,
  1040. componentDidUpdate: 1,
  1041. componentWillMount: 1,
  1042. componentDidMount: 1,
  1043. componentWillUnmount: 1,
  1044. componentDidUnmount: 1
  1045. };
  1046. function collectMixins(mixins) {
  1047. var keyed = {};
  1048. for (var i = 0; i < mixins.length; i++) {
  1049. var mixin = mixins[i];
  1050. if (mixin.mixins) {
  1051. applyMixins(mixin, collectMixins(mixin.mixins));
  1052. }
  1053. for (var key in mixin) {
  1054. if (mixin.hasOwnProperty(key) && key !== "mixins") {
  1055. (keyed[key] || (keyed[key] = [])).push(mixin[key]);
  1056. }
  1057. }
  1058. }
  1059. return keyed;
  1060. }
  1061. var MANY_MERGED = {
  1062. getInitialState: 1,
  1063. getDefaultProps: 1,
  1064. getChildContext: 1
  1065. };
  1066. function flattenHooks(key, hooks) {
  1067. var hookType = _typeof(hooks[0]);
  1068. if (hookType === "object") {
  1069. // Merge objects
  1070. hooks.unshift({});
  1071. return Object.assign.apply(null, hooks);
  1072. } else if (hookType === "function" && hooks.length > 1) {
  1073. return function () {
  1074. var ret = {},
  1075. r = void 0,
  1076. hasReturn = MANY_MERGED[key];
  1077. for (var i = 0; i < hooks.length; i++) {
  1078. r = hooks[i].apply(this, arguments);
  1079. if (hasReturn && r) {
  1080. Object.assign(ret, r);
  1081. }
  1082. }
  1083. if (hasReturn) {
  1084. return ret;
  1085. }
  1086. return r;
  1087. };
  1088. } else {
  1089. return hooks[0];
  1090. }
  1091. }
  1092. function applyMixins(proto, mixins) {
  1093. for (var key in mixins) {
  1094. if (mixins.hasOwnProperty(key)) {
  1095. proto[key] = flattenHooks(key, mixins[key].concat(proto[key] || []));
  1096. }
  1097. }
  1098. }
  1099. //创建一个构造器
  1100. function newCtor(className, spec) {
  1101. var curry = Function("ReactComponent", "blacklist", "spec", "return function " + className + "(props, context) {\n ReactComponent.call(this, props, context);\n\n for (var methodName in this) {\n var method = this[methodName];\n if (typeof method === \"function\"&& !blacklist[methodName]) {\n this[methodName] = method.bind(this);\n }\n }\n\n if (spec.getInitialState) {\n var test = this.state = spec.getInitialState.call(this);\n if(!(test === null || ({}).toString.call(test) == \"[object Object]\")){\n throw \"getInitialState(): must return an object or null\"\n }\n }\n\n };");
  1102. return curry(Component, NOBIND, spec);
  1103. }
  1104. function createClass(spec) {
  1105. deprecatedWarn("createClass");
  1106. if (!isFn(spec.render)) {
  1107. throw "请实现render方法";
  1108. }
  1109. var Constructor = newCtor(spec.displayName || "Component", spec);
  1110. var proto = inherit(Constructor, Component);
  1111. //如果mixins里面非常复杂,可能mixin还包含其他mixin
  1112. if (spec.mixins) {
  1113. applyMixins(spec, collectMixins(spec.mixins));
  1114. }
  1115. extend(proto, spec);
  1116. if (spec.statics) {
  1117. extend(Constructor, spec.statics);
  1118. }
  1119. "propTypes,contextTypes,childContextTypes,displayName".replace(/\w+/g, function (name) {
  1120. if (spec[name]) {
  1121. var props = Constructor[name] = spec[name];
  1122. if (name !== "displayName") {
  1123. for (var i in props) {
  1124. if (!isFn(props[i])) {
  1125. console.error(i + " in " + name + " must be a function"); // eslint-disable-line
  1126. }
  1127. }
  1128. }
  1129. }
  1130. });
  1131. if (isFn(spec.getDefaultProps)) {
  1132. Constructor.defaultProps = spec.getDefaultProps();
  1133. }
  1134. return Constructor;
  1135. }
  1136. var hasOwnProperty = Object.prototype.hasOwnProperty;
  1137. function shallowEqual(objA, objB) {
  1138. if (Object.is(objA, objB)) {
  1139. return true;
  1140. }
  1141. //确保objA, objB都是对象
  1142. if (typeNumber(objA) < 7 || typeNumber(objB) < 7) {
  1143. return false;
  1144. }
  1145. var keysA = Object.keys(objA);
  1146. var keysB = Object.keys(objB);
  1147. if (keysA.length !== keysB.length) {
  1148. return false;
  1149. }
  1150. // Test for A's keys different from B.
  1151. for (var i = 0; i < keysA.length; i++) {
  1152. if (!hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) {
  1153. return false;
  1154. }
  1155. }
  1156. return true;
  1157. }
  1158. function PureComponent(props, context) {
  1159. Component.call(this, props, context);
  1160. }
  1161. var fn$1 = inherit(PureComponent, Component);
  1162. fn$1.shouldComponentUpdate = function shallowCompare(nextProps, nextState) {
  1163. var a = shallowEqual(this.props, nextProps);
  1164. var b = shallowEqual(this.state, nextState);
  1165. return !a || !b;
  1166. };
  1167. fn$1.isPureComponent = true;
  1168. var rnumber = /^-?\d+(\.\d+)?$/;
  1169. /**
  1170. * 为元素样子设置样式
  1171. *
  1172. * @export
  1173. * @param {any} dom
  1174. * @param {any} lastStyle
  1175. * @param {any} nextStyle
  1176. */
  1177. function patchStyle(dom, lastStyle, nextStyle) {
  1178. if (lastStyle === nextStyle) {
  1179. return;
  1180. }
  1181. for (var name in nextStyle) {
  1182. var val = nextStyle[name];
  1183. if (lastStyle[name] !== val) {
  1184. name = cssName(name, dom);
  1185. if (val !== 0 && !val) {
  1186. val = ""; //清除样式
  1187. } else if (rnumber.test(val) && !cssNumber[name]) {
  1188. val = val + "px"; //添加单位
  1189. }
  1190. try {
  1191. //node.style.width = NaN;node.style.width = 'xxxxxxx';
  1192. //node.style.width = undefine 在旧式IE下会抛异常
  1193. dom.style[name] = val; //应用样式
  1194. } catch (e) {
  1195. console.log("dom.style[" + name + "] = " + val + "throw error"); // eslint-disable-line
  1196. }
  1197. }
  1198. }
  1199. // 如果旧样式存在,但新样式已经去掉
  1200. for (var _name in lastStyle) {
  1201. if (!(_name in nextStyle)) {
  1202. _name = cssName(_name, dom);
  1203. dom.style[_name] = ""; //清除样式
  1204. }
  1205. }
  1206. }
  1207. var cssNumber = oneObject("animationIterationCount,columnCount,order,flex,flexGrow,flexShrink,fillOpacity,fontWeight,lineHeight,opacity,orphans,widows,zIndex,zoom");
  1208. //var testStyle = document.documentElement.style
  1209. var prefixes = ["", "-webkit-", "-o-", "-moz-", "-ms-"];
  1210. var cssMap = oneObject("float", "cssFloat");
  1211. /**
  1212. * 转换成当前浏览器可用的样式名
  1213. *
  1214. * @param {any} name
  1215. * @returns
  1216. */
  1217. function cssName(name, dom) {
  1218. if (cssMap[name]) {
  1219. return cssMap[name];
  1220. }
  1221. var host = dom && dom.style || {};
  1222. for (var i = 0, n = prefixes.length; i < n; i++) {
  1223. var camelCase = camelize(prefixes[i] + name);
  1224. if (camelCase in host) {
  1225. return cssMap[name] = camelCase;
  1226. }
  1227. }
  1228. return null;
  1229. }
  1230. function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
  1231. //布尔属性的值末必为true,false
  1232. //https://github.com/facebook/react/issues/10589
  1233. var controlled = {
  1234. value: 1,
  1235. defaultValue: 1
  1236. };
  1237. var isSpecialAttr = {
  1238. style: 1,
  1239. children: 1,
  1240. innerHTML: 1,
  1241. dangerouslySetInnerHTML: 1
  1242. };
  1243. var svgCache = {};
  1244. var strategyCache = {};
  1245. /**
  1246. * 仅匹配 svg 属性名中的第一个驼峰处,如 viewBox 中的 wB,
  1247. * 数字表示该特征在属性列表中重复的次数
  1248. * -1 表示用 ":" 隔开的属性 (xlink:href, xlink:title 等)
  1249. * https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
  1250. */
  1251. var svgCamelCase = {
  1252. w: { r: 1, b: 1, t: 1 },
  1253. e: { n: 1, t: 1, f: 1, p: 1, c: 1, m: 1, a: 2, u: 1, s: 1, v: 1 },
  1254. o: { r: 1 },
  1255. c: { m: 1 },
  1256. p: { p: 1 },
  1257. t: { s: 2, t: 1, u: 1, c: 1, d: 1, o: 1, x: 1, y: 1, l: 1 },
  1258. l: { r: 1, m: 1, u: 1, b: -1, l: -1, s: -1 },
  1259. r: { r: 1, u: 2, h: 1, w: 1, c: 1, e: 1 },
  1260. h: { r: 1, a: 1, l: 1, t: 1 },
  1261. y: { p: 1, s: 1, t: 1, c: 1 },
  1262. g: { c: 1 },
  1263. k: { a: -1, h: -1, r: -1, s: -1, t: -1, c: 1, u: 1 },
  1264. m: { o: 1, l: 1, a: 1 },
  1265. n: { c: 1, t: 1, u: 1 },
  1266. s: { a: 3 },
  1267. f: { x: 1, y: 1 },
  1268. d: { e: 1, f: 1, m: 1, d: 1 },
  1269. x: { c: 1 }
  1270. };
  1271. // SVG 属性列表中驼峰命名和短横线分隔命名特征值有重复
  1272. // 列出了重复特征中的短横线命名的属性名
  1273. var specialSVGPropertyName = {
  1274. "overline-thickness": 2,
  1275. "underline-thickness": 2,
  1276. "overline-position": 2,
  1277. "underline-position": 2,
  1278. "stroke-miterlimit": 2,
  1279. "baseline-shift": 2,
  1280. "clip-path": 2,
  1281. "font-size": 2,
  1282. "font-size-adjust": 2,
  1283. "font-stretch": 2,
  1284. "font-style": 2,
  1285. "text-decoration": 2,
  1286. "vert-origin-x": 2,
  1287. "vert-origin-y": 2,
  1288. "paint-order": 2,
  1289. "fill-rule": 2,
  1290. "color-rendering": 2,
  1291. "marker-end": 2,
  1292. "pointer-events": 2,
  1293. "units-per-em": 2,
  1294. "strikethrough-thickness": 2,
  1295. "lighting-color": 2
  1296. };
  1297. // 重复属性名的特征值列表
  1298. var repeatedKey = ["et", "ep", "em", "es", "pp", "ts", "td", "to", "lr", "rr", "re", "ht", "gc"];
  1299. function createRepaceFn(split) {
  1300. return function (match) {
  1301. return match.slice(0, 1) + split + match.slice(1).toLowerCase();
  1302. };
  1303. }
  1304. var rhump = /[a-z][A-Z]/;
  1305. var toHyphen = createRepaceFn("-");
  1306. var toColon = createRepaceFn(":");
  1307. function getSVGAttributeName(name) {
  1308. if (svgCache[name]) {
  1309. return svgCache[name];
  1310. }
  1311. var key = name.match(rhump);
  1312. if (!key) {
  1313. return svgCache[name] = name;
  1314. }
  1315. var _ref = [].concat(_toConsumableArray(key[0].toLowerCase())),
  1316. prefix = _ref[0],
  1317. postfix = _ref[1];
  1318. var orig = name;
  1319. if (svgCamelCase[prefix] && svgCamelCase[prefix][postfix]) {
  1320. var count = svgCamelCase[prefix][postfix];
  1321. if (count === -1) {
  1322. return svgCache[orig] = {
  1323. name: name.replace(rhump, toColon),
  1324. ifSpecial: true
  1325. };
  1326. }
  1327. if (~repeatedKey.indexOf(prefix + postfix)) {
  1328. var dashName = name.replace(rhump, toHyphen);
  1329. if (specialSVGPropertyName[dashName]) {
  1330. name = dashName;
  1331. }
  1332. }
  1333. } else {
  1334. name = name.replace(rhump, toHyphen);
  1335. }
  1336. return svgCache[orig] = name;
  1337. }
  1338. function diffProps(dom, lastProps, nextProps, vnode) {
  1339. var isSVG = vnode.namespaceURI === NAMESPACE.svg;
  1340. var tag = vnode.type;
  1341. //eslint-disable-next-line
  1342. for (var name in nextProps) {
  1343. var val = nextProps[name];
  1344. if (val !== lastProps[name]) {
  1345. var which = tag + isSVG + name;
  1346. var action = strategyCache[which];
  1347. if (!action) {
  1348. action = strategyCache[which] = getPropAction(dom, name, isSVG);
  1349. }
  1350. actionStrategy[action](dom, name, val, lastProps);
  1351. }
  1352. }
  1353. //如果旧属性在新属性对象不存在,那么移除DOM eslint-disable-next-line
  1354. for (var _name in lastProps) {
  1355. if (!nextProps.hasOwnProperty(_name)) {
  1356. var _which = tag + isSVG + _name;
  1357. var _action = strategyCache[_which];
  1358. actionStrategy[_action](dom, _name, false, lastProps);
  1359. }
  1360. }
  1361. }
  1362. function isBooleanAttr(dom, name) {
  1363. var val = dom[name];
  1364. return val === true || val === false;
  1365. }
  1366. /**
  1367. * 根据一个属性所在的元素或元素的文档类型,就可以永久决定该使用什么策略操作它
  1368. *
  1369. * @param {any} dom 元素节点
  1370. * @param {any} name 属性名
  1371. * @param {any} isSVG
  1372. * @returns
  1373. */
  1374. function getPropAction(dom, name, isSVG) {
  1375. if (isSVG && name === "className") {
  1376. return "svgClass";
  1377. }
  1378. if (isSpecialAttr[name]) {
  1379. return name;
  1380. }
  1381. if (isEventName(name)) {
  1382. return "event";
  1383. }
  1384. if (isSVG) {
  1385. return "svgAttr";
  1386. }
  1387. if (isBooleanAttr(dom, name)) {
  1388. return "booleanAttr";
  1389. }
  1390. return name.indexOf("data-") === 0 || dom[name] === void 666 ? "attribute" : "property";
  1391. }
  1392. var builtinStringProps = {
  1393. className: 1,
  1394. title: 1,
  1395. name: 1,
  1396. alt: 1,
  1397. lang: 1,
  1398. value: 1
  1399. };
  1400. var actionStrategy = {
  1401. innerHTML: noop,
  1402. children: noop,
  1403. style: function style(dom, _, val, lastProps) {
  1404. patchStyle(dom, lastProps.style || emptyObject, val || emptyObject);
  1405. },
  1406. svgClass: function svgClass(dom, name, val) {
  1407. if (!val) {
  1408. dom.removeAttribute("class");
  1409. } else {
  1410. dom.setAttribute("class", val);
  1411. }
  1412. },
  1413. svgAttr: function svgAttr(dom, name, val) {
  1414. // http://www.w3school.com.cn/xlink/xlink_reference.asp
  1415. // https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#notable-enh
  1416. // a ncements xlinkActuate, xlinkArcrole, xlinkHref, xlinkRole, xlinkShow,
  1417. // xlinkTitle, xlinkType eslint-disable-next-line
  1418. var method = typeNumber(val) < 3 && !val ? "removeAttribute" : "setAttribute";
  1419. var nameRes = getSVGAttributeName(name);
  1420. if (nameRes.ifSpecial) {
  1421. var prefix = nameRes.name.split(":")[0];
  1422. // 将xlinkHref 转换为 xlink:href
  1423. dom[method + "NS"](NAMESPACE[prefix], nameRes.name, val || "");
  1424. } else {
  1425. dom[method](nameRes, val || "");
  1426. }
  1427. },
  1428. booleanAttr: function booleanAttr(dom, name, val) {
  1429. // 布尔属性必须使用el.xxx = true|false方式设值 如果为false, IE全系列下相当于setAttribute(xxx,""),
  1430. // 会影响到样式,需要进一步处理 eslint-disable-next-line
  1431. dom[name] = !!val;
  1432. if (dom[name] === false) {
  1433. dom.removeAttribute(name);
  1434. } else if (dom[name] === "false") {
  1435. //字符串属性会将它转换为false
  1436. dom[name] = "";
  1437. }
  1438. },
  1439. attribute: function attribute(dom, name, val) {
  1440. if (val == null || val === false) {
  1441. return dom.removeAttribute(name);
  1442. }
  1443. try {
  1444. dom.setAttribute(name, val);
  1445. } catch (e) {
  1446. console.warn("setAttribute error", name, val); // eslint-disable-line
  1447. }
  1448. },
  1449. property: function property(dom, name, val) {
  1450. if (name !== "value" || dom[name] !== val) {
  1451. // 尝试直接赋值,部分情况下会失败,如给 input 元素的 size 属性赋值 0 或字符串
  1452. // 这时如果用 setAttribute 则会静默失败
  1453. try {
  1454. if (!val && val !== 0) {
  1455. //如果它是字符串属性,并且不等于"",清空
  1456. // if (typeNumber(dom[name]) === 4 && dom[name] !== "") {
  1457. if (builtinStringProps[name]) {
  1458. dom[name] = "";
  1459. }
  1460. // }
  1461. dom.removeAttribute(name);
  1462. } else {
  1463. dom[name] = val;
  1464. }
  1465. } catch (e) {
  1466. dom.setAttribute(name, val);
  1467. }
  1468. if (controlled[name]) {
  1469. dom._lastValue = val;
  1470. }
  1471. }
  1472. },
  1473. event: function event(dom, name, val, lastProps) {
  1474. var events = dom.__events || (dom.__events = {});
  1475. var refName = toLowerCase(name.slice(2));
  1476. if (val === false) {
  1477. delete events[refName];
  1478. } else {
  1479. if (!lastProps[name]) {
  1480. //添加全局监听事件
  1481. var eventName = getBrowserName(name);
  1482. var hook = eventHooks[eventName];
  1483. addGlobalEvent(eventName);
  1484. if (hook) {
  1485. hook(dom, eventName);
  1486. }
  1487. }
  1488. //onClick --> click, onClickCapture --> clickcapture
  1489. events[refName] = val;
  1490. }
  1491. },
  1492. dangerouslySetInnerHTML: function dangerouslySetInnerHTML(dom, name, val, lastProps) {
  1493. var oldhtml = lastProps[name] && lastProps[name].__html;
  1494. var html = val && val.__html;
  1495. if (html !== oldhtml) {
  1496. dom.innerHTML = html;
  1497. }
  1498. }
  1499. };
  1500. function disposeVnode(vnode) {
  1501. if (!vnode || vnode._disposed) {
  1502. return;
  1503. }
  1504. var instance = vnode._instance;
  1505. if (vnode._hasRef) {
  1506. vnode._hasRef = false;
  1507. Refs.fireRef(vnode, null);
  1508. }
  1509. if (instance) {
  1510. disposeComponent(vnode, instance);
  1511. } else if (vnode.vtype === 1) {
  1512. disposeElement(vnode);
  1513. }
  1514. vnode._disposed = true;
  1515. }
  1516. function disposeElement(vnode) {
  1517. var props = vnode.props,
  1518. vchildren = vnode.vchildren;
  1519. if (props[innerHTML]) {
  1520. removeElement(vnode._hostNode);
  1521. } else {
  1522. for (var i = 0, n = vchildren.length; i < n; i++) {
  1523. disposeVnode(vchildren[i]);
  1524. }
  1525. vchildren.length = 0;
  1526. }
  1527. }
  1528. function disposeComponent(vnode, instance) {
  1529. options.beforeUnmount(instance);
  1530. instance.setState = instance.forceUpdate = noop;
  1531. if (instance.componentWillUnmount) {
  1532. instance.componentWillUnmount();
  1533. }
  1534. var updater = instance.updater;
  1535. //在执行componentWillUnmount后才将关联的元素节点解绑,防止用户在钩子里调用 findDOMNode方法
  1536. disposeVnode(updater.rendered);
  1537. updater._renderInNextCycle = vnode._instance = instance.updater = null;
  1538. }
  1539. /**
  1540. input, select, textarea这几个元素如果指定了value/checked的**状态属性**,就会包装成受控组件或非受控组件
  1541. 受控组件是指,用户除了为它指定**状态属性**,还为它指定了onChange/onInput/disabled等用于控制此状态属性
  1542. 变动的属性
  1543. 反之,它就是非受控组件,非受控组件会在框架内部添加一些事件,阻止**状态属性**被用户的行为改变,只能被setState改变
  1544. */
  1545. var duplexData = {
  1546. 1: ["value", {
  1547. onChange: 1,
  1548. onInput: 1,
  1549. readOnly: 1,
  1550. disabled: 1
  1551. }, "oninput", preventUserInput],
  1552. 2: ["checked", {
  1553. onChange: 1,
  1554. onClick: 1,
  1555. readOnly: 1,
  1556. disabled: 1
  1557. }, "onclick", preventUserClick],
  1558. 3: ["value", {
  1559. onChange: 1,
  1560. disabled: 1
  1561. }, "onchange", preventUserChange]
  1562. };
  1563. var duplexMap = {
  1564. color: 1,
  1565. date: 1,
  1566. datetime: 1,
  1567. "datetime-local": 1,
  1568. email: 1,
  1569. month: 1,
  1570. number: 1,
  1571. password: 1,
  1572. range: 1,
  1573. search: 1,
  1574. tel: 1,
  1575. text: 1,
  1576. time: 1,
  1577. url: 1,
  1578. week: 1,
  1579. textarea: 1,
  1580. checkbox: 2,
  1581. radio: 2,
  1582. "select-one": 3,
  1583. "select-multiple": 3
  1584. };
  1585. function processFormElement(vnode, dom, props) {
  1586. var domType = dom.type;
  1587. var duplexType = duplexMap[domType];
  1588. if (duplexType) {
  1589. var data = duplexData[duplexType];
  1590. var duplexProp = data[0];
  1591. var keys = data[1];
  1592. var eventName = data[2];
  1593. if (duplexProp in props && !hasOtherControllProperty(props, keys)) {
  1594. // eslint-disable-next-line
  1595. console.warn("\u4F60\u4E3A" + vnode.type + "[type=" + domType + "]\u5143\u7D20\u6307\u5B9A\u4E86" + duplexProp + "\u5C5E\u6027\uFF0C\n \u4F46\u662F\u6CA1\u6709\u63D0\u4F9B\u53E6\u5916\u7684" + Object.keys(keys) + "\u6765\u63A7\u5236" + duplexProp + "\u5C5E\u6027\u7684\u53D8\u5316\n \u90A3\u4E48\u5B83\u5373\u4E3A\u4E00\u4E2A\u975E\u53D7\u63A7\u7EC4\u4EF6\uFF0C\u7528\u6237\u65E0\u6CD5\u901A\u8FC7\u8F93\u5165\u6539\u53D8\u5143\u7D20\u7684" + duplexProp + "\u503C");
  1596. dom[eventName] = data[3];
  1597. }
  1598. if (duplexType === 3) {
  1599. postUpdateSelectedOptions(vnode, dom);
  1600. }
  1601. } else {
  1602. dom.duplexValue = props.value === undefined ? typeNumber(props.children) > 4 ? dom.text : props.children : props.value;
  1603. }
  1604. }
  1605. function hasOtherControllProperty(props, keys) {
  1606. for (var key in props) {
  1607. if (keys[key]) {
  1608. return true;
  1609. }
  1610. }
  1611. }
  1612. function preventUserInput(e) {
  1613. var target = e.target;
  1614. var name = e.type === "textarea" ? "innerHTML" : "value";
  1615. target[name] = target._lastValue;
  1616. }
  1617. function preventUserClick(e) {
  1618. e.preventDefault();
  1619. }
  1620. function preventUserChange(e) {
  1621. var target = e.target,
  1622. value = target._lastValue,
  1623. options$$1 = target.options;
  1624. if (target.multiple) {
  1625. updateOptionsMore(options$$1, options$$1.length, value);
  1626. } else {
  1627. updateOptionsOne(options$$1, options$$1.length, value);
  1628. }
  1629. }
  1630. function postUpdateSelectedOptions(vnode, target) {
  1631. var props = vnode.props,
  1632. multiple = !!props.multiple;
  1633. target._lastValue = typeNumber(props.value) > 1 ? props.value : typeNumber(props.defaultValue) > 1 ? props.defaultValue : multiple ? [] : "";
  1634. preventUserChange({
  1635. target: target
  1636. });
  1637. }
  1638. function updateOptionsOne(options$$1, n, propValue) {
  1639. var stringValues = {};
  1640. for (var i = 0; i < n; i++) {
  1641. var option = options$$1[i];
  1642. var value = option.duplexValue;
  1643. if (value === propValue) {
  1644. //精确匹配
  1645. return setOptionSelected(option, true);
  1646. }
  1647. stringValues[value] = option;
  1648. }
  1649. var match = stringValues[propValue];
  1650. if (match) {
  1651. //字符串模糊匹配
  1652. return setOptionSelected(match, true);
  1653. }
  1654. if (n) {
  1655. //选中第一个
  1656. setOptionSelected(options$$1[0], true);
  1657. }
  1658. }
  1659. function updateOptionsMore(options$$1, n, propValue) {
  1660. var selectedValue = {};
  1661. try {
  1662. for (var i = 0; i < propValue.length; i++) {
  1663. selectedValue["&" + propValue[i]] = true;
  1664. }
  1665. } catch (e) {
  1666. /* istanbul ignore next */
  1667. console.warn('<select multiple="true"> 的value应该对应一个字符串数组'); // eslint-disable-line
  1668. }
  1669. for (var _i = 0; _i < n; _i++) {
  1670. var option = options$$1[_i];
  1671. var value = option.duplexValue;
  1672. var selected = selectedValue.hasOwnProperty("&" + value);
  1673. setOptionSelected(option, selected);
  1674. }
  1675. }
  1676. function setOptionSelected(dom, selected) {
  1677. dom.selected = selected;
  1678. }
  1679. var mountOrder = 1;
  1680. function alwaysNull() {
  1681. return null;
  1682. }
  1683. function Updater(instance, vnode) {
  1684. vnode._instance = instance;
  1685. instance.updater = this;
  1686. this._mountOrder = mountOrder++;
  1687. this._instance = instance;
  1688. this._pendingCallbacks = [];
  1689. // this._openRef = false;
  1690. this._didHook = noop;
  1691. this._pendingStates = [];
  1692. this._lifeStage = 0; //判断生命周期
  1693. //update总是保存最新的数据,如state, props, context, parentContext, vparent
  1694. this.vnode = vnode;
  1695. // this._hydrating = true 表示组件正在根据虚拟DOM合成真实DOM
  1696. // this._renderInNextCycle = true 表示组件需要在下一周期重新渲染
  1697. // this._forceUpdate = true 表示会无视shouldComponentUpdate的结果
  1698. if (instance.__isStateless) {
  1699. this.mergeStates = alwaysNull;
  1700. }
  1701. }
  1702. var cbMap = {
  1703. 1: "componentDidMount",
  1704. 2: "componentDidUpdate"
  1705. };
  1706. Updater.prototype = {
  1707. mergeStates: function mergeStates() {
  1708. var instance = this._instance,
  1709. pendings = this._pendingStates,
  1710. state = instance.state,
  1711. n = pendings.length;
  1712. if (n === 0) {
  1713. return state;
  1714. }
  1715. var nextState = extend({}, state); //每次都返回新的state
  1716. for (var i = 0; i < n; i++) {
  1717. var pending = pendings[i];
  1718. if (pending && pending.call) {
  1719. pending = pending.call(instance, nextState, this.props);
  1720. }
  1721. extend(nextState, pending);
  1722. }
  1723. pendings.length = 0;
  1724. return nextState;
  1725. },
  1726. _ref: function _ref() {
  1727. var vnode = this.vnode;
  1728. if (vnode.ref && this._openRef) {
  1729. var inst = this._instance;
  1730. Refs.fireRef(vnode, inst.__isStateless ? null : inst);
  1731. this._openRef = false;
  1732. }
  1733. },
  1734. componentDidCallback: function componentDidCallback() {
  1735. if (this._lifeStage > 0) {
  1736. var instance = this._instance;
  1737. var userHook = instance[cbMap[this._lifeStage]];
  1738. this._lifeStage = -1;
  1739. userHook && userHook.apply(instance, this.oldDatas);
  1740. this.oldDatas = emptyArray;
  1741. if (this._lifeStage == 1) {
  1742. options.afterMount(instance);
  1743. } else {
  1744. options.afterUpdate(instance);
  1745. }
  1746. this._hydrating = false; // 见setStateImpl
  1747. }
  1748. },
  1749. renderComponent: function renderComponent(cb) {
  1750. var vnode = this.vnode,
  1751. parentContext = this.parentContext,
  1752. instance = this._instance;
  1753. //调整全局的 CurrentOwner.cur
  1754. var lastOwn = Refs.currentOwner,
  1755. rendered = void 0;
  1756. Refs.currentOwner = instance;
  1757. try {
  1758. if (this.willReceive === false) {
  1759. rendered = this.rendered;
  1760. delete this.willReceive;
  1761. } else {
  1762. rendered = instance.render();
  1763. }
  1764. } finally {
  1765. Refs.currentOwner = lastOwn;
  1766. }
  1767. //组件只能返回组件或null
  1768. if (rendered === null || rendered === false) {
  1769. rendered = { type: "#comment", text: "empty", vtype: 0 };
  1770. } else if (!rendered || !rendered.type) {
  1771. //true, undefined, array, {}
  1772. throw new Error("@" + vnode.type.name + "#render:You may have returned undefined, an array or some other invalid object");
  1773. }
  1774. var childContext = rendered.vtype ? getChildContext(instance, parentContext) : parentContext;
  1775. var dom = cb(rendered, this.vparent, childContext);
  1776. if (rendered._hostNode) {
  1777. this.rendered = rendered;
  1778. }
  1779. if (!dom) {
  1780. throw ["必须返回节点", rendered];
  1781. }
  1782. var u = this;
  1783. do {
  1784. u.vnode._hostNode = u._hostNode = dom;
  1785. } while (u = u.parentUpdater);
  1786. return dom;
  1787. }
  1788. };
  1789. function instantiateComponent(type, vnode, props, context) {
  1790. var isStateless = vnode.vtype === 4;
  1791. var instance = isStateless ? {
  1792. refs: {},
  1793. render: function render() {
  1794. return type(this.props, this.context);
  1795. }
  1796. } : new type(props, context);
  1797. var updater = new Updater(instance, vnode, props, context);
  1798. //props, context是不可变的
  1799. instance.props = updater.props = props;
  1800. instance.context = updater.context = context;
  1801. instance.constructor = type;
  1802. updater.displayName = type.displayName || type.name;
  1803. if (isStateless) {
  1804. var lastOwn = Refs.currentOwner;
  1805. Refs.currentOwner = instance;
  1806. try {
  1807. var mixin = instance.render();
  1808. } finally {
  1809. Refs.currentOwner = lastOwn;
  1810. }
  1811. if (mixin && mixin.render) {
  1812. //支持module pattern component
  1813. extend(instance, mixin);
  1814. } else {
  1815. instance.__isStateless = true;
  1816. updater.rendered = mixin;
  1817. updater.willReceive = false;
  1818. }
  1819. }
  1820. return instance;
  1821. }
  1822. function drainQueue(queue) {
  1823. options.beforePatch();
  1824. //先执行所有元素虚拟DOMrefs方法(从上到下)
  1825. Refs.clearElementRefs();
  1826. var needSort = [],
  1827. unique = {},
  1828. updater = void 0;
  1829. while (updater = queue.shift()) {
  1830. //queue可能中途加入新元素, 因此不能直接使用queue.forEach(fn)
  1831. if (updater._disposed) {
  1832. continue;
  1833. }
  1834. if (!unique[updater._mountOrder]) {
  1835. unique[updater._mountOrder] = 1;
  1836. needSort.push(updater);
  1837. }
  1838. Refs.clearElementRefs();
  1839. updater._didUpdate = updater._lifeStage === 2;
  1840. updater.componentDidCallback(); //执行所有mount/update钩子(从下到上)
  1841. // updater._lifeStage = 1;
  1842. // updater._hydrating = false;
  1843. if (!updater._renderInNextCycle) {
  1844. updater._didUpdate = false;
  1845. }
  1846. updater._ref(); //执行组件虚拟DOM的ref
  1847. //如果组件在componentDidMount中调用setState
  1848. if (updater._renderInNextCycle) {
  1849. options.patchComponent(updater);
  1850. }
  1851. }
  1852. //再执行所有setState/forceUpdate回调,根据从下到上的顺序执行
  1853. needSort.sort(mountSorter).forEach(function (updater) {
  1854. clearArray(updater._pendingCallbacks).forEach(function (fn) {
  1855. fn.call(updater._instance);
  1856. });
  1857. });
  1858. options.afterPatch();
  1859. }
  1860. var dirtyComponents = options.dirtyComponents;
  1861. function mountSorter(u1, u2) {
  1862. //按文档顺序执行
  1863. return u1._mountOrder - u2._mountOrder;
  1864. }
  1865. options.flushUpdaters = function (queue) {
  1866. if (!queue) {
  1867. var last = dirtyComponents.last;
  1868. if (!last) {
  1869. return;
  1870. }
  1871. queue = clearArray(dirtyComponents);
  1872. dirtyComponents.last = null;
  1873. if (queue.length) {
  1874. options.queue = queue;
  1875. queue.last = last;
  1876. queue.sort(mountSorter);
  1877. } else {
  1878. options.queue = last;
  1879. }
  1880. }
  1881. drainQueue(queue);
  1882. };
  1883. options.enqueueUpdater = function (updater) {
  1884. if (dirtyComponents.indexOf(updater) == -1) {
  1885. dirtyComponents.push(updater);
  1886. }
  1887. };
  1888. //[Top API] React.isValidElement
  1889. function isValidElement(vnode) {
  1890. return vnode && vnode.vtype;
  1891. }
  1892. //[Top API] ReactDOM.render
  1893. function render(vnode, container, callback) {
  1894. return renderByAnu(vnode, container, callback);
  1895. }
  1896. //[Top API] ReactDOM.unstable_renderSubtreeIntoContainer
  1897. function unstable_renderSubtreeIntoContainer(lastVnode, nextVnode, container, callback) {
  1898. deprecatedWarn("unstable_renderSubtreeIntoContainer");
  1899. var parentContext = lastVnode && lastVnode.context || {};
  1900. return renderByAnu(nextVnode, container, callback, parentContext);
  1901. }
  1902. //[Top API] ReactDOM.unmountComponentAtNode
  1903. function unmountComponentAtNode(container) {
  1904. var lastVnode = container.__component;
  1905. if (lastVnode) {
  1906. disposeVnode(lastVnode);
  1907. emptyElement(container);
  1908. container.__component = null;
  1909. }
  1910. }
  1911. //[Top API] ReactDOM.findDOMNode
  1912. function findDOMNode(ref) {
  1913. if (ref == null) {
  1914. return null;
  1915. }
  1916. if (ref.nodeType === 1) {
  1917. return ref;
  1918. }
  1919. return ref.updater ? ref.updater._hostNode : ref._hostNode || null;
  1920. }
  1921. //[Top API] ReactDOM.createPortal
  1922. function createPortal(vchildren, container) {
  1923. var parentVnode = getVParent(container);
  1924. parentVnode.vchildren = container.vchildren || emptyArray;
  1925. diffChildren(getVParent(container), vchildren, container, {});
  1926. parentVnode.vchildren = vchildren;
  1927. return null;
  1928. }
  1929. // 用于辅助XML元素的生成(svg, math),
  1930. // 它们需要根据父节点的tagName与namespaceURI,知道自己是存在什么文档中
  1931. function getVParent(container) {
  1932. return {
  1933. type: container.nodeName,
  1934. namespaceURI: container.namespaceURI
  1935. };
  1936. }
  1937. // ReactDOM.render的内部实现
  1938. function renderByAnu(vnode, container, callback) {
  1939. var context = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  1940. if (!isValidElement(vnode)) {
  1941. throw "ReactDOM.render\u7684\u7B2C\u4E00\u4E2A\u53C2\u6570\u9519\u8BEF"; // eslint-disable-line
  1942. }
  1943. if (!(container && container.getElementsByTagName)) {
  1944. throw "ReactDOM.render\u7684\u7B2C\u4E8C\u4E2A\u53C2\u6570\u9519\u8BEF"; // eslint-disable-line
  1945. }
  1946. var rootNode = void 0,
  1947. lastVnode = container.__component;
  1948. if (lastVnode) {
  1949. rootNode = alignVnode(lastVnode, vnode, getVParent(container), context);
  1950. } else {
  1951. //如果是后端渲染生成,它的孩子中存在一个拥有data-reactroot属性的元素节点
  1952. rootNode = genVnodes(container, vnode, context);
  1953. }
  1954. if (rootNode.setAttribute) {
  1955. rootNode.setAttribute("data-reactroot", "");
  1956. }
  1957. var instance = vnode._instance;
  1958. container.__component = vnode;
  1959. drainQueue(options.queue);
  1960. // drainQueue(updateQueue);
  1961. Refs.currentOwner = null; //防止干扰
  1962. var ret = instance || rootNode;
  1963. if (callback) {
  1964. callback.call(ret); //坑
  1965. }
  1966. //组件返回组件实例,而普通虚拟DOM 返回元素节点
  1967. return ret;
  1968. }
  1969. var toArray = Array.from || function (a) {
  1970. var ret = [];
  1971. for (var i = 0, n = a.length; i < n; i++) {
  1972. ret[i] = a[i];
  1973. }
  1974. return ret;
  1975. };
  1976. function genVnodes(container, vnode, context) {
  1977. var nodes = toArray(container.childNodes || emptyArray);
  1978. var lastNode = null;
  1979. for (var i = 0, el; el = nodes[i++];) {
  1980. if (el.getAttribute && el.getAttribute("data-reactroot") !== null) {
  1981. lastNode = el;
  1982. } else {
  1983. container.removeChild(el);
  1984. }
  1985. }
  1986. return container.appendChild(mountVnode(lastNode, vnode, getVParent(container), context));
  1987. }
  1988. var patchStrategy = {
  1989. 0: mountText,
  1990. 1: mountElement,
  1991. 2: mountComponent,
  1992. 4: mountComponent,
  1993. 10: updateText,
  1994. 11: updateElement,
  1995. 12: updateComponent,
  1996. 14: updateComponent
  1997. };
  1998. //mountVnode只是转换虚拟DOM为真实DOM,不做插入DOM树操作
  1999. function mountVnode(lastNode, vnode) {
  2000. return patchStrategy[vnode.vtype].apply(null, arguments);
  2001. }
  2002. function updateVnode(lastVnode) {
  2003. return patchStrategy[lastVnode.vtype + 10].apply(null, arguments);
  2004. }
  2005. function mountText(lastNode, vnode) {
  2006. if (!lastNode || lastNode.nodeName !== vnode.type) {
  2007. lastNode = createElement$1(vnode);
  2008. }
  2009. return vnode._hostNode = lastNode;
  2010. }
  2011. function updateText(lastVnode, nextVnode) {
  2012. var dom = lastVnode._hostNode;
  2013. nextVnode._hostNode = dom;
  2014. if (lastVnode.text !== nextVnode.text) {
  2015. dom.nodeValue = nextVnode.text;
  2016. }
  2017. return dom;
  2018. }
  2019. function genMountElement(lastNode, vnode, vparent, type) {
  2020. if (lastNode && toLowerCase(lastNode.nodeName) === type) {
  2021. return lastNode;
  2022. } else {
  2023. var dom = createElement$1(vnode, vparent);
  2024. if (lastNode) {
  2025. while (lastNode.firstChild) {
  2026. dom.appendChild(lastNode.firstChild);
  2027. }
  2028. }
  2029. return dom;
  2030. }
  2031. }
  2032. var formElements = {
  2033. select: 1,
  2034. textarea: 1,
  2035. input: 1,
  2036. option: 1
  2037. };
  2038. function mountElement(lastNode, vnode, vparent, context) {
  2039. var type = vnode.type,
  2040. props = vnode.props,
  2041. _hasRef = vnode._hasRef;
  2042. var dom = genMountElement(lastNode, vnode, vparent, type);
  2043. vnode._hostNode = dom;
  2044. var children = flattenChildren(vnode);
  2045. var method = lastNode ? alignChildren : mountChildren;
  2046. method(dom, children, vnode, context);
  2047. // dom.vchildren = children;/** fatal 不再访问真实DOM */
  2048. if (vnode.checkProps) {
  2049. diffProps(dom, emptyObject, props, vnode);
  2050. }
  2051. if (formElements[type]) {
  2052. processFormElement(vnode, dom, props);
  2053. }
  2054. if (_hasRef) {
  2055. pendingRefs.push(vnode, dom);
  2056. }
  2057. return dom;
  2058. }
  2059. function updateElement(lastVnode, nextVnode, vparent, context) {
  2060. var lastProps = lastVnode.props,
  2061. dom = lastVnode._hostNode,
  2062. checkProps = lastVnode.checkProps,
  2063. type = lastVnode.type;
  2064. var nextProps = nextVnode.props,
  2065. nextCheckProps = nextVnode.checkProps;
  2066. nextVnode._hostNode = dom;
  2067. var vchildren = lastVnode.vchildren || emptyArray,
  2068. newChildren = void 0;
  2069. if (nextProps[innerHTML]) {
  2070. vchildren.forEach(function (el) {
  2071. disposeVnode(el);
  2072. });
  2073. vchildren.length = 0;
  2074. } else {
  2075. if (nextVnode === lastVnode) {
  2076. //如果新旧节点一样,为了防止旧vchildren被重写,需要restore一下
  2077. newChildren = vchildren.concat();
  2078. } else {
  2079. newChildren = flattenChildren(nextVnode);
  2080. }
  2081. if (lastProps[innerHTML]) {
  2082. vchildren.length = 0;
  2083. }
  2084. diffChildren(lastVnode, newChildren, dom, context);
  2085. nextVnode.vchildren = newChildren;
  2086. }
  2087. if (checkProps || nextCheckProps) {
  2088. diffProps(dom, lastProps, nextProps, nextVnode);
  2089. }
  2090. if (formElements[type]) {
  2091. processFormElement(nextVnode, dom, nextProps);
  2092. }
  2093. Refs.detachRef(lastVnode, nextVnode, dom);
  2094. return dom;
  2095. }
  2096. //将虚拟DOM转换为真实DOM并插入父元素
  2097. function mountChildren(parentNode, children, vparent, context) {
  2098. for (var i = 0, n = children.length; i < n; i++) {
  2099. var vnode = children[i];
  2100. parentNode.appendChild(mountVnode(null, vnode, vparent, context));
  2101. }
  2102. }
  2103. function alignChildren(parentNode, children, vparent, context) {
  2104. var childNodes = parentNode.childNodes,
  2105. insertPoint = childNodes[0] || null,
  2106. j = 0,
  2107. n = children.length;
  2108. for (var i = 0; i < n; i++) {
  2109. var vnode = children[i];
  2110. var lastNode = childNodes[j];
  2111. var dom = mountVnode(lastNode, vnode, vparent, context);
  2112. if (dom === lastNode) {
  2113. j++;
  2114. }
  2115. parentNode.insertBefore(dom, insertPoint);
  2116. insertPoint = dom.nextSibling;
  2117. }
  2118. while (childNodes[n]) {
  2119. parentNode.removeChild(childNodes[n]);
  2120. }
  2121. }
  2122. function mountComponent(lastNode, vnode, vparent, parentContext, parentUpdater) {
  2123. var type = vnode.type,
  2124. props = vnode.props,
  2125. ref = vnode.ref;
  2126. var context = getContextByTypes(parentContext, type.contextTypes);
  2127. var instance = instantiateComponent(type, vnode, props, context); //互相持有引用
  2128. var updater = instance.updater;
  2129. if (parentUpdater) {
  2130. updater.parentUpdater = parentUpdater;
  2131. }
  2132. updater.vparent = vparent;
  2133. updater.parentContext = parentContext;
  2134. if (instance.componentWillMount) {
  2135. instance.componentWillMount(); //这里可能执行了setState
  2136. instance.state = updater.mergeStates();
  2137. }
  2138. updater._hydrating = true;
  2139. var dom = updater.renderComponent(function (nextRendered, vparent, childContext) {
  2140. return mountVnode(lastNode, nextRendered, vparent, childContext, updater //作为parentUpater往下传
  2141. );
  2142. });
  2143. updater._openRef = !!ref;
  2144. updater._lifeStage = 1;
  2145. updater.oldDatas = emptyArray;
  2146. options.queue.push(updater);
  2147. return dom;
  2148. }
  2149. function updateComponent(lastVnode, nextVnode, vparent, parentContext) {
  2150. var type = lastVnode.type,
  2151. _hasRef = lastVnode._hasRef,
  2152. instance = lastVnode._instance,
  2153. _hostNode = lastVnode._hostNode;
  2154. var nextContext = void 0,
  2155. nextProps = nextVnode.props,
  2156. updater = instance.updater;
  2157. if (type.contextTypes) {
  2158. nextContext = getContextByTypes(parentContext, type.contextTypes);
  2159. } else {
  2160. nextContext = instance.context; //没有定义contextTypes就沿用旧的
  2161. }
  2162. var willReceive = lastVnode !== nextVnode || updater.context !== nextContext;
  2163. nextVnode._hostNode = _hostNode;
  2164. nextVnode._instance = instance;
  2165. updater.willReceive = willReceive;
  2166. //如果context与props都没有改变,那么就不会触发组件的receive,render,update等一系列钩子
  2167. //但还会继续向下比较
  2168. if (willReceive && instance.componentWillReceiveProps) {
  2169. updater._receiving = true;
  2170. instance.componentWillReceiveProps(nextProps, nextContext);
  2171. updater._receiving = false;
  2172. }
  2173. _hasRef && Refs.detachRef(lastVnode, nextVnode);
  2174. updater._openRef = nextVnode.ref;
  2175. //updater上总是保持新的数据
  2176. updater.context = nextContext;
  2177. updater.props = nextProps;
  2178. updater.vparent = vparent;
  2179. updater.parentContext = parentContext;
  2180. // nextVnode._instance = instance; //不能放这里
  2181. if (!willReceive) {
  2182. return updater.renderComponent(function (nextRendered, vparent, childContext) {
  2183. return alignVnode(updater.rendered, nextRendered, vparent, childContext);
  2184. });
  2185. }
  2186. updater.vnode = nextVnode;
  2187. patchComponent(updater);
  2188. //子组件先执行
  2189. options.queue.push(updater);
  2190. return updater._hostNode;
  2191. }
  2192. function patchComponent(updater) {
  2193. var instance = updater._instance,
  2194. dom = updater._hostNode,
  2195. nextContext = updater.context,
  2196. nextProps = updater.props,
  2197. vnode = updater.vnode;
  2198. if (updater._lifeStage === 1) {
  2199. return dom;
  2200. }
  2201. vnode._instance = instance; //放这里
  2202. updater._renderInNextCycle = null;
  2203. var nextState = updater.mergeStates();
  2204. var shouldUpdate = true;
  2205. if (!updater._forceUpdate && instance.shouldComponentUpdate && !instance.shouldComponentUpdate(nextProps, nextState, nextContext)) {
  2206. shouldUpdate = false;
  2207. } else if (instance.componentWillUpdate) {
  2208. instance.componentWillUpdate(nextProps, nextState, nextContext);
  2209. }
  2210. var lastProps = instance.props,
  2211. lastContext = instance.context,
  2212. lastState = instance.state;
  2213. updater._forceUpdate = false;
  2214. instance.state = nextState; //既然setState了,无论shouldComponentUpdate结果如何,用户传给的state对象都会作用到组件上
  2215. instance.context = nextContext;
  2216. if (!shouldUpdate) {
  2217. options.queue.push(updater);
  2218. return dom;
  2219. }
  2220. instance.props = nextProps;
  2221. updater._hydrating = true;
  2222. var lastRendered = updater.rendered;
  2223. dom = updater.renderComponent(function (nextRendered, vparent, childContext) {
  2224. return alignVnode(lastRendered, nextRendered, vparent, childContext, updater);
  2225. });
  2226. updater._lifeStage = 2;
  2227. updater.oldDatas = [lastProps, lastState, lastContext];
  2228. options.queue.push(updater);
  2229. return dom;
  2230. }
  2231. options.patchComponent = patchComponent;
  2232. var fakeLastNode = {
  2233. _disposed: true
  2234. };
  2235. function alignVnode(lastVnode, nextVnode, vparent, context, parentUpdater) {
  2236. var dom = void 0;
  2237. if (isSameNode(lastVnode, nextVnode)) {
  2238. dom = updateVnode(lastVnode, nextVnode, vparent, context);
  2239. } else {
  2240. disposeVnode(lastVnode);
  2241. var node = lastVnode._hostNode,
  2242. parentNode = node.parentNode;
  2243. dom = mountVnode(null, nextVnode, vparent, context, parentUpdater);
  2244. parentNode.replaceChild(dom, node);
  2245. }
  2246. return dom;
  2247. }
  2248. function genkey(vnode) {
  2249. return vnode.key ? "@" + vnode.key : vnode.type.name || vnode.type;
  2250. }
  2251. function diffChildren(parentVnode, nextChildren, parentNode, context) {
  2252. var lastChildren = parentVnode.vchildren || emptyArray,
  2253. //parentNode.vchildren,
  2254. nextLength = nextChildren.length,
  2255. insertPoint = parentNode.firstChild,
  2256. lastLength = lastChildren.length;
  2257. //optimize 1: 如果旧数组长度为零, 只进行添加
  2258. if (!lastLength) {
  2259. emptyElement(parentNode);
  2260. return mountChildren(parentNode, nextChildren, parentVnode, context);
  2261. }
  2262. //optimize 2: 如果新数组长度为零, 只进行删除
  2263. if (!nextLength) {
  2264. return lastChildren.forEach(function (el) {
  2265. removeElement(el._hostNode);
  2266. disposeVnode(el);
  2267. });
  2268. }
  2269. //optimize 3: 如果1vs1, 不用进入下面复杂的循环
  2270. if (nextLength === lastLength && lastLength === 1) {
  2271. if (insertPoint) {
  2272. lastChildren[0]._hostNode = insertPoint;
  2273. }
  2274. return alignVnode(lastChildren[0], nextChildren[0], parentVnode, context);
  2275. }
  2276. var mergeChildren = [],
  2277. //确保新旧数组都按原顺数排列
  2278. fuzzyHits = {},
  2279. i = 0,
  2280. hit = void 0,
  2281. oldDom = void 0,
  2282. dom = void 0,
  2283. nextChild = void 0;
  2284. lastChildren.forEach(function (lastChild) {
  2285. hit = genkey(lastChild);
  2286. mergeChildren.push(lastChild);
  2287. var hits = fuzzyHits[hit];
  2288. if (hits) {
  2289. hits.push(lastChild);
  2290. } else {
  2291. fuzzyHits[hit] = [lastChild];
  2292. }
  2293. });
  2294. while (i < nextLength) {
  2295. nextChild = nextChildren[i];
  2296. nextChild._new = true;
  2297. hit = genkey(nextChild);
  2298. if (fuzzyHits[hit] && fuzzyHits[hit].length) {
  2299. var oldChild = fuzzyHits[hit].shift();
  2300. // 如果命中旧节点,置空旧节点,并在新位置放入旧节点(向后移动)
  2301. var lastIndex = mergeChildren.indexOf(oldChild);
  2302. if (lastIndex !== -1) {
  2303. mergeChildren[lastIndex] = fakeLastNode;
  2304. // mergeChildren.splice(lastIndex, 1);
  2305. }
  2306. nextChild._new = oldChild;
  2307. }
  2308. mergeChildren.splice(i, 0, nextChild);
  2309. i++;
  2310. }
  2311. for (var j = 0, n = mergeChildren.length; j < n; j++) {
  2312. var _nextChild = mergeChildren[j];
  2313. if (_nextChild._new) {
  2314. var lastChild = _nextChild._new;
  2315. delete _nextChild._new;
  2316. if (dom) {
  2317. insertPoint = dom.nextSibling;
  2318. }
  2319. if (lastChild === true) {
  2320. //新节点有两种情况,命中位置更后方的旧节点或就地创建实例化
  2321. dom = mountVnode(null, _nextChild, parentVnode, context);
  2322. insertElement(parentNode, dom, insertPoint);
  2323. } else {
  2324. oldDom = lastChild._hostNode;
  2325. if (oldDom !== insertPoint) {
  2326. insertElement(parentNode, oldDom, insertPoint);
  2327. }
  2328. dom = alignVnode(lastChild, _nextChild, parentVnode, context);
  2329. }
  2330. } else {
  2331. if (_nextChild._hostNode) {
  2332. removeElement(_nextChild._hostNode);
  2333. disposeVnode(_nextChild);
  2334. }
  2335. }
  2336. }
  2337. }
  2338. function isSameNode(a, b) {
  2339. if (a.type === b.type && a.key === b.key) {
  2340. return true;
  2341. }
  2342. }
  2343. var React = {
  2344. version: "1.1.4",
  2345. render: render,
  2346. options: options,
  2347. PropTypes: PropTypes,
  2348. Children: Children, //为了react-redux
  2349. createPortal: createPortal,
  2350. Component: Component,
  2351. eventSystem: eventSystem,
  2352. findDOMNode: findDOMNode,
  2353. createClass: createClass,
  2354. createElement: createElement,
  2355. cloneElement: cloneElement,
  2356. PureComponent: PureComponent,
  2357. isValidElement: isValidElement,
  2358. unmountComponentAtNode: unmountComponentAtNode,
  2359. unstable_renderSubtreeIntoContainer: unstable_renderSubtreeIntoContainer,
  2360. createFactory: function createFactory(type) {
  2361. console.error("createFactory is deprecated"); // eslint-disable-line
  2362. var factory = createElement.bind(null, type);
  2363. factory.type = type;
  2364. return factory;
  2365. }
  2366. };
  2367. win.React = win.ReactDOM = React;
  2368. return React;
  2369. })));