[英]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.