组件未在密钥更改时更新

时间:2019-10-21 15:58:45

标签: javascript vue.js vuetify.js

据我了解,向组件添加key属性将使该组件在键更改时具有响应性,但是Vuetify提供的v-navigation-drawer似乎具有没有影响。

我甚至尝试对loggedIn之类的+= 1键进行任意更改,该更改足以重新呈现组件。

这里的用例是我有一个全局导航抽屉,该抽屉应根据用户是否登录来显示上下文。

完整组件

<template>
  <v-navigation-drawer
    absolute
    right
    dark
    color="primary"
    v-if="$store.state.globalDrawer"
    v-model="$store.state.globalDrawer"
    :key="loggedIn"
  >

  <v-container class="pa-5">
    <v-layout column align-center justify-center>

      <v-avatar class="ma-4" size="60">
        <img v-if="!twitter" src="https://pbs.twimg.com/profile_images/1173674959731867648/6kzApb83_400x400.jpg" />
        <img v-else :src="twitter.profile_image_url" />
      </v-avatar>

      <h2 v-if="!twitter" class="title">StreamBeacon.tv</h2>
      <h2 v-else class="title">{{ twitter.display_name }}</h2>

      <p v-if="!twitter" class="body-2 text-center">Enhance your Going Live experience.</p>
      <p v-else class="body-2 text-center">@{{ twitter.screen_name }}</p>

      <v-chip v-if="twitch.live">
        <font-awesome-icon :icon="['fab', 'twitch']" />  
        &nbsp;Live Now
      </v-chip>
    </v-layout>
  </v-container>

    <!-- User is authenticated -->
    <v-list dense nav>
      <v-subheader>Account</v-subheader>
      <v-list-item-group 
        color="primary"
        v-if="user"
      >
        <v-list-item
          v-for="(link, i) in accountLinks"
          :key="i"
          :color="activeLinkColor"
          :to="link.target"
          @click="changeDashboardView(link.dashboardComponent)"
        >
          <v-list-item-icon :color="activeLinkColor">
            <v-icon v-text="link.icon"></v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title v-text="link.text"></v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list-item-group>

    <!-- User is NOT authenticated -->
    <v-list-item-group 
      color="primary"
      v-else
    >
        <v-list-item
          @click="$eventHub.$emit('registration')"
          :color="activeLinkColor"
        >
          <v-list-item-icon color="primary">
            <v-icon>mdi-shield-account</v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title>Sign In</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list-item-group>

      <v-subheader>Quick Links</v-subheader>
      <v-list-item-group 
        color="primary"
      >
        <v-list-item
          v-for="(link, i) in quickLinks"
          :key="i"
          :color="activeLinkColor"
        >
          <v-list-item-icon color="primary">
            <v-icon v-text="link.icon"></v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title v-text="link.text"></v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list-item-group>

    </v-list>
  </v-navigation-drawer>
</template>

<script>
export default {
  data() {
    return {
      user: false,
      twitter: false,
      twitch: false,
      loggedIn: false,
      active: this.$store.state.globalDrawer,
      activeLinkColor: "#fff",
      accountLinks: [
        {
          "icon": "mdi-shield-account",
          "dashboardComponent": null,
          "text": "My Account",
        },
        {
          "icon": "mdi-account-box-multiple",
          "dashboardComponent": "connections",
          "text": "My Connections"
        },
        {
          "icon": "mdi-credit-card",
          "dashboardComponent": "subscription",
          "text": "Subscription",
        },
        {
          "icon": "mdi-bug",
          "dashboardComponent": "support",
          "text": "Support"
        },
        {
          "icon": "mdi-logout",
          "target": "logout",
          "text": "Logout"
        }
      ],
      quickLinks: [
        {
          "icon": "mdi-gift",
          "click": "",
          "text": "Gift a Streamer"
        },
        {
          "icon": "mdi-mail",
          "click": "",
          "text": "Contact Us"
        },
        {
          "icon": "mdi-library-video",
          "click": "",
          "text": "Our Streamers"
        },
      ]
    }
  },
  methods: {
    checkIfAuthenticated() {
      if(this.$store.state.authenticatedUser != null) {
        this.user = JSON.parse(this.$store.state.authenticatedUser)
        this.loggedIn = true
        if(this.user.twitter) {
          this.twitter = this.user.twitter
        }
        if(this.user.twitch_channel) {
          this.twitch = this.user.twitch_channel
        }
      }
    },
    changeDashboardView(targetComponent) {
      if(this.$route.name != 'dashboard') {
        this.$router.replace('dashboard')
        .then(() => {
          this.$eventHub.$emit('changeDashboardComponent', targetComponent)
        })
      } else {
        this.$eventHub.$emit('changeDashboardComponent', targetComponent)
      }
    }
  },
  mounted() {
    this.checkIfAuthenticated()
  },
  watch: {
    $route: function(to, from) {
      this.loggedIn true
    }
  }
}
</script>

是否需要使key更改生效的情况还是应该起作用?我已验证loggedIn在登录时确实可以正确更改。

我的另一种理论是,由于使用v-if指令,该组件在密钥更改期间就消失了,但是,我已经揭穿了这一理论。

1 个答案:

答案 0 :(得分:1)

正如安东尼奥在上面提到的,潜在的问题是我没有为v-if指令的键和依赖项使用任何反应式数据。

如果使用上面的代码查找,登录后user仍然为false,这是经过身份验证的用户的上下文的值依赖项。在mounted()钩上并更改路由后,我会寻找它们并进行更新,但这是一种骇人听闻的方法。

登录后:

enter image description here

解决方案是使用Vuex getter使用计算属性,该属性将触发组件上的渲染。

enter image description here

话虽如此,我对上面代码的更改如下(可能会更改,因为这与我需要解决的当前错误相反,但请使其与原始错误尽可能接近,以便于阅读差异)。

  computed: {
    loggedIn: {
      get() {
        return this.$store.state.isLoggedIn
      },
      set(value) {
        this.$store.commit('updateLoggedInState', value)
      }
    },
    user: {
      get() {
        return JSON.parse(this.$store.state.authenticatedUser)
      }
    }
  }

立即登录 enter image description here

简单的解决方案,是一天的一堂好课!谢谢安东尼奥的指导。