簡體   English   中英

根據道具,更新 Vue3 組件中 div 中的 CSS 類不起作用(缺少反應性?)

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM