index.html
vue可以使用v-bind:style绑定样式,但是权重层级比较高。在一些场景使用CSS写class样式更好,但是某些场景生成更多的元素,针对与每个都有特定的样式,比如低代码平台写table组件对于每一列都可以设置自己的样式,此时我们可以创建动态类,但是如何去绑定那就不能写死了,所以下面这种方式动态创建style标签可以使用,当然下面的方式中,注意参数的使用。以下是通过原始模拟了组件创建和销毁,在vue中对应mounted和unmounted两个生命周期。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.mt20{
margin-top: 20px;
}
</style>
</head>
<body>
<button id="mounted">模拟组件创建</button>
<button id="unmounted">模拟组件销毁</button>
<div class="mt20"></div>
<div id="app"></div>
<script type="module">
import './index.js'
</script>
</body>
</html>
index.js
export { }
const create_dynamic_style = (styleArr, pSelect, classNamePre, classNamesuffix, tagId) => {
let dynamicStyle = {}
styleArr.forEach((item, index) => {
Reflect.set(dynamicStyle, `${classNamePre}${index}${classNamesuffix}`, item)
})
const classNames = Object.keys(dynamicStyle)
let dynamicStr = ''
classNames.forEach(className => {
let styleStr = ''
Object.keys(dynamicStyle[className]).forEach(attr => {
styleStr += `
${attr}:${dynamicStyle[className][attr]};
`
})
dynamicStr += `
#${pSelect} .${className}{
${styleStr}
}
`
})
const _dynamic_style = document.createElement('style')
_dynamic_style.setAttribute('id', tagId)
_dynamic_style.innerHTML = dynamicStr
document.body.appendChild(_dynamic_style)
}
const init = (componentData, component, ID) => {
const { tagId, classNamePre, classNamesuffix, dataSoure } = componentData
const pSelect = component.id
const boxStyle = dataSoure.map((item, index) => {
// 创建元素
const div = document.createElement('div')
div.innerText = item.content.value
div.className = classNamePre + index + classNamesuffix
component.appendChild(div)
return item.style
})
create_dynamic_style(boxStyle, pSelect, classNamePre, classNamesuffix, tagId + ID)
}
const components = {
componentA: {
dataSoure: [
{
content: {
"value": 1
},
style: {
'width': "100px",
"height": '100px',
"background": "#1890FF",
"line-height": "100px",
"text-align": "center"
}
},
{
content: {
"value": 2
},
style: {
'width': "100px",
"height": '100px',
"background": "#00FF00",
"line-height": "100px",
"text-align": "center"
}
},
{
content: {
"value": 3
},
style: {
'width': "100px",
"height": '100px',
"background": "#FF0000",
"line-height": "100px",
"text-align": "center"
}
},
{
content: {
"value": 4
},
style: {
'width': "100px",
"height": '100px',
"background": "#0000FF",
"line-height": "100px",
"text-align": "center"
}
}
],
tagId: 'dynmaic_style',
baseName: 'componentA',
classNamePre: '__self-box-',
classNamesuffix: '__'
},
componentB: {
dataSoure: [
{
content: {
"value": 1
},
style: {
'width': "100px",
"height": '100px',
"background": "#1890FF",
"line-height": "100px",
"text-align": "center",
"border-radius": "50%"
}
},
{
content: {
"value": 2
},
style: {
'width': "100px",
"height": '100px',
"background": "#00FF00",
"line-height": "100px",
"text-align": "center",
"border-radius": "50%"
}
},
{
content: {
"value": 3
},
style: {
'width': "100px",
"height": '100px',
"background": "#FF0000",
"line-height": "100px",
"text-align": "center",
"border-radius": "50%"
}
},
{
content: {
"value": 4
},
style: {
'width': "100px",
"height": '100px',
"background": "#0000FF",
"line-height": "100px",
"text-align": "center",
"border-radius": "50%"
}
}
],
tagId: 'dynmaic_style',
baseName: 'componentB',
classNamePre: '__self-box-',
classNamesuffix: '__'
}
}
let CPNS = []
let ID = 0
const createComponent = (componentName) => {
if (components[componentName]) {
// 创建组件
const component = document.createElement('div')
component.id = components[componentName].baseName + ID
CPNS.push({
name: components[componentName].baseName,
id: ID
})
app.appendChild(component)
init(components[componentName], component, ID)
ID++
}
}
document.querySelector('#mounted').addEventListener('click', () => {
let message = ''
const cpns = Object.keys(components)
cpns.forEach(key => {
message += key + '、'
})
const componentName = window.prompt('请输入需要创建的组件类型,当前已存在组件类型包含:' + message)
if(cpns.indexOf(componentName) > -1){
createComponent(componentName)
}else{
alert('不存在组件:'+componentName)
}
})
document.querySelector('#unmounted').addEventListener('click', () => {
let message = ''
CPNS.forEach(item => {
message += item.id + '、'
})
const id = window.prompt('请输入需要销魂的组件ID,当前已存在组件ID包含:' + message)
// 销毁组件
const cpn = CPNS.filter(item => item.id == id)[0]
if (cpn) {
document.body.removeChild(document.querySelector(`#${components[cpn.name].tagId}${id}`))
app.removeChild(document.querySelector(`#${cpn.name}${id}`))
CPNS = CPNS.filter(item => item.id != id)
}else{
alert('请输入正确的组件ID')
}
})