[英]Updating CSS classes in on div in Vue3 component, depending on props, does not work (Missing reactivity?)
我在 Github ( https://github.com/imanmalekian31/vue-bottom-navigation ) 上找到了一个好看的 vue 底部导航栏。
遗憾的是,它不适用于 Vue3、Typescript 和脚本设置语法。
我重写了组件并让它运行并显示在我的应用程序中。
问题是,按钮目前没有反应。 当单击运行时,元素上的 css 类不会更新。
我最好的猜测是,localOptions 和 button
<div v-for="(button, index) in localOptions" :key="`grow-button-${index}`"></div>
需要反应,他们可能不会由于脚本设置的更改。
非常感谢有关如何修复此代码的任何帮助。
更新:我确实用let localOptions = reactive(props.options.slice())
替换了let localOptions: any[] = reactive([])
,这似乎已经成功了。 这些按钮正在工作并且更新得很好。
现在出现的问题是,计算属性似乎并没有在每次组件重新渲染时运行。 因此按钮不会改变宽度或颜色。
组件文件:
<template>
<div class="gr-btn-container-foreground" :style="cssVariables">
<div v-for="(button, index) in localOptions" :key="`grow-button-${index}`" :class="[
'gr-btn-container',
{ 'gr-btn-container-active': button.selected },
]" @click="handleButtonClick(button, index)">
<div :class="['gr-btn-item', { 'gr-btn-item-active': button.selected }]">
<div :class="['gr-btn-icon', { 'gr-btn-icon-active': button.selected }]">
<slot name="icon" :props="button">
<i :class="`${button.icon}`" />
</slot>
</div>
<div class="gr-btn-title">
<span class="gr-hidden-title">
<slot name="title" :props="button">{{ button.title }}</slot>
</span>
<span :class="[
'gr-animated-title',
{ 'gr-animated-title-active': button.selected },
]">
<slot name="title" :props="button">{{ button.title }}</slot>
</span>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed, reactive } from "vue";
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const button = reactive({})
const model = {
prop: "value",
event: "update",
}
const props = defineProps({
value: {
default: null,
},
options: {
type: Array,
default: () => [],
},
color: {
type: String,
default: "#74cbbb",
},
replaceRoute: {
type: Boolean,
default: false,
},
})
const emit = defineEmits<{
(e: 'update', value: string): void
}>()
let prevSelected = null
let currSelected = null
let localOptions: any[] = reactive([])
const cssVariables = computed(() => {
const activeTitle = (localOptions[currSelected] || {}).title;
let activeWidth = 95;
if (activeTitle && activeTitle.length * 15 > 110) {
activeWidth = 95 + (activeTitle.length * 15 - 110) / 2;
}
const mainColor =
(localOptions[currSelected] || {}).color || props.color;
const styles = {
"--color": mainColor,
"--color-background": mainColor + "30",
"--active-width": `${activeWidth}px`,
};
return styles;
})
localOptions = props.options.slice();
let index = localOptions.findIndex(
(item) =>
item.id == props.value ||
(item.path || {}).name == (route || {}).name
);
if (index > -1) {
currSelected = index;
prevSelected = index;
localOptions[index] = { ...localOptions[index], selected: true }
}
function handleButtonClick(button: any, index: number) {
console.log("Button: " + button + " Index: " + index);
currSelected = index;
if (prevSelected !== null) {
localOptions[prevSelected].selected = false;
}
localOptions[index] = { ...localOptions[index], selected: true }
prevSelected = currSelected;
updateValue(button);
}
function updateValue(button) {
console.log("Update value: " + button.id + " with Path: " + button.path)
emit("update", button.id);
if (button.path && Object.keys(button.path).length) {
router[!props.replaceRoute ? "push" : "replace"](
button.path
).catch(() => { console.log("Error updating path") });
}
}
</script>
<style scoped>
.gr-btn-container-foreground {
position: fixed;
direction: ltr;
display: flex;
align-items: center;
bottom: 0;
width: 100%;
z-index: 2147483647;
height: 64px;
background: #fff;
box-shadow: 0 0 5px 0 #eee;
}
.gr-btn-container {
display: flex;
align-items: center;
justify-content: center;
height: 45px;
flex-grow: 1;
transition: all 0.3s;
}
@media (min-width: 576px) {
.gr-btn-container {
cursor: pointer;
}
}
.gr-btn-container-active {
background-color: var(--color-background);
border-radius: 100px;
}
.gr-btn-item {
display: flex;
position: relative;
overflow: hidden;
width: 24px;
transition: all 0.3s ease;
color: #0000008a;
}
.gr-btn-item-active {
width: var(--active-width);
}
.gr-btn-icon {
font-size: 20px;
transition: all 0.3s ease;
margin: 0px !important;
}
.gr-btn-icon-active {
color: var(--color);
}
.gr-btn-title {
position: relative;
color: var(--color);
padding: 0px 5px;
margin-left: 10px;
display: flex;
justify-content: center;
align-items: center;
}
.gr-hidden-title {
visibility: hidden;
}
.gr-animated-title {
color: var(--color);
position: absolute;
left: 5px;
bottom: -15px;
transition: bottom 0.4s ease 0.1s;
}
.gr-animated-title-active {
bottom: 2px;
}
</style>
currSelected
不是反应变量 (ref)。 据我所知,这就是为什么你的cssVariables
计算不重新计算的原因 - 它错过了currSelected
的反应依赖
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.