ログインページ
1. 便宜上、最初に element-ui の使用をグローバル インポートに変更します。main.js ファイルを次のように変更します。
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
//这个是局部引入,前面的文章有讲过
// import '../plugins/element'
import 'font-awesome/css/font-awesome.min.css'
import axios from 'axios'
import router from './router/index'
Vue.config.productionTip = false
Vue.prototype.axios = axios
Vue.use(ElementUI)
new Vue({
router,
render: h => h(App),
}).$mount('#app')
2. ランディング ページを作成します。
2.1. components フォルダーの下に新しい Login.vue を作成します
2.2. element-ui の公式 Web サイトから必要なコンポーネントを見つけます: +
2.3. コードの変更後 (データおよびフォーム バインディングを含む) 統合:
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form
:model="loginForm"
ref="loginForm"
label-width="100px"
>
<el-form-item label="用户名" prop="username">
<el-input
v-model="loginForm.username"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('loginForm')"
>登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
data() {
return{
loginForm:{
username:'',
password:''
}
}
},
};
</script>
<style lang="scss">
.login{
width: 100%;
height: 100%;
position:absolute;
background: #88b2dc;
.box-card{
width: 450px;
margin: 160px auto;
.el-card__header{
font-size: 34px;
}
.el-button{
width: 30%;
}
}
}
</style>
3. ルートを変更します。プロジェクトを開始し (リダイレクトを使用)、http://localhost/login と入力します。入力したページはすべてログイン ページです。
import Vue from 'vue'
import Router from 'vue-router'
//import Home from '../components/Home.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
// component: Home
redirect:'/login',
component: () => import('@/components/Login') //路由懒加载
//component: resolve => require(['@/components/Home'], resolve) //异步加载
},
{
path: '/login',
name:'Login',
component: () => import('@/components/Login') //路由懒加载
//component: resolve => require(['@/components/Home'], resolve) //异步加载
},
{
path: '/home',
// component: Home
component: () => import('@/components/Home') //路由懒加载
//component: resolve => require(['@/components/Home'], resolve) //异步加载
}
],
mode: 'history'
})
操作結果:
4. ログイン認証
4.1 小規模プロジェクトや単純な検証ルールに適した単純なバージョン、実装: 検証ルールを html に直接記述
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form :model="loginForm" ref="loginForm" label-width="100px">
<el-form-item
label="用户名"
prop="username"
:rules="[
{ required: true, message: '请输入用户名', trigger: 'blur' },
{
min: 4,
max: 10,
message: '长度在4-10位字符之间',
trigger: 'blur',
},
]"
>
<el-input v-model="loginForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item
label="密码"
prop="password"
:rules="[
{ required: true, message: '请输入密码', trigger: 'blur' },
{
min: 6,
max: 12,
message: '长度在6-12位字符之间',
trigger: 'blur',
},
]"
>
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('loginForm')"
>登录</el-button
>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
入力ボックスがフォーカスを失うと、フォームの検証が自動的に実行されます
4.2 ログイン認証の高度なバージョン
①フォームにルールをバインドし、Login.vueページのデータに検証ルールを直接記述し、記述方法はelement-uiのフォームformを参照
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form
:model="loginForm"
ref="loginForm"
label-width="100px"
:rules="rules"
>
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
export default {
data() {
// rule 是校验规则,value是input用户输入的值,callback是回调函数 参考element-ui的api文档
const validateName = (rule, value, callback) => {
// 请输入4-10位昵称
let reg = /(^[a-zA-Z0-9]{4,10}$)/;
if (value === "") {
callback(new Error("请输入用户名"));
} else if (!reg.test(value)) {
callback(new Error("请输入4-10位用户名"));
} else {
callback();
}
};
const validatePass = (rule, value, callback) => {
// 6-12位密码需要包含大小写字母和数字以及特殊符号
let pass =
/^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
if (value === "") {
callback(new Error("请输入密码"));
} else if (!pass.test(value)) {
callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
} else {
callback();
}
};
return {
loginForm: {
username: "",
password: "",
},
rules: {
username: [{ validator: validateName, trigger: "blur" }],
password: [{ validator: validatePass, trigger: "blur" }],
},
};
},
methods: {
login(loginForm) {
this.$refs[loginForm].validate((valid) => {
if (valid) {
console.log(this.loginForm);
} else {
console.log(this.loginForm);
}
});
},
resetForm(loginForm) {
this.$refs[loginForm].resetFields();
},
},
};
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
position: absolute;
background: #88b2dc;
.box-card {
width: 450px;
margin: 160px auto;
.el-card__header {
font-size: 34px;
}
.el-button {
width: 30%;
}
}
}
</style>
効果:
ヒント: 書き込み検証ルール プラグインを使用する
使用するには:f1を押します(私のラップトップはFn + f1を押す必要があります)
② フォームにルールをバインドし、検証ルールをカプセル化した後、Login.vue ページで検証ルールをインポートします (推奨)
src の下に新しい utlis フォルダーを作成し、新しい validate.js ファイルを作成して、Login.vue ページのデータの検証ルールを次のように変更します。
// 用户名匹配
export function nameRule(rule, value, callback) {
// 请输入4-10位昵称
let reg = /(^[a-zA-Z0-9]{4,10}$)/;
if (value === "") {
callback(new Error("请输入用户名"));
} else if (!reg.test(value)) {
callback(new Error("请输入4-10位用户名"));
} else {
callback();
}
}
// 密码正则匹配
export function passRule(rule, value, callback) {
// 6-12位密码需要包含大小写字母和数字以及特殊符号
let pass = /^\S*(?=\S{6,12})(?=\S*\d)(?=\S*[A-Z])(?=\S*[a-z])(?=\S*[!@#$%^&*? ])\S*$/;
if (value === "") {
callback(new Error("请输入密码"));
} else if (!pass.test(value)) {
callback(new Error("6-12位密码需要包含大小写字母和数字及特殊符号"));
} else {
callback();
}
}
Login.vue ページで、次のように変更します。
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form
:model="loginForm"
ref="loginForm"
label-width="100px"
:rules="rules"
>
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { nameRule, passRule } from '../utils/validate.js'
export default {
data() {
return {
loginForm: {
username: "",
password: "",
},
rules: {
username: [{ validator: nameRule, trigger: "blur" }],
password: [{ validator: passRule, trigger: "blur" }],
},
};
},
methods: {
login(loginForm) {
this.$refs[loginForm].validate((valid) => {
if (valid) {
console.log(this.loginForm);
this.axios
.post("http://1.116.64.64:5004/api2/login", this.loginForm)
.then((res) => {
console.log(res);
if (res.data.status === 200) {
localStorage.setItem("username", res.data.username);
this.$message({ message: res.data.message, type: "success" });
this.$router.push("/home");
}
})
.catch((err) => {
console.error(err);
});
} else {
console.log(this.loginForm);
}
});
},
resetForm(loginForm) {
this.$refs[loginForm].resetFields();
},
},
};
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
position: absolute;
background: #88b2dc;
.box-card {
width: 450px;
margin: 160px auto;
.el-card__header {
font-size: 34px;
}
.el-button {
width: 30%;
}
}
}
</style>
効果:
5. ログインページがバックエンドに接続します
最初
まず、モックを使用して、ネットワーク リクエストのバックエンド インターフェイスをシミュレートする準備をします。
① vscode ターミナルに入力し、ctrl+c で実行中のプロジェクトを終了し、モック プラグインをダウンロードして入力します。
npm i @shymean/mock-server -g
② プラグインをインストールしたら、ディスクの任意の場所にフォルダを作成し、mock という名前を付け、mock ファイル内に空の mock.js ファイルを作成します。
ターミナルでモック フォルダーに入り、コマンド mock を入力し、ローカル モック サーバーを起動します。デフォルトのポートは 7654 です
モック>モックサーバーは7654でリッスンします
操作手順は次のとおりです。
mock.js ファイルを開き、次のようにテスト データを自分で記述します。
//登录接口
Mock.mock(/login/, {
code: 200,
data: {
access_token: "748_bef_246_test",
expires_in: 7200,
}
})
//用户信息
Mock.mock(/userInfo/, {
code: 200,
user: {
userName:'admin',
password:'123456',
role:'admim',
}
})
二番目
自分自身または他の誰かが作成したバックエンド インターフェイスを見つけます。Bilibili にはたくさんあります。見つけて直接使用してください。
カプセル化トークン
次の内容で、utils フォルダーの下に新しい setToken.js ファイルを作成します。
export function setToken(tokenKey, token) {
return localStorage.setItem(tokenKey, token)
}
export function getToken(tokenKey) {
return localStorage.getItem(tokenKey)
}
export function removeToken(tokenKey) {
return localStorage.removeItem(tokenKey)
}
Login.vue でインポートして使用する
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form
:model="loginForm"
ref="loginForm"
label-width="100px"
:rules="rules"
>
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { nameRule, passRule } from '../utils/validate.js'
import { setToken } from '@/utils/setToken.js'
export default {
data() {
return {
loginForm: {
username: "",
password: "",
},
rules: {
username: [{ validator: nameRule, trigger: "blur" }],
password: [{ validator: passRule, trigger: "blur" }],
},
};
},
methods: {
login(loginForm) {
this.$refs[loginForm].validate((valid) => {
if (valid) {
console.log(this.loginForm);
this.axios
.post("http://1.116.64.64:5004/api2/login", this.loginForm)
.then((res) => {
console.log(res);
if (res.data.status === 200) {
// localStorage.setItem("username", res.data.username);
setToken("username", res.data.username);
this.$message({ message: res.data.message, type: "success" });
this.$router.push("/home");
}
})
.catch((err) => {
console.error(err);
});
} else {
console.log(this.loginForm);
}
});
},
resetForm(loginForm) {
this.$refs[loginForm].resetFields();
},
},
};
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
position: absolute;
background: #88b2dc;
.box-card {
width: 450px;
margin: 160px auto;
.el-card__header {
font-size: 34px;
}
.el-button {
width: 30%;
}
}
}
</style>
バックエンドのログイン インターフェイスに接続し、axios を 2 回カプセル化します
プロジェクト プロキシを設定し、vue.config.js ファイルを次のように変更します。
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
open: true,
host: 'localhost',
proxy: {
'/api': {
target: 'http://1.116.64.64:5004/api2/',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
})
axios をカプセル化するために、プロジェクトのルート ディレクトリに新しい service.js ファイルを作成します。
import axios from 'axios'
import { getToken } from '@/utils/setToken.js'
import { Message } from 'element-ui'
const service = axios.create({
baseURL: '/api', // baseURL会自动加在请求地址上
timeout: 3000
})
// 添加请求拦截器
service.interceptors.request.use((config) => {
// 在请求之前做些什么(获取并设置token)
config.headers['token'] = getToken('token')
return config
}, (error) => {
return Promise.reject(error)
})
// 添加响应拦截器
service.interceptors.response.use((response) => {
// 对响应数据做些什么
let { status, message } = response.data
if(status !== 200) {
Message({message: message || 'error', type: 'warning'})
}
return response
}, (error) => {
return Promise.reject(error)
})
export default service
2 番目のパッケージを使用する axios は引き続きグローバル インポート メソッドを採用し、main.js ファイルは次のように変更されます。
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
// import '../plugins/element'
import 'font-awesome/css/font-awesome.min.css'
// import axios from 'axios'
import service from '../service'
import router from './router/index'
//或者这样导入:会自动找到index文件
//import router from './router'
Vue.config.productionTip = false
// Vue.prototype.axios = axios
Vue.prototype.service = service
Vue.use(ElementUI)
new Vue({
router,
render: h => h(App),
}).$mount('#app')
Login.vue ページを変更し、インポートされた setToken ファイルをコメントアウトします。
<template>
<div class="login">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>疫起健康后台管理系统</span>
</div>
<el-form
:model="loginForm"
ref="loginForm"
label-width="100px"
:rules="rules"
>
<el-form-item label="用户名" prop="username">
<el-input v-model="loginForm.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input
type="password"
v-model="loginForm.password"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="login('loginForm')">登录</el-button>
<el-button @click="resetForm('loginForm')">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script>
import { nameRule, passRule } from '../utils/validate.js'
// import { setToken } from '@/utils/setToken.js'
export default {
data() {
return {
loginForm: {
username: "",
password: "",
},
rules: {
username: [{ validator: nameRule, trigger: "blur" }],
password: [{ validator: passRule, trigger: "blur" }],
},
};
},
methods: {
login(loginForm) {
this.$refs[loginForm].validate((valid) => {
if (valid) {
console.log(this.loginForm);
this.service.post('/login',this.loginForm)
.then((res) => {
console.log(res.data)
})
} else {
console.log(this.loginForm);
}
});
},
resetForm(loginForm) {
this.$refs[loginForm].resetFields();
},
},
};
</script>
<style lang="scss">
.login {
width: 100%;
height: 100%;
position: absolute;
background: #88b2dc;
.box-card {
width: 450px;
margin: 160px auto;
.el-card__header {
font-size: 34px;
}
.el-button {
width: 30%;
}
}
}
</style>
ctrl+c を押して現在実行中のプロジェクトを閉じ、新しいターミナルを作成して次のように入力します: npm run serve、vue.config.js ファイルを変更した後、構成を有効にするためにプロジェクトを再起動する必要があります。その後、インターフェイス テストが実行されます。それ以外の場合、エラーは次のように報告されます: アクセスはまだ同じです localhost:8080 ポートです
サービスを再起動しても意味がない場合は、文法を 1 つずつ確認してください。スペルが間違っているか、欠落しているかどうかを確認してください。デバッグ プロセス中に次のことがわかりました。
Axiosパッケージ分析(実際には、より完璧になる可能性があります。axiosによって送信されたデータはオブジェクトにすることはできず、文字列の形式でのみ可能であるため、統一されたツールクラスを使用してaxiosによって送信されたデータを処理できます;など、返ってきたリクエスト):
試験結果:
次に、Kangkang はインターフェイスによって返されるデータについて考えます。トークン以外に、他に保存する必要があるもの === "username ===" ログインが成功し、システムのホームページに入ると、ユーザー名を表示する必要があります。 , so: modify Login. vue ページのログイン方法は次のとおりです。
login(loginForm) {
this.$refs[loginForm].validate((valid) => {
if (valid) {
console.log(this.loginForm);
this.service.post('/login',this.loginForm)
.then((res) => {
if (res.data.status === 200) {
setToken('username', res.data.username)
setToken('token', res.data.token)
this.$message({message: res.data.message, type: 'success'})
this.$router.push('/home')
}
})
} else {
console.log(this.loginForm);
}
});
},
このステップを実行した後、コードに問題がないことがわかりましたが、その後のプロジェクトの編成と保守、管理インターフェースおよびメソッドを容易にするために、∴ login メソッドを呼び出し用の API に再パッケージ化できます。
src の下に、新しい api フォルダーを作成し、新しい api.js ファイルを作成します。
// 把对应的接口请求封装成api来调用
import service from '../service.js'
// 登录接口
export function login(data) {
return service({
method: 'post',
url: '/login',
data
})
}
Login.vue ページで使用します。
404ページ
プロジェクトで静的リソースを準備します。
コンポーネントの下に新しい NotFound.vue を作成します
<template>
<div class="notfound">
<div class="wrapper">
<div class="big">页面不见了!</div>
<div>首页瞧瞧,点击<router-link to="/">这里</router-link>进入首页.</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {};
},
};
</script>
<style>
.notfound {
height: 100%;
background-image: url('../assets/img/astronauta.jpg'), url('../assets/img/stars404.png');
background-position: right top, center center;
background-repeat: no-repeat, repeat;
background-size: cover, auto;
}
.notfound .wrapper {
position: absolute;
top: 60%;
right: 2%;
color: #fff;
width: 635px;
font-size: 19px;
line-height: 29px;
-webkit-font-smoothing: antialiased;
padding: 20px;
font-family: 'Source Sans Pro', sans-serif;
}
.notfound .wrapper .big {
font-size: 74px;
font-weight: 700;
line-height: 68px;
margin-bottom: 48px;
}
.notfound .wrapper a {
color: #ffcc00;
text-decoration: none;
font-weight: 700;
cursor: pointer;
}
@media only screen and (max-width: 666px) {
.notfound .wrapper {
left: auto;
right: 0;
width: 100%;
max-width: 450px;
top: 35%;
}
.notfound .wrapper .big {
font-size: 42px;
line-height: 50px;
margin-bottom: 15px;
}
}
</style>
ルーティングを構成する
効果:
分析: