export function createElement({ innerText, innerHTML, textContent, readOnly, children = [], dataset, style, classList = [], ...attributes }, tagName = 'div') { const element = document.createElement(tagName) for (const key in attributes) { if (key.startsWith('on')) element[key] = attributes[key] // 如果是事件则直接赋值 else element.setAttribute(key, attributes[key]) // 否则是属性则使用setAttribute } if (dataset) Object.assign(element.dataset, dataset) if (style) Object.assign(element.style, style) if (classList.length) element.classList.add(...classList) if (textContent) element.textContent = textContent if (innerText) element.innerText = innerText if (innerHTML) element.innerHTML = innerHTML if (readOnly) element.readOnly = readOnly if (children) children.forEach(child => element.appendChild(child)) return element } /* HTML5 语义标签 */ export const List = (options) => createElement(options, 'ul') export const ListItem = (options) => createElement(options, 'li') export const Div = (options) => createElement(options, 'div') export const Span = (options) => createElement(options, 'span') export const Button = (options) => createElement({ ...options, style: { cursor: 'pointer', ...options.style } }, 'button') export const Form = (options) => createElement(options, 'form') export const Header = (options) => createElement(options, 'header') export const Nav = (options) => createElement(options, 'nav') export const Main = (options) => createElement(options, 'main') export const Article = (options) => createElement(options, 'article') export const Section = (options) => createElement(options, 'section') export const Aside = (options) => createElement(options, 'aside') export const Footer = (options) => createElement(options, 'footer') export const H1 = (options) => createElement(options, 'h1') export const H2 = (options) => createElement(options, 'h2') export const H3 = (options) => createElement(options, 'h3') export const H4 = (options) => createElement(options, 'h4') export const H5 = (options) => createElement(options, 'h5') export const H6 = (options) => createElement(options, 'h6') export const P = (options) => createElement(options, 'p') export const A = (options) => createElement(options, 'a') export const Strong = (options) => createElement(options, 'strong') export const Em = (options) => createElement(options, 'em') export const Small = (options) => createElement(options, 'small') export const Mark = (options) => createElement(options, 'mark') export const Del = (options) => createElement(options, 'del') export const Ins = (options) => createElement(options, 'ins') export const Pre = (options) => createElement(options, 'pre') export const Code = (options) => createElement(options, 'code') export const Blockquote = (options) => createElement(options, 'blockquote') export const Q = (options) => createElement(options, 'q') export const Cite = (options) => createElement(options, 'cite') export const Hr = (options) => createElement(options, 'hr') export const Br = (options) => createElement(options, 'br') export const Ol = (options) => createElement(options, 'ol') export const Ul = (options) => createElement(options, 'ul') export const Li = (options) => createElement(options, 'li') export const Dl = (options) => createElement(options, 'dl') export const Dt = (options) => createElement(options, 'dt') export const Dd = (options) => createElement(options, 'dd') export const Figure = (options) => createElement(options, 'figure') export const Figcaption = (options) => createElement(options, 'figcaption') export const Img = (options) => createElement(options, 'img') export const Video = (options) => createElement(options, 'video') export const Audio = (options) => createElement(options, 'audio') export const Canvas = (options) => createElement(options, 'canvas') export const Svg = (options) => createElement(options, 'svg') export const Math = (options) => createElement(options, 'math') export const Table = (options) => createElement(options, 'table') export const Caption = (options) => createElement(options, 'caption') export const Thead = (options) => createElement(options, 'thead') export const Tfoot = (options) => createElement(options, 'tfoot') export const Tbody = (options) => createElement(options, 'tbody') export const Tr = (options) => createElement(options, 'tr') export const Th = (options) => createElement(options, 'th') export const Td = (options) => createElement(options, 'td') export const Col = (options) => createElement(options, 'col') export const Colgroup = (options) => createElement(options, 'colgroup') export const Fieldset = (options) => createElement(options, 'fieldset') export const Legend = (options) => createElement(options, 'legend') export const Label = (options) => createElement(options, 'label') export const Input = (options) => createElement(options, 'input') export const Select = (options) => createElement(options, 'select') export const TextArea = (options) => createElement(options, 'textarea') export function Avatar(options) { const element = createElement(options, 'img') element.onerror = () => element.src = '/favicon.ico' return element } export function Dialog(options) { const element = createElement({ tabIndex: 0, style: { position: 'fixed', top: 0, left: 0, zIndex: 1000, width: '100%', height: '100%', backdropFilter: 'blur(5px)', duration: '0.5s', transition: 'all 0.5s' }, onclick: async event => { if (event.target !== event.currentTarget) return await event.target.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 100 }).finished await event.target.remove() }, onkeydown: async event => { if (event.key !== 'Escape') return await event.target.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 100 }).finished await event.target.remove() }, children: [ createElement({ ...options, style: { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', backgroundColor: '#fff', borderRadius: '150px', boxShadow: '0 0 1em #ccc', overflow: 'hidden', display: 'flex', justifyContent: 'center', ...options.style, } }) ] }) const observer = new MutationObserver(mutationsList => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { element.focus() element.animate([{ opacity: 0 }, { opacity: 1 }], { duration: 100 }).finished return observer.disconnect() } } }) observer.observe(document.body, { childList: true, subtree: true }) return element } export default { createElement, List, ListItem, Span, Button, Img, Input, TextArea, Avatar, Dialog, Div, Form, Header, Nav, Main, Article, Section, Aside, Footer, H1, H2, H3, H4, H5, H6, P, A, Strong, Em, Small, Mark, Del, Ins, Pre, Code, Blockquote, Q, Cite, Hr, Br, Ol, Ul, Li, Dl, Dt, Dd, Figure, Figcaption, Video, Audio, Canvas, Svg, Math, Table, Caption, Thead, Tfoot, Tbody, Tr, Th, Td, Col, Colgroup, Fieldset, Legend, Label, Select, TextArea }