preact.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. ! function () {
  2. "use strict";
  3. function VNode() {}
  4. function h(nodeName, attributes) {
  5. var lastSimple, child, simple, i, children = EMPTY_CHILDREN;
  6. for (i = arguments.length; i-- > 2;) {
  7. stack.push(arguments[i]);
  8. }
  9. if (attributes && null != attributes.children) {
  10. if (!stack.length) {
  11. stack.push(attributes.children);
  12. }
  13. delete attributes.children;
  14. }
  15. while (stack.length) {
  16. if ((child = stack.pop()) && void 0 !== child.pop)
  17. for (i = child.length; i--;) stack.push(child[i]);
  18. else {
  19. if ('boolean' == typeof child) child = null;
  20. if (simple = 'function' != typeof nodeName)
  21. if (null == child) child = '';
  22. else if ('number' == typeof child) child = String(child);
  23. else if ('string' != typeof child) simple = !1;
  24. if (simple && lastSimple) children[children.length - 1] += child;
  25. else if (children === EMPTY_CHILDREN) children = [child];
  26. else children.push(child);
  27. lastSimple = simple;
  28. }
  29. }
  30. var p = new VNode();
  31. p.nodeName = nodeName;
  32. p.children = children;
  33. p.attributes = null == attributes ? void 0 : attributes;
  34. p.key = null == attributes ? void 0 : attributes.key;
  35. if (void 0 !== options.vnode) {
  36. options.vnode(p);
  37. }
  38. return p;
  39. }
  40. function extend(obj, props) {
  41. for (var i in props) {
  42. obj[i] = props[i];
  43. }
  44. return obj;
  45. }
  46. function cloneElement(vnode, props) {
  47. return h(vnode.nodeName, extend(extend({}, vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children);
  48. }
  49. function enqueueRender(component) {
  50. if (!component.__d && (component.__d = !0) && 1 == items.push(component)) {
  51. (options.debounceRendering || defer)(rerender);
  52. }
  53. }
  54. function rerender() {
  55. var p, list = items;
  56. items = [];
  57. while (p = list.pop()) {
  58. if (p.__d) renderComponent(p);
  59. }
  60. }
  61. function isSameNodeType(node, vnode, hydrating) {
  62. if ("string" == typeof vnode || "number" == typeof vnode) {
  63. return void 0 !== node.splitText;
  64. }
  65. if ("string" == typeof vnode.nodeName) {
  66. return !node._componentConstructor && isNamedNode(node, vnode.nodeName);
  67. } else {
  68. return hydrating || node._componentConstructor === vnode.nodeName;
  69. }
  70. }
  71. function isNamedNode(node, nodeName) {
  72. return node.__n === nodeName || node.nodeName.toLowerCase() === nodeName.toLowerCase();
  73. }
  74. function getNodeProps(vnode) {
  75. var props = extend({}, vnode.attributes);
  76. props.children = vnode.children;
  77. var defaultProps = vnode.nodeName.defaultProps;
  78. if (void 0 !== defaultProps) {
  79. for (var i in defaultProps)
  80. if (void 0 === props[i]) props[i] = defaultProps[i];
  81. }
  82. return props;
  83. }
  84. function createNode(nodeName, isSvg) {
  85. var node = isSvg ? document.createElementNS("http://www.w3.org/2000/svg", nodeName) : document.createElement(nodeName);
  86. node.__n = nodeName;
  87. return node;
  88. }
  89. function removeNode(node) {
  90. var parentNode = node.parentNode;
  91. if (parentNode) {
  92. parentNode.removeChild(node);
  93. }
  94. }
  95. function setAccessor(node, name, old, value, isSvg) {
  96. if ("className" === name) {
  97. name = 'class';
  98. }
  99. if ("key" === name) {;
  100. } else if ("ref" === name) {
  101. if (old) {
  102. old(null);
  103. }
  104. if (value) {
  105. value(node);
  106. }
  107. } else if ("class" === name && !isSvg) {
  108. node.className = value || '';
  109. } else if ("style" === name) {
  110. if (!value || "string" == typeof value || "string" == typeof old) {
  111. node.style.cssText = value || '';
  112. }
  113. if (value && "object" == typeof value) {
  114. if ("string" != typeof old) {
  115. for (var i in old)
  116. if (!(i in value)) node.style[i] = '';
  117. }
  118. for (var i in value) {
  119. node.style[i] = 'number' == typeof value[i] && !1 === IS_NON_DIMENSIONAL.test(i) ? value[i] + 'px' : value[i];
  120. }
  121. }
  122. } else if ("dangerouslySetInnerHTML" === name) {
  123. if (value) {
  124. node.innerHTML = value.__html || '';
  125. }
  126. } else if ("o" == name[0] && "n" == name[1]) {
  127. var useCapture = name !== (name = name.replace(/Capture$/, ""));
  128. name = name.toLowerCase().substring(2);
  129. if (value) {
  130. if (!old) {
  131. node.addEventListener(name, eventProxy, useCapture);
  132. }
  133. } else {
  134. node.removeEventListener(name, eventProxy, useCapture);
  135. }
  136. (node.__l || (node.__l = {}))[name] = value;
  137. } else if ("list" !== name && "type" !== name && !isSvg && name in node) {
  138. setProperty(node, name, null == value ? "" : value);
  139. if (null == value || !1 === value) {
  140. node.removeAttribute(name);
  141. }
  142. } else {
  143. var ns = isSvg && name !== (name = name.replace(/^xlink\:?/, ""));
  144. if (null == value || !1 === value) {
  145. if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());
  146. else node.removeAttribute(name);
  147. } else if ("function" != typeof value) {
  148. if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);
  149. else node.setAttribute(name, value);
  150. }
  151. }
  152. }
  153. function setProperty(node, name, value) {
  154. try {
  155. node[name] = value;
  156. } catch (e) {}
  157. }
  158. function eventProxy(e) {
  159. return this.__l[e.type](options.event && options.event(e) || e);
  160. }
  161. function flushMounts() {
  162. var c;
  163. while (c = mounts.pop()) {
  164. if (options.afterMount) {
  165. options.afterMount(c);
  166. }
  167. if (c.componentDidMount) {
  168. c.componentDidMount();
  169. }
  170. }
  171. }
  172. function diff(dom, vnode, context, mountAll, parent, componentRoot) {
  173. if (!diffLevel++) {
  174. isSvgMode = null != parent && void 0 !== parent.ownerSVGElement;
  175. hydrating = null != dom && !("__preactattr_" in dom);
  176. }
  177. var ret = idiff(dom, vnode, context, mountAll, componentRoot);
  178. if (parent && ret.parentNode !== parent) {
  179. parent.appendChild(ret);
  180. }
  181. if (!--diffLevel) {
  182. hydrating = !1;
  183. if (!componentRoot) {
  184. flushMounts();
  185. }
  186. }
  187. return ret;
  188. }
  189. function idiff(dom, vnode, context, mountAll, componentRoot) {
  190. var out = dom,
  191. prevSvgMode = isSvgMode;
  192. if (null == vnode || "boolean" == typeof vnode) {
  193. vnode = '';
  194. }
  195. if ("string" == typeof vnode || "number" == typeof vnode) {
  196. if (dom && void 0 !== dom.splitText && dom.parentNode && (!dom._component || componentRoot)) {
  197. if (dom.nodeValue != vnode) {
  198. dom.nodeValue = vnode;
  199. }
  200. } else {
  201. out = document.createTextNode(vnode);
  202. if (dom) {
  203. if (dom.parentNode) {
  204. dom.parentNode.replaceChild(out, dom);
  205. }
  206. recollectNodeTree(dom, !0);
  207. }
  208. }
  209. out.__preactattr_ = !0;
  210. return out;
  211. }
  212. var vnodeName = vnode.nodeName;
  213. if ("function" == typeof vnodeName) {
  214. return buildComponentFromVNode(dom, vnode, context, mountAll);
  215. }
  216. isSvgMode = "svg" === vnodeName ? !0 : "foreignObject" === vnodeName ? !1 : isSvgMode;
  217. vnodeName = String(vnodeName);
  218. if (!dom || !isNamedNode(dom, vnodeName)) {
  219. out = createNode(vnodeName, isSvgMode);
  220. if (dom) {
  221. while (dom.firstChild) {
  222. out.appendChild(dom.firstChild);
  223. }
  224. if (dom.parentNode) {
  225. dom.parentNode.replaceChild(out, dom);
  226. }
  227. recollectNodeTree(dom, !0);
  228. }
  229. }
  230. var fc = out.firstChild,
  231. props = out.__preactattr_,
  232. vchildren = vnode.children;
  233. if (null == props) {
  234. props = out.__preactattr_ = {};
  235. for (var a = out.attributes, i = a.length; i--;) {
  236. props[a[i].name] = a[i].value;
  237. }
  238. }
  239. if (!hydrating && vchildren && 1 === vchildren.length && "string" == typeof vchildren[0] && null != fc && void 0 !== fc.splitText && null == fc.nextSibling) {
  240. if (fc.nodeValue != vchildren[0]) {
  241. fc.nodeValue = vchildren[0];
  242. }
  243. } else if (vchildren && vchildren.length || null != fc) {
  244. innerDiffNode(out, vchildren, context, mountAll, hydrating || null != props.dangerouslySetInnerHTML);
  245. }
  246. diffAttributes(out, vnode.attributes, props);
  247. isSvgMode = prevSvgMode;
  248. return out;
  249. }
  250. function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
  251. var j, c, f, vchild, child, originalChildren = dom.childNodes,
  252. children = [],
  253. keyed = {},
  254. keyedLen = 0,
  255. min = 0,
  256. len = originalChildren.length,
  257. childrenLen = 0,
  258. vlen = vchildren ? vchildren.length : 0;
  259. if (0 !== len) {
  260. for (var i = 0; i < len; i++) {
  261. var _child = originalChildren[i],
  262. props = _child.__preactattr_,
  263. key = vlen && props ? _child._component ? _child._component.__k : props.key : null;
  264. if (null != key) {
  265. keyedLen++;
  266. keyed[key] = _child;
  267. } else if (props || (void 0 !== _child.splitText ? isHydrating ? _child.nodeValue.trim() : !0 : isHydrating)) children[childrenLen++] = _child;
  268. }
  269. }
  270. if (0 !== vlen) {
  271. for (var i = 0; i < vlen; i++) {
  272. vchild = vchildren[i];
  273. child = null;
  274. var key = vchild.key;
  275. if (null != key) {
  276. if (keyedLen && void 0 !== keyed[key]) {
  277. child = keyed[key];
  278. keyed[key] = void 0;
  279. keyedLen--;
  280. }
  281. } else if (!child && min < childrenLen)
  282. for (j = min; j < childrenLen; j++)
  283. if (void 0 !== children[j] && isSameNodeType(c = children[j], vchild, isHydrating)) {
  284. child = c;
  285. children[j] = void 0;
  286. if (j === childrenLen - 1) childrenLen--;
  287. if (j === min) min++;
  288. break;
  289. }
  290. child = idiff(child, vchild, context, mountAll);
  291. f = originalChildren[i];
  292. if (child && child !== dom && child !== f)
  293. if (null == f) dom.appendChild(child);
  294. else if (child === f.nextSibling) removeNode(f);
  295. else dom.insertBefore(child, f);
  296. }
  297. }
  298. if (keyedLen) {
  299. for (var i in keyed)
  300. if (void 0 !== keyed[i]) recollectNodeTree(keyed[i], !1);
  301. }
  302. while (min <= childrenLen) {
  303. if (void 0 !== (child = children[childrenLen--])) recollectNodeTree(child, !1);
  304. }
  305. }
  306. function recollectNodeTree(node, unmountOnly) {
  307. var component = node._component;
  308. if (component) {
  309. unmountComponent(component);
  310. } else {
  311. if (null != node.__preactattr_ && node.__preactattr_.ref) {
  312. node.__preactattr_.ref(null);
  313. }
  314. if (!1 === unmountOnly || null == node.__preactattr_) {
  315. removeNode(node);
  316. }
  317. removeChildren(node);
  318. }
  319. }
  320. function removeChildren(node) {
  321. node = node.lastChild;
  322. while (node) {
  323. var next = node.previousSibling;
  324. recollectNodeTree(node, !0);
  325. node = next;
  326. }
  327. }
  328. function diffAttributes(dom, attrs, old) {
  329. var name;
  330. for (name in old) {
  331. if ((!attrs || null == attrs[name]) && null != old[name]) setAccessor(dom, name, old[name], old[name] = void 0, isSvgMode);
  332. }
  333. for (name in attrs) {
  334. if (!('children' === name || 'innerHTML' === name || name in old && attrs[name] === ('value' === name || 'checked' === name ? dom[name] : old[name]))) setAccessor(dom, name, old[name], old[name] = attrs[name], isSvgMode);
  335. }
  336. }
  337. function collectComponent(component) {
  338. var name = component.constructor.name;
  339. (components[name] || (components[name] = [])).push(component);
  340. }
  341. function createComponent(Ctor, props, context) {
  342. var inst, list = components[Ctor.name];
  343. if (Ctor.prototype && Ctor.prototype.render) {
  344. inst = new Ctor(props, context);
  345. Component.call(inst, props, context);
  346. } else {
  347. inst = new Component(props, context);
  348. inst.constructor = Ctor;
  349. inst.render = doRender;
  350. }
  351. if (list) {
  352. for (var i = list.length; i--;)
  353. if (list[i].constructor === Ctor) {
  354. inst.__b = list[i].__b;
  355. list.splice(i, 1);
  356. break;
  357. }
  358. }
  359. return inst;
  360. }
  361. function doRender(props, state, context) {
  362. return this.constructor(props, context);
  363. }
  364. function setComponentProps(component, props, opts, context, mountAll) {
  365. if (!component.__x) {
  366. component.__x = !0;
  367. if (component.__r = props.ref) {
  368. delete props.ref;
  369. }
  370. if (component.__k = props.key) {
  371. delete props.key;
  372. }
  373. if (!component.base || mountAll) {
  374. if (component.componentWillMount) {
  375. component.componentWillMount();
  376. }
  377. } else if (component.componentWillReceiveProps) {
  378. component.componentWillReceiveProps(props, context);
  379. }
  380. if (context && context !== component.context) {
  381. if (!component.__c) {
  382. component.__c = component.context;
  383. }
  384. component.context = context;
  385. }
  386. if (!component.__p) {
  387. component.__p = component.props;
  388. }
  389. component.props = props;
  390. component.__x = !1;
  391. if (0 !== opts) {
  392. if (1 === opts || !1 !== options.syncComponentUpdates || !component.base) renderComponent(component, 1, mountAll);
  393. else enqueueRender(component);
  394. }
  395. if (component.__r) {
  396. component.__r(component);
  397. }
  398. }
  399. }
  400. function renderComponent(component, opts, mountAll, isChild) {
  401. if (!component.__x) {
  402. var rendered, inst, cbase, props = component.props,
  403. state = component.state,
  404. context = component.context,
  405. previousProps = component.__p || props,
  406. previousState = component.__s || state,
  407. previousContext = component.__c || context,
  408. isUpdate = component.base,
  409. nextBase = component.__b,
  410. initialBase = isUpdate || nextBase,
  411. initialChildComponent = component._component,
  412. skip = !1;
  413. if (isUpdate) {
  414. component.props = previousProps;
  415. component.state = previousState;
  416. component.context = previousContext;
  417. if (2 !== opts && component.shouldComponentUpdate && !1 === component.shouldComponentUpdate(props, state, context)) {
  418. skip = !0;
  419. } else if (component.componentWillUpdate) {
  420. component.componentWillUpdate(props, state, context);
  421. }
  422. component.props = props;
  423. component.state = state;
  424. component.context = context;
  425. }
  426. component.__p = component.__s = component.__c = component.__b = null;
  427. component.__d = !1;
  428. if (!skip) {
  429. rendered = component.render(props, state, context);
  430. if (component.getChildContext) {
  431. context = extend(extend({}, context), component.getChildContext());
  432. }
  433. var toUnmount, base, childComponent = rendered && rendered.nodeName;
  434. if ("function" == typeof childComponent) {
  435. var childProps = getNodeProps(rendered);
  436. inst = initialChildComponent;
  437. if (inst && inst.constructor === childComponent && childProps.key == inst.__k) {
  438. setComponentProps(inst, childProps, 1, context, !1);
  439. } else {
  440. toUnmount = inst;
  441. component._component = inst = createComponent(childComponent, childProps, context);
  442. inst.__b = inst.__b || nextBase;
  443. inst.__u = component;
  444. setComponentProps(inst, childProps, 0, context, !1);
  445. renderComponent(inst, 1, mountAll, !0);
  446. }
  447. base = inst.base;
  448. } else {
  449. cbase = initialBase;
  450. toUnmount = initialChildComponent;
  451. if (toUnmount) {
  452. cbase = component._component = null;
  453. }
  454. if (initialBase || 1 === opts) {
  455. if (cbase) {
  456. cbase._component = null;
  457. }
  458. base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0);
  459. }
  460. }
  461. if (initialBase && base !== initialBase && inst !== initialChildComponent) {
  462. var baseParent = initialBase.parentNode;
  463. if (baseParent && base !== baseParent) {
  464. baseParent.replaceChild(base, initialBase);
  465. if (!toUnmount) {
  466. initialBase._component = null;
  467. recollectNodeTree(initialBase, !1);
  468. }
  469. }
  470. }
  471. if (toUnmount) {
  472. unmountComponent(toUnmount);
  473. }
  474. component.base = base;
  475. if (base && !isChild) {
  476. var componentRef = component,
  477. t = component;
  478. while (t = t.__u) {
  479. (componentRef = t).base = base;
  480. }
  481. base._component = componentRef;
  482. base._componentConstructor = componentRef.constructor;
  483. }
  484. }
  485. if (!isUpdate || mountAll) {
  486. mounts.unshift(component);
  487. } else if (!skip) {
  488. if (component.componentDidUpdate) {
  489. component.componentDidUpdate(previousProps, previousState, previousContext);
  490. }
  491. if (options.afterUpdate) {
  492. options.afterUpdate(component);
  493. }
  494. }
  495. if (null != component.__h) {
  496. while (component.__h.length) component.__h.pop().call(component);
  497. }
  498. if (!diffLevel && !isChild) {
  499. flushMounts();
  500. }
  501. }
  502. }
  503. function buildComponentFromVNode(dom, vnode, context, mountAll) {
  504. var c = dom && dom._component,
  505. originalComponent = c,
  506. oldDom = dom,
  507. isDirectOwner = c && dom._componentConstructor === vnode.nodeName,
  508. isOwner = isDirectOwner,
  509. props = getNodeProps(vnode);
  510. while (c && !isOwner && (c = c.__u)) {
  511. isOwner = c.constructor === vnode.nodeName;
  512. }
  513. if (c && isOwner && (!mountAll || c._component)) {
  514. setComponentProps(c, props, 3, context, mountAll);
  515. dom = c.base;
  516. } else {
  517. if (originalComponent && !isDirectOwner) {
  518. unmountComponent(originalComponent);
  519. dom = oldDom = null;
  520. }
  521. c = createComponent(vnode.nodeName, props, context);
  522. if (dom && !c.__b) {
  523. c.__b = dom;
  524. oldDom = null;
  525. }
  526. setComponentProps(c, props, 1, context, mountAll);
  527. dom = c.base;
  528. if (oldDom && dom !== oldDom) {
  529. oldDom._component = null;
  530. recollectNodeTree(oldDom, !1);
  531. }
  532. }
  533. return dom;
  534. }
  535. function unmountComponent(component) {
  536. if (options.beforeUnmount) {
  537. options.beforeUnmount(component);
  538. }
  539. var base = component.base;
  540. component.__x = !0;
  541. if (component.componentWillUnmount) {
  542. component.componentWillUnmount();
  543. }
  544. component.base = null;
  545. var inner = component._component;
  546. if (inner) {
  547. unmountComponent(inner);
  548. } else if (base) {
  549. if (base.__preactattr_ && base.__preactattr_.ref) {
  550. base.__preactattr_.ref(null);
  551. }
  552. component.__b = base;
  553. removeNode(base);
  554. collectComponent(component);
  555. removeChildren(base);
  556. }
  557. if (component.__r) {
  558. component.__r(null);
  559. }
  560. }
  561. function Component(props, context) {
  562. this.__d = !0;
  563. this.context = context;
  564. this.props = props;
  565. this.state = this.state || {};
  566. }
  567. function render(vnode, parent, merge) {
  568. return diff(merge, vnode, {}, !1, parent, !1);
  569. }
  570. var options = {};
  571. var stack = [];
  572. var EMPTY_CHILDREN = [];
  573. var defer = "function" == typeof Promise ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;
  574. var IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
  575. var items = [];
  576. var mounts = [];
  577. var diffLevel = 0;
  578. var isSvgMode = !1;
  579. var hydrating = !1;
  580. var components = {};
  581. extend(Component.prototype, {
  582. setState: function (state, callback) {
  583. var s = this.state;
  584. if (!this.__s) {
  585. this.__s = extend({}, s);
  586. }
  587. extend(s, "function" == typeof state ? state(s, this.props) : state);
  588. if (callback) {
  589. (this.__h = this.__h || []).push(callback);
  590. }
  591. enqueueRender(this);
  592. },
  593. forceUpdate: function (callback) {
  594. if (callback) {
  595. (this.__h = this.__h || []).push(callback);
  596. }
  597. renderComponent(this, 2);
  598. },
  599. render: function () {}
  600. });
  601. var preact = {
  602. h: h,
  603. createElement: h,
  604. cloneElement: cloneElement,
  605. Component: Component,
  606. render: render,
  607. rerender: rerender,
  608. options: options
  609. };
  610. if ("undefined" != typeof module) {
  611. module.exports = preact;
  612. } else {
  613. self.preact = preact;
  614. }
  615. }();