我正在使用VueJS并具有像这样动态创建的嵌套元素:
<container>
<outerElement class="outer" v-for="obj in objects">
<innerElement class="inner" v-for="element in obj"/>
</outerElement>
</container>
现在,谈到CSS时,我遇到了一个小问题。由于innerElements旨在可移动,因此它们需要外部元素具有与容器相同的大小/位置。
CSS中是否有某种方法可以在保留在容器中的同时从“外部”类中删除框模型?
为了解决提到的XY问题,这是简化版本的模板,使用与我的应用程序相同的实现方法。
<template>
<div class="home">
<h1>This is the main Page.</h1>
<h2>Testing area:</h2>
<br />Simple Data Example:
<br />
<div class="container">
<button @click="simpleXOR()">XOR</button>
{{ data }}
<vue-draggable-resizable
class="simple"
v-for="(bit,index) in simpleData"
:key="index"
:w="50"
:h="50"
:parent="true"
:resizable="false"
>
{{`Bit-${index} => `}}
<status-indicator :status="bit ? 'positive' : 'negative'" />
</vue-draggable-resizable>
</div>
<br />Nested Data Example
<div class="container">
<div class="outer" v-for="obj in nestedObj.data" :key="obj.name">
<div class="label">
<button @click="nestedXOR(obj.name)">XOR -> {{ obj.name }}</button>
{{ obj.states }}
</div>
<vue-draggable-resizable
class="inner"
v-for="(state, index) in obj.states"
:key="index"
:resizable="false"
:w="100"
:h="50"
:parent="true"
>
<div v-if="obj.contentType === 'TypeA'">
<b>{{ `Bit-${index} of ${obj.name}` }}</b>
<br />
<status-indicator :status="state ? 'positive' : 'negative'" />
</div>
<div v-else>
<b>{{ `Bit-${index} of ${obj.name}` }}</b>
<br />
<status-indicator :status="state ? 'active' : 'intermediary'" />
</div>
</vue-draggable-resizable>
</div>
</div>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: "home",
components: {},
data() {
return {
simpleData: [0, 1, 0, 1],
nestedObj: {
data: [
{
states: [0, 1, 0, 1],
name: "a",
contentType: "TypeA"
},
{
states: [0, 1, 0, 1],
name: "b",
contentType: "TypeB"
}
]
}
};
},
computed: {
data() {
return this.simpleData;
}
},
methods: {
simpleXOR() {
var x = [];
for (var i = 0; i < this.simpleData.length; i++) {
x.push(this.simpleData[i] ^ 1);
}
this.simpleData = x;
console.debug(this.simpleData);
},
nestedXOR(name) {
var index = this.nestedObj.data.findIndex(obj => {
return obj.name === name;
});
var x = [];
for (var i = 0; i < this.nestedObj.data[index].states.length; i++) {
x.push(this.nestedObj.data[index].states[i] ^ 1);
}
this.nestedObj.data[index].states = x;
}
}
};
</script>
<style scoped>
.container {
margin: auto;
height: 200px;
width: 1000px;
border: 2px solid black;
position: relative;
}
.simple {
top: 0px;
left: 0px;
}
.outer {
display: contents; /* as suggested */
}
.inner {
/* ??? */
}
.label {
border: 1px dashed green;
padding: 10px;
height: 20%;
width: 20%;
}
/* // This is the css for vue-draggable-resizable */
/* // DON'T EDIT unless customization is needed */
.vdr {
touch-action: none;
position: absolute;
box-sizing: border-box;
border: 1px dashed black;
}
.handle {
box-sizing: border-box;
position: absolute;
width: 10px;
height: 10px;
background: #eee;
border: 1px solid #333;
}
.handle-tl {
top: -10px;
left: -10px;
cursor: nw-resize;
}
.handle-tm {
top: -10px;
left: 50%;
margin-left: -5px;
cursor: n-resize;
}
.handle-tr {
top: -10px;
right: -10px;
cursor: ne-resize;
}
.handle-ml {
top: 50%;
margin-top: -5px;
left: -10px;
cursor: w-resize;
}
.handle-mr {
top: 50%;
margin-top: -5px;
right: -10px;
cursor: e-resize;
}
.handle-bl {
bottom: -10px;
left: -10px;
cursor: sw-resize;
}
.handle-bm {
bottom: -10px;
left: 50%;
margin-left: -5px;
cursor: s-resize;
}
.handle-br {
bottom: -10px;
right: -10px;
cursor: se-resize;
}
@media only screen and (max-width: 768px) {
[class*="handle-"]:before {
content: "";
left: -10px;
right: -10px;
bottom: -10px;
top: -10px;
position: absolute;
}
}
</style>
Currently the problem in this code is that the innerElements can't be moved inside the container, because the outerElement is their container.
Since I can't change the parent selector to use the container instead of the outerElement this is hard to change.
Thus I wanted to make the outerElements borders non-existant so that the innerElement uses the container as parent.
But I suppose my thought is a bit weird, considering that the vue-draggable-resizable component will use the outerElement as parent anyways.
Here's a screenshot of the problem:
The moveable boxes can't be moved inside the container because the outerElement doesn't inherit the position and size of the container.
For your simple example, you could just flatten the nested array before iterating over it:
<container>
<innerElement class="inner" v-for="element in objects.flat(1)" />
</container>
您发布的更复杂的示例有点棘手,因为内部循环也需要访问obj
。尽管如此,您仍然可以通过编写一个自定义方法来实现此目的,该方法将每个状态包装在一个包装器中,该包装器既包含状态又包含对其所属对象的引用,如下所示:
<div class="container">
<div class="label" v-for="obj in nestedObj.data" :key="obj.name">
<button @click="nestedXOR(obj.name)">XOR -> {{ obj.name }}</button>
{{ obj.states }}
</div>
<vue-draggable-resizable
class="inner"
v-for="wrapper in flattenStates(nestedObj.data)"
:key="wrapper.key"
:resizable="false"
:w="100"
:h="50"
:parent="true"
>
<div v-if="wrapper.obj.contentType === 'TypeA'">
<b>{{ `Bit-${wrapper.index} of ${wrapper.obj.name}` }}</b>
<br />
<status-indicator :status="wrapper.state ? 'positive' : 'negative'" />
</div>
<div v-else>
<b>{{ `Bit-${wrapper.index} of ${wrapper.obj.name}` }}</b>
<br />
<status-indicator :status="wrapper.state ? 'active' : 'intermediary'" />
</div>
</vue-draggable-resizable>
</div>
该flattenStates
方法看起来像这样:
flattenStates: function (objects) {
return objects.flatMap( obj => {
return obj.states.map( (state, index) => {
return {
obj: obj,
state: state,
index: index,
key: obj.name + " state " + index
};
} );
} );
}
兼容性说明:.flat()
并且.flatMap()
在IE或Edge的当前稳定版本上不可用。要使这些代码在那些浏览器上运行,您需要一个polyfill。但是,基于Chromium的基于Chromium的新版本在撰写本文时仍处于beta版,但两者都支持。
另外,您可以通过将一些逻辑移入flattenStates
方法来简化模板:
<div class="container">
<!-- label divs omitted for brevity -->
<vue-draggable-resizable
class="inner"
v-for="wrapper in flattenStates(nestedObj.data)"
:key="wrapper.title"
:resizable="false"
:w="100"
:h="50"
:parent="true"
>
<div>
<b>{{ wrapper.title }}</b>
<br />
<status-indicator :status="wrapper.status" />
</div>
</vue-draggable-resizable>
</div>
flattenStates: function (objects) {
return objects.flatMap( obj => {
return obj.states.map( (state, index) => {
const wrapper = {
title: `Bit-${index} of ${obj.name}` // also used as :key
};
if (obj.contentType === 'TypeA') {
wrapper.status = (state ? 'positive' : 'negative');
} else {
wrapper.status = (state ? 'active' : 'intermediary');
}
return wrapper;
} );
} );
}
...甚至:
<div class="container">
<!-- label divs omitted for brevity -->
<vue-draggable-resizable
class="inner"
v-for="(status, title) in flattenStates(nestedObj.data)"
:key="title"
:resizable="false"
:w="100"
:h="50"
:parent="true"
>
<div>
<b>{{ title }}</b>
<br />
<status-indicator :status="status" />
</div>
</vue-draggable-resizable>
</div>
flattenStates: function (objects) {
const objStates = {};
for (const obj of objects) {
obj.states.forEach( (state, index) => {
const title = `Bit-${index} of ${obj.name}`;
if (obj.contentType === 'TypeA') {
objStates[title] = (state ? 'positive' : 'negative');
} else {
objStates[title] = (state ? 'active' : 'intermediary');
}
} );
}
return objStates;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句