225 lines
10 KiB
JavaScript
225 lines
10 KiB
JavaScript
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 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 const Div = (options) => createElement(options, 'div')
|
|
|
|
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 class div extends HTMLDivElement {
|
|
constructor(options) {
|
|
super()
|
|
for (const key in options) {
|
|
if (key === 'text') {
|
|
this.textContent = options[key]
|
|
continue
|
|
}
|
|
|
|
if (key.startsWith('on')) this[key] = options[key]
|
|
else this.setAttribute(key, options[key])
|
|
}
|
|
}
|
|
static w(width) { return new this({ style: { width } }) }
|
|
static h(height) { return new this({ style: { height } }) }
|
|
static x(left) { return new this({ style: { left } }) }
|
|
static y(top) { return new this({ style: { top } }) }
|
|
static z(index) { return new this({ style: { zIndex: index } }) }
|
|
static r(radius) { return new this({ style: { borderRadius: radius } }) }
|
|
static b(border) { return new this({ style: { border } }) }
|
|
static p(padding) { return new this({ style: { padding } }) }
|
|
static m(margin) { return new this({ style: { margin } }) }
|
|
static o(opacity) { return new this({ style: { opacity } }) }
|
|
static flex(flex) { return new this({ style: { flex } }) }
|
|
static grid(grid) { return new this({ style: { grid } }) }
|
|
static text(text) {
|
|
console.log('text::', new this({ text }))
|
|
return new this({ text })
|
|
}
|
|
static children(children) { return new this({ children }) }
|
|
|
|
w(width) { this.style.width = width + 'px'; return this }
|
|
h(height) { this.style.height = height + 'px'; return this }
|
|
x(left) { this.style.left = left; return this }
|
|
y(top) { this.style.top = top; return this }
|
|
z(index) { this.style.zIndex = index; return this }
|
|
r(radius) { this.style.borderRadius = radius; return this }
|
|
b(border) { this.style.border = border; return this }
|
|
p(padding) { this.style.padding = padding; return this }
|
|
m(margin) { this.style.margin = margin; return this }
|
|
o(opacity) { this.style.opacity = opacity; return this }
|
|
flex(flex) { this.style.flex = flex; return this }
|
|
grid(grid) { this.style.grid = grid; return this }
|
|
text(text) {
|
|
console.log('text', text)
|
|
this.textContent = text; return this
|
|
}
|
|
children(children) {
|
|
children.forEach(child => {
|
|
console.log('child', child)
|
|
this.appendChild(child)
|
|
});
|
|
return this
|
|
}
|
|
}
|
|
|
|
export class pre extends HTMLPreElement {
|
|
constructor(options) {
|
|
super()
|
|
for (const key in options) {
|
|
if (key.startsWith('on')) this[key] = options[key]
|
|
else this.setAttribute(key, options[key])
|
|
}
|
|
}
|
|
static text(text) { return new this({ textContent: text }) }
|
|
}
|
|
|
|
customElements.define('my-div', div, { extends: 'div' })
|
|
customElements.define('my-pre', pre, { extends: 'pre' })
|
|
|
|
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,
|
|
div, pre
|
|
}
|