如何更改路由器在Vue中状态更改时呈现的组件?

Posted

技术标签:

【中文标题】如何更改路由器在Vue中状态更改时呈现的组件?【英文标题】:How to change component rendered by router on state change in Vue? 【发布时间】:2021-04-11 18:36:06 【问题描述】:

我在 Vue 中设置了一个 Vuex 商店和路由器。根据此存储中的某个状态,我希望路由器为同一路径呈现不同的组件。以下是我的尝试。

在我的路由器中,我包含一个条件,即“如果用户已登录,则返回 Home,否则返回 Login”。

在我的Login 组件中,当用户成功登录时,我将我的loggedIn 状态(在Vuex 商店中)的值更改为true。我已经测试并且可以看到这个状态正在更新,但 Home 组件不会在此状态更改时呈现 - 它仍为 Login


Login.vue

<template>
  <div className = "container">
    <div className = "sign-in">
        <div className = "inner-sign-in">
            <div className = "title-outer">
                <div className = "title-inner">
                    <h1 className = "reg-title title">Tweeter</h1>
                    <span className = "slogan">Twitter, but not as good.</span>
                </div>
            </div>
            <div className = "form-outer">
                <form className = "sign-in-form" v-on:submit="submitForm">
                    <input @input="updateUsername" type="text" id="username" name="username" placeholder="Username" required/><br/>
                    <input @input="updatePassword" type="password" id="password" name="password" placeholder="Password" required/><br/>
                    <input type="submit" value="Login"/>
                    <div className = "wrongCreds">Sorry, incorrect username or password.</div>
                </form>
                <a className = "register-but" to="/register">Create an Account</a>
                <span className = "guestButton">Continue as Guest &gt;</span>
            </div>
        </div>
    </div>
  </div>
</template>

<script>
  import loginService from '../services/login.js'
  export default 
    name: 'Login',
    computed: 
      loggedIn() 
        return this.$store.getters.loggedIn
      
    ,
    methods: 
      updateUsername: function(event) 
        this.$store.commit('change', 
          name: "username",
          value: event.target.value
        )
      ,
      updatePassword: function(event) 
        this.$store.commit('change', 
          name: "password",
          value: event.target.value
        )
      ,
      async submitForm(e) 
        e.preventDefault()
        await loginService.login(this.$store.getters.username, this.$store.getters.password)
          .then(data => 
            console.log(data)
            this.$store.commit('change', 
              name: "loggedIn",
              value: true
            )
            console.log(this.$store.getters.loggedIn)
          )
          .catch(error => 
            console.log(error)
          )
      
    
  
</script>

router.js

import  createRouter, createWebHistory  from 'vue-router'
import store from "../store/store"
import Home from "../Home.vue"
import Login from "../Login.vue"

const router = createRouter(
    history: createWebHistory(),
    routes: [
         path: '/', component: function () 
            console.log(store.getters.loggedIn)
            if(store.getters.loggedIn) 
                return Home
            
            else 
                return Login
            
        
    ]
)

export default router

store.js

import  createStore  from 'vuex';

const store = createStore(
    state: 
        username: '',
        password: '',
        loggedIn: false
    ,
    mutations: 
        change(state, theChange) 
            state[theChange.name] = theChange.value
        ,
        arrayItemChange(state, theChange) 
            state[theChange.name][theChange.index] = theChange.value
        
    ,
    getters: 
        username: state => state.username,
        password: state => state.password,
        loggedIn: state => state.loggedIn
    
)

export default store

【问题讨论】:

【参考方案1】:

最好的做法是使用Navigation Guards。

现在,为了加快速度,您需要设置 2 个导航守卫来检查用户是否经过身份验证。

index.js(路由器文件)

const ifNotAuthenticated = (to, from, next) => 
    if (!store.getters.loggedIn) 
        next();
        return;
    
    next("/");
;

const ifAuthenticated = (to, from, next) => 
    if (store.getters.loggedIn) 
        next();
        return;
    
    next("/login");
;

const routes =[
    
        path: "/home",
        name: "Home",
        component: Home,
        beforeEnter: ifAuthenticated,
      ,
    
        path: "/login",
        name: "Login",
        component: Login,
        beforeEnter: ifNotAuthenticated,
      
]

beforeEnter 这里是了解经过身份验证的用户是否应该进入下一页或登录的关键。

【讨论】:

【参考方案2】:

将路由配置为简单地具有 /home/login(不要在此处创建逻辑)并在您的模板或 Vuex 中处理登录:router.push() 到正确的路径,以匹配您的路由。

【讨论】:

【参考方案3】:

解决此问题的方法之一是拥有一个包含 Login 和 Home 组件的父组件,然后使用 Dynamic 组件根据状态进行切换。

你可以查看Vue文档here

【讨论】:

以上是关于如何更改路由器在Vue中状态更改时呈现的组件?的主要内容,如果未能解决你的问题,请参考以下文章

导航栏不会根据路由条件在 app.js 中呈现。路由更改时不会触发 Useeffect

为啥当我更改路由时组件不呈现?

如何调试反应路由器未在 url 更改时加载组件

更改路由时jQuery在vue组件中不起作用

Vue Keep-Alive - 组件应用程序标头在路由更改期间不会保持活动状态

Angular2路由-路由更改时保持组件状态[重复]