Voici une implémentation simplifiée d'une fonctionnalité de connexion, inspirée mais non strictement conforme au modèle de vue-element-admin.
Fonctionnalité de connexion
La démarche de réalisation est la suivante :
- Configurer dans le routeur un accès au layout de base (BasicLayout) ainsi qu'une page 404.
- Lorsqu'un utilisateur clique sur le bouton de connexion, les paramètres sont envoyés au serveur.
- Utiliser Vuex pour gérer la soumission des paramètres.
- Dans Vuex, utiliser une requête (basée sur une instance axios ancapsulée) pour simuler un appel mock, retournant un token et des rôles (admin, guest, user).
- En cas de succès, rediriger vers la page du layout de base ; en cas d'échec, afficher une page 404.
- Configurer le serveur de développement (devServer) et le dossier de mock.
Configuration du routeur
import Vue from "vue";
import VueRouter from "vue-router";
import NotFound from "@/views/404.vue";
// Réécriture de la méthode push du routeur pour éviter les erreurs de navigation en double.
const routerPushOriginal = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return routerPushOriginal.call(this, location).catch(err => err);
};
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: () =>
import(/* webpackChunkName: "layout" */ "@/layouts/BasicLayout.vue")
},
{
path: "/about",
name: "About",
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
},
{
path: "/user",
component: { render: h => h("router-view") },
children: [
{ path: "/user", redirect: "/user/login" },
{
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "@/views/user/Login.vue")
},
{
path: "/user/register",
name: "register",
component: () =>
import(/* webpackChunkName: "user" */ "@/views/user/Register.vue")
}
]
},
{ path: "*", name: "404", component: NotFound }
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
Configuration des méthodes et des paramètres dans Vuex
Créer un dossier modules dans le répertoire store, puis ajouter un fichier pour le store utilisateur, par exemple user.js.
Définir la méthode de connexion :
import router from "@/router";
import request from "@/utils/request";
const state = {
currentUser: {
name: "",
token: "",
password: "",
roles: []
}
};
const actions = {
handleLogin({ commit }, credentials) {
const { username, password } = credentials;
request({
url: "/api/user/login",
method: "post",
data: { name: username, password }
}).then(response => {
const userData = response.data.userInfo;
if (userData.token !== "error") {
commit("SET_USER_ROLES", userData.roles);
commit("SET_USER_NAME", userData.name);
commit("SET_USER_TOKEN", userData.token);
router.push("/");
} else {
console.error("Échec de l'authentification:", userData.token);
router.push("/404");
}
});
}
};
const mutations = {
SET_USER_TOKEN(state, newToken) {
state.currentUser.token = newToken;
},
SET_USER_NAME(state, newName) {
state.currentUser.name = newName;
},
SET_USER_ROLES(state, newRoles) {
state.currentUser.roles = newRoles;
}
};
export default {
namespaced: true,
state,
mutations,
actions
};
Enregistrer le module utilisateur dans le fichier principal store/index.js :
import Vue from "vue";
import Vuex from "vuex";
import userModule from "./modules/user";
Vue.use(Vuex);
export default new Vuex.Store({
modules: { user: userModule }
});
Encapsulation d'axios
Installer axios :
yarn add axios
Créer une fonction d'encapsulation pour les requêtes :
import axios from "axios";
function sendRequest(config) {
return axios(config)
.then(response => {
return response;
})
.catch(error => {
if (error.response) {
const { status, statusText } = error.response;
console.error(`Erreur HTTP: ${status} - ${statusText}`);
}
return Promise.reject(error);
});
}
export default sendRequest;
Configuration du Mock
Configurer le serveur de développement pour intercepter les requêtes et servir des données simulées. Dans vue.config.js, ajouter le parser de corps (body-parser) :
const bodyParser = require("body-parser");
Configurer le devServer avec un proxy et un intercepteur :
devServer: {
before(app) {
app.use(bodyParser.json());
},
proxy: {
"/api": {
target: "http://localhost:63000",
bypass: function(req, res) {
if (req.headers.accept.indexOf("html") !== -1) {
return "/index.html";
} else if (process.env.MOCK !== "none") {
const resourcePath = req.path
.split("/api/")[1]
.split("/")
.join("_");
const mockModule = require(`./mock/${resourcePath}`);
const responseData = mockModule(req);
// Suppression du cache pour refléter les modifications en temps réel
delete require.cache[require.resolve(`./mock/${resourcePath}`)];
return res.send(responseData);
}
}
}
}
},
Données de Mock
Créer un dossier mock à la racine du projet. Selon la règle de dénomination du proxy, le fichier pour la connexion s'appellera user_login.js.
function mockLogin(req) {
const method = req.method.toUpperCase();
const { name, password } = req.body;
let token = null;
let roles = [];
let result = null;
const userDatabase = {
admin: { password: "111111", token: "TOKEN_ADMIN_123", roles: ["admin"] },
user: { password: "222222", token: "TOKEN_USER_456", roles: ["user"] },
guest: { password: "333333", token: "TOKEN_GUEST_789", roles: ["guest"] }
};
if (method === "POST") {
const userRecord = userDatabase[name];
if (userRecord && userRecord.password === password) {
token = userRecord.token;
roles = userRecord.roles;
} else {
token = "error";
}
result = {
message: "HTTP OK",
userInfo: { token, roles, name }
};
}
return result;
}
module.exports = mockLogin;
Interception des paramètres
Si le devServer ne peut pas intercepter les corps des requêtes POST, l'ajout de bodyParser dans la section before (comme montré ci-dessus) est nécessaire pour rendre les données de req.body disponibles.