用于全局功能的 Vue 2 Mixins

Vue 2 Mixins for global functionalities

我想在应用程序和路由中为全局身份验证实现一个简单的 auth mixin。 auth mixin 有一个 loggedIn 数据,它是 True 或 False 以及两个用于登录和注销的函数。整个应用程序基于 vue router webpack 模板。问题是 loggedIn 状态不会被保存。因此,当我转到 Login.vue 并登录时,loggedIn 将设置为 true,但是当我再次转到 Login.vue 组件时,checkStatus 函数会将 loggedIn 记录为 false 再一次。

我怎么能

这是我的混音:

Auth.js

export default {
  data() {
    return {
      loggedIn: false
    }
  },
  methods: {
    logIn(user,password) {
      return new Promise((resolve, reject) => {
        console.log("Logging in ", user, password);
        this.loggedIn = true;
        resolve()
      })
    },
    logOut(){
      return new Promis ((resolve, reject) => {
        console.log("Logging out");
        this.loggedIn = false;
        resolve();
      })
    }
  }
};

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import Utils from "./mixins/Utils"
import Auth from "./mixins/Auth"

// Load mixins
Vue.mixin(Auth);
Vue.mixin(Utils);

// This part redirects to login page when authentication is needed
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth) && this.loggedIn) {
    next({ path: '/login', query: { redirect: to.fullPath }});
  } else {
    next();
  }
});

Login.vue

<template>
  <div>
    <form class="form-signin">
      <h1 class="mb-3">Please sign in</h1>
      <label for="inputEmail" class="sr-only">Email address</label>
      <input type="email" id="inputEmail" v-model="email" class="form-control" placeholder="Email address" required autofocus>
      <label for="inputPassword" class="sr-only">Password</label>
      <input type="password" id="inputPassword" class="form-control" placeholder="Password" required v-model="password">
      <div class="checkbox mb-3">
        <label>
          <input type="checkbox" value="remember-me"> Remember me
        </label>
      </div>
      <button class="btn btn-lg btn-primary btn-block" type="submit" v-on:click="checkCredentials">Sign in</button>
    </form>
    <div class="mb-3" style="text-align: center">
      <label>
        <router-link to="/signup">Not registerd yet? Sign up!</router-link>
      </label>
    </div>
    <notifications position="bottom center" group="notifications" />
  </div>
</template>


<script>

  export default {
    name: 'Login',
    methods: {
      checkCredentials(event) {
        event.preventDefault();
        if (this.email.length <= 0 || !this.email) {
          this.notify("Enter email", "warn")
          return;
        }
        if (this.password.length <= 0 || !this.password) {
          this.notify("Enter password", "warn");
          return;
        }
        this.performLogin(this.email, this.password);
      },
      performLogin(mail, password) {
        let x = this;
        this.logIn(mail, password)
          .then(function (result) {
            x.notify("Logged in as " + mail, "success");
            if (x.loggedIn) {
              console.log("[LOG] redirecting");
              x.$router.push(x.$route.query.redirect || '/');
            }
          })
          .catch(function (error) {
            document.cookie = "Test";
            x.notify("Error loggin in (" + error + ")", "error");
          })
      },
      checkStatus() {
        this.$log.info("Checking status", this.loggedIn)
        if (this.loggedIn) {
          this.$router.push(this.$route.query.redirect || "/");
        }
      }
    },
    data() {
      return {
        email: "",
        password: ""
      }
    },
    created() {
      this.checkStatus()
    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .form-signin {
    width: 100%;
    max-width: 330px;
    padding: 15px;
    margin: auto;
  }

  .form-signin .checkbox {
    font-weight: 400;
  }

  .form-signin .form-control {
    position: relative;
    box-sizing: border-box;
    height: auto;
    padding: 10px;
    font-size: 16px;
  }

  .form-signin .form-control:focus {
    z-index: 2;
  }

  .form-signin input[type="email"] {
    margin-bottom: -1px;
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;
  }

  .form-signin input[type="password"] {
    margin-bottom: 10px;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
  }
</style>

The problem is that the loggedIn state will not be saved.

确切地说,Mixins 并不是为了管理它们应该用于 functions/methods 的状态,需要在您的组件中重复使用,要维护您需要状态管理系统和 Vue 的状态提供一个,叫做Vuex.

使用 Vuex 你可以定义一个初始状态,在你的情况下用户是否已经登录,我建议你通过 Vuex Docs 一次

这是一个简短的示例,说明它将如何解决您的问题,

const store = new Vuex.Store({
 state: {
  loggedIn: false
 },
 mutations: {
  logInUser (state) {
  state.loggedIn = true
 }
}
})

/* Pass the store to your Vue App */
const app = new Vue({
  el: '#app',

  // this will inject the store instance to all child components.
  store,
  components: { App },
  ..........

现在,此状态将在您的整个组件中可用,并且不会更改,除非您从某处手动提交更改。

Login.vue

 this.$store.commit('logInUser', true)

someOtherComp.vue

console.log(this.$store.state.loggedIn) // true