Last active
May 7, 2018 15:27
-
-
Save jixunmoe/9ad359759597f706f61d07a09995c7d9 to your computer and use it in GitHub Desktop.
es5 implementation of jsx without state management.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @jsx h */ | |
// See https://c.jixun.moe/ui for live-demo | |
(function(root) { | |
function UnsafeHtml({ html }) { | |
var div = (<i />); | |
div.innerHTML = html; | |
return div.childNodes; | |
} | |
function ExternalLink({ className, href, children }) { | |
return ( | |
<a className={className} href={href} target="_blank"> | |
{ children } | |
</a> | |
); | |
} | |
function Author({ author, uri }) { | |
var AuthorTag = uri ? ExternalLink : "i"; | |
return ( | |
<AuthorTag className="author" href={uri}> | |
{author || "无名氏"} | |
</AuthorTag> | |
); | |
} | |
function Comment({ website, author, uri, text }) { | |
return ( | |
<div className="comment"> | |
<p> | |
<Author className="author" author={author} uri={website} /> | |
(来源: <ExternalLink href={`https://jixun.moe` + uri}>{uri}</ExternalLink>) | |
</p> | |
<div className="body"> | |
<UnsafeHtml html={text} /> | |
</div> | |
</div> | |
); | |
} | |
function App({ comments }) { | |
return ( | |
<div className="comments"> | |
{comments.map(comment => ( | |
<Comment {...comment} /> | |
))} | |
</div> | |
); | |
} | |
var xhr = new XMLHttpRequest(); | |
xhr.open("GET", "/latest"); | |
xhr.onload = xhr.onerror = function () { | |
var data; | |
try { | |
data = JSON.parse(xhr.responseText); | |
mount(root, <App {...data} />); | |
} catch (error) { | |
root.textContent = "获取评论出错。"; | |
} | |
} | |
xhr.send(); | |
})(document.getElementById("app")); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var h = (function () { | |
function deref(fn) { | |
return Function.call.bind(fn); | |
} | |
var slice = deref(Array.prototype.slice); | |
// Lodash code starts here | |
var MAX_SAFE_INTEGER = 9007199254740991; | |
function isObject(value) { | |
var type = typeof value; | |
return value != null && (type == 'object' || type == 'function'); | |
} | |
function isLength(value) { | |
return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; | |
} | |
function isArrayLike(value) { | |
return value != null && isLength(value.length) && !isFunction(value); | |
} | |
function isObjectLike (value) { | |
return value != null && typeof value == "object"; | |
} | |
// Lodash code ends here | |
function isFunction(value) { | |
return value instanceof Function; | |
} | |
function makeArray(v) { | |
return (isArrayLike(v) && typeof v !== "string") ? slice(v) : [v]; | |
} | |
function isNode(el) { | |
return el instanceof Node; | |
} | |
function isObjectLikeNotArray(value) { | |
return isObjectLike(value) && !isArrayLike(value); | |
} | |
/** | |
* 深度对象合并 | |
* @param {Object} src 需要扩展的对象。 | |
* @param {Object} [...ext] 待扩展的属性。 | |
*/ | |
function merge(src) { | |
slice(arguments, 1).forEach(function (ext) { | |
if (isObjectLikeNotArray(ext)) { | |
Object.keys(ext).forEach(function (key) { | |
var value = ext[key]; | |
if (isObjectLikeNotArray(value)) { | |
if (!src[key]) { | |
src[key] = {}; | |
} | |
merge(src[key], value); | |
} else { | |
src[key] = value; | |
} | |
}); | |
} | |
}); | |
return src; | |
} | |
/** | |
* 建立一个 HTML 元素 | |
* @param {String|Function} tag 元素标签,或传入 Stateless 组件函数。 | |
* @param {Object.<String.String|Bool|Number>} [attrs = {}] 元素属性集合。 | |
* @param {Array.<String|Node>|String|Node} [...children] 子元素集合。 | |
*/ | |
function h(tag, attrs) { | |
var children = slice(arguments, 2); | |
// Stateless 组件建立 | |
if (isFunction(tag)) { | |
return tag(Object.assign({ children }, attrs)); | |
} | |
var el = merge(document.createElement(tag), attrs); | |
children.forEach(function (children) { | |
makeArray(children).forEach(function (child) { | |
el.appendChild(isNode(child) ? child : document.createTextNode(child)); | |
}); | |
}); | |
return el; | |
} | |
return h; | |
})(); | |
/** | |
* 将建立的元素挂载到一个 HTML 节点 (会先暴力清空节点内容)。 | |
* @param {HTMLElement} mnt 挂载点。 | |
* @param {Node} node HTML 元素或节点。 | |
*/ | |
function mount(mnt, node) { | |
mnt.innerHTML = ""; | |
mnt.appendChild(node); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment