我目前正在使用Vue 2.x构建自定义叠加层组件。组件有一个支柱,可以使它处于绝对位置或固定位置。
问题是当我打开绝对位置时,我想向父组件添加position: relative
。我希望这是一个可重用的组件,所以我希望能够在不了解任何有关父项(id,class等)的情况下执行此操作。在自定义组件的父级中添加样式属性的最佳方法是什么?
这是我的自定义组件当前的外观:
<template>
<component
class="custom-overlay"
:style="overlayStyle"
:is="type"
v-if="value">
<slot :style="overlayContentStyle">
</slot>
</component>
</template>
<script>
import { colorShiftHelpers } from '../../mixins/helpers'
export default {
props: {
value: {
default: true,
type: Boolean
},
dark: {
default: false,
type: Boolean
},
absolute: {
default: false,
type: Boolean
},
color: {
default: 'rgb(23, 30, 38)',
type: String
},
opacity: {
default: 0.46,
type: Number | String
},
type: {
default: 'div',
type: String
},
zIndex: {
default: 5,
type: Number | String
}
},
mixins: [colorShiftHelpers],
computed: {
overlayStyle({ absolute, color, opacity, zIndex }) {
return {
position: absolute ? 'absolute' : 'fixed',
background: this.addAlpha(color, opacity),
'z-index': zIndex
}
}
}
}
</script>
<style scoped>
.custom-overlay {
top: 0;
left: 0;
height: 100%;
width: 100%;
}
</style>
答案 0 :(得分:0)
有两种方法可以实现这一目标:
Whith Vuex
通过一个状态变量控制所有样式。
商店
state: {
absolute: false;
}
mutations: {
setAbsolute(state, value) {
state.absolute = value // Here value should be true or false
}
}
父母
<template>
<div :class="{relative: absolute}">
<child-component
:is-absolute="absolute"
/>
</div>
</template>
<script>
export default {
computed: {
absolute() {
return this$store.state.absolute
}
}
}
</script>
在前面的示例中,我在商店中有一个名为absolute的变量,并且有一个变量来为该属性设置一个值,在这种情况下,您总是要传递一个布尔值,也可以像这样进行切换器突变: >
mutations: {
switchAbsolute(state) {
state.absolute = !state.absolute
}
}
只要您想更改该名称,即可
$store.commit('switchAbsolute')
或以下,如果要使用第一种方法手动设置值
$store.commit('setAbsolute', [the value you want absolute to be])
absolute的值在您的父级上作为计算属性接收,从那里您可以控制父级的样式,并将与prop相同的值传递给子级。注意条件类的绑定,.relative类应将位置设置为相对。
具有观看者和事件
接下来的逻辑是:在子组件上,只要prop发生更改,您都会发出一个事件,并在父组件上处理该事件以更改其样式:
孩子
props: {
absolute: {
type: Boolean,
default: false
}
},
watch: {
absolute: function(newVal, oldVal) {
if (newVal === true) {
this.$emit('childIsAbsolute')
}
}
}
在父母身上*
<template>
<div :styles="relativePosition">
<child-component @childIsAbsolute="handleChange($event)"
:absolute="absolute"
/>
</div>
</template>
<scrip>
export default {
data() {
relative: false;
absolute: false
},
methods: {
handleChange(event) {
this.relative = event //here event is true or false, depending
on the value of the child's prop, emited from the watcher
}
},
computed: {
relativePosition() {
return `position: ${this.relative ? 'relative' : 'static'}`
}
}
}
</script>
我们在这里所做的是:
为孩子设置一个prop绝对值,当它改变时,我们观察它发出一个事件,该事件将prop的新值发送给父对象,然后我们对该事件做出反应并根据该新值更改样式(如果孩子是绝对的,则为true;否则,则为false)。 我真的不知道你在哪里处理那个道具的价值,在这个例子中我说没有必要用事件来处理它,因为我们实际上拥有我们想要在父母中做出反应的价值,但是我不是真的知道你是从哪里寄来的。
答案 1 :(得分:0)
正如大卫·韦尔登(David Weldon)在我的问题的评论中所述,在干净的编码实践中实际上不建议我尝试实现的目标(当孩子的道具为x时,使孩子组件操纵父母的风格)。他说的更好,所以我在这里粘贴他的评论:
通常,如果代码库的子单元(在此 案例组件)具有明确的关系。您想要的解决方案是 隐式关系-将组件C添加到组件的动作 P,将会改变P。想象一下,一年后,您将P转换为模态, 突然由于C的行为而中断。一个明确的解决方案是 只需添加位置:相对于P(带有注释),或添加类似 P的o容器,其中o容器是具有以下内容的可重用CSS对象类: 您的应用中可以理解的目的。
我最终要做的只是创建一个可重用的css类,并将其添加到父类中,而不是让子组件操纵父组件的样式。
.relative {
position: relative;
}
我不建议为此使用vuex状态-正如MattAft在评论中所指出的那样。