プロジェクトのフロントエンド学習ノート ディレクトリ
B ステーション クラウド E オフィス Vue+SpringBoot フロントエンドとバックエンド分離プロジェクト - vue.js プロジェクトを構築
B ステーション クラウド E オフィス Vue+SpringBoot フロントエンドとバックエンドの分離プロジェクト - フロントエンドはメニュー ディレクトリを動的に取得します
プロジェクトのバックエンド研究ノートのディレクトリ
B ステーション クラウド E オフィス Vue+SpringBoot フロントエンドとバックエンドの分離プロジェクト - バックグラウンド プロジェクトを構築するための MVC 3 層アーキテクチャ
プロジェクトの説明
プロジェクトの背景: 疫病の影響を受け、多くの企業がオンライン オフィスからオフライン オフィスに切り替えました。オンラインで働く人の増加に伴い、ワークフローの自動化、企業のオフィスコストの削減、グリーンオフィスの実現、オフィス効率の向上など、オンラインオフィスの利点が徐々に顕著になってきています。
プロジェクトの紹介: このプロジェクトは、日常の事務処理 (日々のプロセスの承認、ニュース、通知、お知らせ、ファイル情報、財務、人事、経費、資産、管理、プロジェクト、モバイル オフィスなど) を管理するためのオンライン オフィス システムを実装します。ソフトウェアを通じてオフィスシステムを都合に合わせて管理することができ、全体の管理・運用レベルを向上させることができます。
実装方法:本プロジェクトはVue+Spring Bootをベースにフロントエンドとバックエンド分離プロジェクトを構築します。フロントエンドは、コミュニティで非常に活発なオープンソース フレームワーク Vue を使用して構築されています。簡単に言うと、フロントエンドとバックエンドの分離の中心的な考え方は、フロントエンド ページが ajax を介してデータ対話のためにバックエンドの Restuful API を呼び出し、一方、シングル ページ アプリケーション (シングル ページ Web アプリケーション、SPA) が呼び出すということです。ページが 1 つだけあり、ユーザーがアプリケーションと対話するときにページを随時動的に更新する Web アプリケーション。
JSON データは、RESTful API を通じてフロントエンドとバックエンドの間で通信されます。JSP などとは異なり、バックエンドはページ自体のコンテンツには関与しません。開発時、フロントエンドはフロントエンド サーバー (Nginx) を使用し、バックエンドはバックエンド サーバー (Tomcat) を使用します。フロントエンド コンテンツを開発するとき、フロントエンド リクエストを次のサーバーに転送できます。フロントエンド サーバー (リバース プロキシと呼ばれる) を介してバックエンドに接続するため、リアルタイムで結果を観察できます。バックエンドがどのように実装されているかを知る必要はなく、バックエンドによって提供される機能だけを知っていれば十分です。インターフェース。
1. 技術アーキテクチャ
2. フロントエンドの技術アーキテクチャ
このプロジェクトではフロントエンドとバックエンドを分離した開発モードを採用しており、Spring Boot を使用してバックエンドを構築します。フロントエンドモジュールは、ログイン、ポジション管理、役職管理、部門管理、オペレータカレンダー、従業員管理、給与口座管理、パーソナルセンター、オンラインチャットに分かれています。
フロントエンドで使用されるテクノロジーは次のとおりです。
プロジェクト構築:Vue-cli
状態管理: Vuex
ルーティング管理: VueRouter
UIインターフェース:ElementUI
通信フレームワーク:Axios
フロントエンド構文: ES6
パッケージング: Webpack
ライブチャット: WebSocket
フォント: font-awesome
ファイルのアップロードとダウンロード: js-file-download
オンライン チャット オープンソース プロジェクト: vue-chat
3. バックエンドの技術アーキテクチャ
バックエンドの主流開発フレームワーク: SpringBoot+Spring MVC+MyBatisPlus。セキュリティ認証と権限管理には Spring Security を、キャッシュには Redis を、電子メールの送信には RabbitMq を使用し、従業員データのインポートとエクスポートには EasyPOI を使用し、オンライン チャットには WebSocket を使用します。
セキュリティフレームワーク: Spring Security
トークン: JWT
グラフィック検証コード: Kaptcha
キャッシュ: redis
ドキュメントのインポートとエクスポート: EasyPOI
メッセージ キュー: RabbitMQ は非同期処理を実行し、電子メールを送信します。
メールコンポーネント: メール
ライブチャット: WebSocket
ファイルサーバー: FastDFS
データベースMySQL+Redis
1. vue.js プロジェクトをビルドする
1.vueの紹介
ネイティブ JS はほとんどの機能を実現できますが、煩雑すぎるか欠陥があるため、ほとんどの開発者は最初にフレームワーク開発ソリューションを選択します。フレームワークに関しては、ライフサイクル、フック関数、仮想DOM、Diffアルゴリズムなどの基礎知識を習得する必要があり、その中で、異なるレベルのコンポーネント間の通信、コンポーネントの状態管理、ルーティングジャンプ、コンポーネントのパフォーマンスの最適化などを習得する必要があります。フレキシブルな使用感。フロントエンドプロジェクトの開発では、実際の状況に応じてさまざまな程度に Vue を使用できます。Vue CLI (または vue-cli、つまり Vue スキャフォールディングとして記述) を使用して構築されたプロジェクトは、Vue の特性を最もよく反映できます。以下のコンテンツでゆっくりと体験していただけます。
モジュラー開発では、大きなファイルを多数の独立した小さなファイルに分割し、必要に応じてそれらをさまざまなコンポーネントにインポートします。これにより、コードの結合が減少し、コードの再利用性が向上します。Vue は HTML エントリを 1 つだけ含むシングルページ アプリケーションを開発し、残りはコンポーネントと呼ばれます。本当のエントリ ポイントは main.js です。Vue: 新しい機能を段階的に実装するプログレッシブ js フレームワーク。モジュール開発、ルーティング、状態管理など。
1.1 アクシオス
フロントエンド通信フレームワーク。vue の境界は非常に明確であり、DOM を処理するためのものであるため、通信機能はありません。現時点では、サーバーと対話するために追加の通信フレームワークを使用する必要があります。もちろん、直接使用することもできます。 jQueryが提供するAJAX通信機能。
1.2 Vueルーター
Vue Router は、Vue.js の公式ルーティング マネージャーです。Vue.js のコアと深く統合されているため、単一ページのアプリケーションを簡単に構築できます。含まれる機能は次のとおりです。
ネストされたルーティング/ビューテーブル
モジュール式のコンポーネントベースのルーティング構成
ルートパラメータ、クエリ、ワイルドカード
Vue.js トランジション システムに基づいたトランジション効果を表示する
きめ細かいナビゲーション制御
自動アクティブ化された CSS クラスとのリンク
HTML5 ヒストリー モードまたはハッシュ モード、IE9 では自動的に機能低下
カスタムスクロールバーの動作
1.3 ウェブパック
フロントエンド開発と他の開発作業の主な違いは、フロントエンドが多言語、マルチレベルのコーディングと編成作業に基づいていること、次に、フロントエンド製品の配信がブラウザに基づいていることです。これらのリソースは、増分読み込みによってブラウザーに実行されます。開発環境でこれらの断片化されたコードとリソースを整理し、ブラウザーでの高速かつエレガントな読み込みと更新を確実に行うには、モジュラー システムが必要です。
webpack は、最新の JavaScript アプリケーション用の静的モジュール バンドラー (モジュール バンドラー) です。Webpack はアプリケーションを処理するときに、アプリケーションが必要とするすべてのモジュールを含む依存関係グラフを再帰的に構築し、これらすべてのモジュールを 1 つ以上のバンドルにパッケージ化します。webpack の考え方: すべてはモジュールです。つまり、webpack は JavaScript によってモジュール化されるだけでなく、CSS、画像、フォントなどのリソースもモジュール化する必要があります。Webpack: モジュール パッケージャー。主な機能は、パッケージ化、圧縮、マージ、ロードを順番に行うことです。ES6 を ES5 にパッケージ化するなど
Webpack構成ファイル では、main.js がエントリ ファイルとして設定されており、プロジェクトはデフォルトで Index.html にアクセスします。このファイルは、App.vue コンポーネントのコンテナーと完全に重なっています。つまり、コンポーネントはインデックスにマウントされています。 page を参照し、あとは他のコンポーネントをビルドするだけです。App コンポーネントでは、他のコンポーネントの導入、登録、適用もできます。App コンポーネントではルーティングを通じて他のコンポーネントをレンダリングできるため、それぞれに注意するだけで済みます。コンポーネント、完璧な機能。つまり、vue のデフォルト ページはindex.html で、大きなコンポーネント App.vue がインデックスにマウントされ、他のすべてのサブコンポーネント (hello.vue など) はメイン コンポーネント App.vue に属します。
1.4 ES6モジュール
Vue は通常、es6 で書かれ、エクスポート デフォルトでエクスポートされます。エクスポート デフォルトには、データ、ライフ サイクル (マウントなど)、メソッド (メソッド) などが含まれます。具体的な構文については、vue.js ドキュメントを参照してください。ES6 標準では、JavaScript 言語レベルでモジュール システム定義が追加されています。ES6 モジュールの設計思想は、モジュールの依存関係や入出力変数をコンパイル時に決定できるように、できる限り静的であることです。CommonJS モジュールと AMD モジュールは両方とも、実行時にのみこれらのことを決定できます。
1.5 UIフレームワーク
Ele.me によって開始された Element-UI
1.6 vuex
アプリケーション専用に開発された状態管理パターン
npm install vuex --save
src ディレクトリに新しいストア ディレクトリを作成し、新しいindex.js ファイルを作成して、main.js にインポートします。
vuex のインストール開始エラー「エクスポート 'watch' が 'vue' に見つかりませんでした」
vue のバージョンが 2.X の場合は、vuex を 3.XX にアップグレードすることで解決できます。
npm install --save [email protected]
vue のバージョンが 3.X の場合は、vuex を 4.XX にアップグレードすることで解決できます。
npm install --save [email protected] npm install --save [email protected]
2. vue.js プロジェクトをビルドする
2.1 環境の準備
Node.js をインストールします (6.x 以上、8.x を推奨) このプロジェクトのバージョンは v14.18.0 です
2.2 Vue CLI のインストール
Vue CLI をインストールするには npm を使用する必要があり、npm は Node.js に統合されているため、Node.js をインストールする最初のステップとして、公式 Web サイト Node.js にアクセスし、ホームページからダウンロードできます。
ダウンロードが完了したら、インストール パッケージを実行し、次の手順に進みます。
次に、cmd に「node -v」と入力して、ノードが正常にインストールされているかどうかを確認します。
npm -v と入力して npm のバージョン番号を表示します
npm -g install npm と入力して、npm を最新バージョンに更新します。
その後、 npm install -g vue-cli でスキャフォールディングをインストールします。(このプロジェクトはバージョン 2.9.6 を使用します)
Vue CLI の 2.x バージョンはこの方法でインストールされ、最新バージョンは npm install -g @vue/cli を通じてインストールする必要があることに注意してください。新しいバージョンでは、グラフィカル インターフェイスを使用してプロジェクトを初期化し、プロジェクトの健全性監視のコンテンツを追加できますが、新しいバージョンで作成されたプロジェクトの依存関係がこのチュートリアルと一致せず、トスするのが面倒です。
タオバオ ミラー アクセラレータ cnpm がインストールされた Node.js
ほとんどの場合は npm を使用し、インストールできない場合は cnpm を使用します
npm インストール cnpm -g
またはnpm install --registry=https://registry.npm.taabao.org
3. フロントエンドプロジェクトをビルドする
一般的な方法では、コマンド ラインを使用してプロジェクトを直接ビルドします。
次に、コマンド vue init webpack yeb を実行します。ここで、webpack は、生成されたプロジェクトを参照するためのテンプレートとして webpack を使用します。また、ここでは説明しませんが、pwa や simple などのパラメーターに置き換えることもできます。
プログラムの実行中にいくつかのプロンプトが表示されます。デフォルト設定に従って Enter キーを押し続けることも、必要に応じて変更することもできます。たとえば、次の図でプロジェクト名が wj-vue かどうかを尋ねられた場合、 、Enter キーを押して確定します。
ここでは、vue-router をインストールするかどうかも尋ねられます。はいを選択する必要があります。つまり、Enter キーを押すか、Y キーを押します。vue-router は、シングルページ アプリケーションを構築するための鍵です。
また、es-lint を使用するかどうかは、N を選択します。
その後、プロジェクトがビルドされるまで待ちます。これで問題ありません。
プロジェクト フォルダーはワークスペース ディレクトリに生成されます。このフォルダーで npm install を実行し、npm run build してから npm run dev を実行する必要があります。
http://localhost:8080にアクセスし、Web ページのデモを表示すれば完了です。
注: vue プロジェクトでは、プロジェクトを開始するために npm runserve を実行する必要がある場合と、npm run dev を使用する必要がある場合があります。違いは何ですか?
違い
デフォルトでは、dev は[email protected] によってデフォルトでサポートされるコマンドです。
デフォルトでは、serve は [email protected] 以降でサポートされるコマンドです。
4. Vueプロジェクトの構造分析
§── ビルド --------------------------------- プロジェクト構築(webpack)関連の設定ファイル、設定パラメータなどオン、通常は移動しません
│ §── build.js ------------------------ webpack パッケージ化設定ファイル
│ §── check-versions.js ---------------------------- npm、nodejsのバージョンを確認する
│ §── dev-client.js ---------------------------------- 環境設定
│ §── dev-server.js ---------------------------------- Express サーバーの作成とミドルウェアの設定、開発プロジェクト用のホットリロード可能なサーバーを起動します
│ §── utils.js -------------------------------------- リソースパスの設定, CSSローダーの設定
│ §── vue-loader.conf.js ----------------------------- cssローダーなどの設定を行います。
│ §── webpack.base.conf.js ------------------------- webpack 基本設定
│ §── webpack.dev.conf.js ---------------------------- 開発用の webpack 設定
│ §── webpack.prod.conf.js ------------------------- パッケージング用の webpack 設定
§── config ----------------------------------- ポート番号などを含む設定ディレクトリ。初心者向けにはデフォルトを使用できます。
│ §── dev.env.js ------------------------ 開発環境変数
│ §──index.js ---------------------------- プロジェクト設定ファイル
│ §── prod.env.js -------------------------------------- 本番環境変数
│ §── test.env.js ------------------------ テスト環境変数
§── node_modules ---------------------------- npm でロードされたプロジェクト依存モジュール
§── src -------------------------------------------- 開発したいディレクトリ、基本的にはすべてあなたが行うのはこのディレクトリにあります。
│ §── アセット ---------------------------- 静的ファイル、ロゴなどの画像を配置します。
│ §── コンポーネント ------------------------ コンポーネントディレクトリ、コンポーネントファイルの格納、は使用できません。
│ §── main.js ----------------------------- メイン js
│ §── App.vue ----------------------------- プロジェクト エントリ コンポーネント。ここにコンポーネントを直接記述することもできます。コンポーネントディレクトリは使用されません。
│ §── ルータ ---------------------------- ルーティング
§── static ---------------------------- 画像、フォントなどの静的リソース ディレクトリ。
§── .babelrc--------------------------------- babel 設定ファイル
§── .editorconfig---------------------------- エディタ設定
§── .gitignore---------------------------- git が無視できるファイルを設定する
§──index.html ---------------------------- ホームページエントリファイル。メタ情報や統計コードを追加できます。の。
§── package.json ---------------------------- ノード構成ファイル。いくつかのコマンドと依存関係、およびプロジェクトの簡単な説明情報が記録されます。
§── .README.md---------------------------- マークダウン形式のプロジェクトドキュメント。好きなように書いてください。書き方がわからない場合は、github で星の数が多いプロジェクトを参照して、どのように書いているかを確認してください
主要書類の詳しい解説
4.1 src - [プロジェクトコアファイル]
vue-cli プロジェクトでは、基本的に行うべきことはすべてこのディレクトリ内にあるため、src フォルダーをマスターする必要があります。
4.2index.html - [ホームページ]
Index.html は他の HTML と同じですが、通常は空のルート ノードのみを定義します。main.js で定義されたインスタンスはルート ノードの下にマウントされ、コンテンツは vue コンポーネントによって埋められ、ビルドされたファイルは次のようになります。自動的に挿入されます。これは、作成した他のコンテンツがこの div に表示されることを意味します。プロジェクト全体で HTML ファイルは 1 つだけなので、これはシングルページ アプリケーションです。このアプリケーションを開くと、表面上は多くのページがあるように見えますが、実際にはすべて 1 つの div に含まれています。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vuedemo</title>
</head>
<body>
<!-- 定义的vue实例将挂载在#app节点下 -->
<div id="app"></div>
</body>
</html>
4.3 App.vue - [ルートコンポーネント]
このコンポーネントには他のコンポーネントが含まれているため、このファイルは「ルート コンポーネント」と呼ばれます。.vue ファイルはカスタム ファイル タイプで、構造が html に似ており、.vue ファイルは vue コンポーネントです。
vue ページは通常、template (テンプレート)、js (スクリプト)、style (スタイル) の 3 つの部分で構成されます。
<!-- 模板 -->
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view></router-view>
</div>
</template>
<!-- script -->
<script>
export default {
name: 'app'
}
</script>
<!-- 样式 -->
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
【テンプレート】
テンプレートには親ノードを 1 つだけ含めることができます。つまり、最上位 div は 1 つだけあります (たとえば、上記のコードでは、親ノードは親ノードが #app である div であり、兄弟ノードはありません) )。ここにも <div id="app"> がありますが、index.html のものとは関係ありません。この id=app は、次の CSS に対応します。
<router-view></router-view> はサブルーティング ビューであり、後続のすべてのルーティング ページがここに表示されます。<router-view> はスロットに似ており、あるルートにジャンプすると、そのルートの下のページがこのスロットに挿入されてレンダリング・表示されます。
【脚本】
<script> タグの内容はコンポーネントのスクリプト、つまり js コードです。エクスポートのデフォルトは ES6 の構文です。これは、このコンポーネントを全体としてエクスポートすることを意味します。その後、インポートを使用してコンポーネントをインポートできます。成分。中括弧内の内容は、このコンポーネントの関連プロパティです。
Vue は通常、es6 で書かれ、エクスポート デフォルトでエクスポートされます。エクスポート デフォルトには、データ、ライフ サイクル (マウントなど)、メソッド (メソッド) などが含まれます。具体的な構文については、vue.js ドキュメントを参照してください。
【スタイル】
スタイルは style タグでラップされており、デフォルトでは全世界に影響します。このコンポーネントの下でのみ機能するようにスコープを定義したい場合は、タグにscoped を追加する必要があります。外部 CSS ファイルをインポートしたい場合は、まず、プロジェクトの css-loader 依存関係パッケージをインストールする必要があります。cmd を開き、プロジェクト ディレクトリに入り、「npm install css-loader」と入力して、Enter キーを押します。インストールが完了したら、必要な CSS ファイルを style タグの下にインポートできます。次に例を示します。
<style>
import './assets/css/public.css'
</style>
4.4 main.js——[エントリファイル]
main.js は主に Vue フレームワーク、ルート コンポーネント、ルーティング設定を導入し、Vue インスタンスを定義します。次のコンポーネント: {App} はインポートされたルート コンポーネント App.vue です。プラグインは後から導入することもできますが、もちろん、プラグインを最初にインストールする必要があります。
前に、App.vue の <div id="app"> は、index.html の <div id="app"> とは無関係であると述べましたが、これら 2 つのファイルはどのように接続されるのでしょうか? エントリーファイルmain.jsのコードを見てみましょう。
/*引入vue框架*/
import Vue from 'vue'
/*引入根组件*/
import App from './App'
/*引入路由设置*/
import router from './router'
/*关闭生产模式下给出的提示*/
Vue.config.productionTip = false
/*定义实例*/
new Vue({
el: '#app',
router,
template: '<App/>',
components: { App }
})
先頭にはいくつかのモジュールがインポートされており、vueモジュールはnode_modulesにあり、AppはApp.vueで定義されたコンポーネント、routerはrouterフォルダーで定義されたルートです。Vue.config.productionTip = false 、この機能は、vue が起動時にプロダクション ヒントを生成しないようにすることです。この js ファイルでは、Vue オブジェクト (インスタンス) を作成し、el 属性は、Vue オブジェクトのマウント ターゲットとしてページ上にすでに存在する DOM 要素を提供します。ここでは、index.html の <div id="app を通じて、 "><div> の id="app" とここの "#app" がマウントされます。router は、オブジェクトに Vue Router が含まれており、プロジェクトで定義されたルートを使用することを意味します。コンポーネントはオブジェクトに含まれる Vue コンポーネントを示し、テンプレートは Vue インスタンスの識別子として文字列テンプレートを使用します。これは HTML タグの定義に似ています。
5. 関連パッケージのインストール
5.1 Element-UIのインストール
Element の正式アドレスは http://element-cn.eleme.io/#/zh-CN です。
1. Element のインストール
公式ドキュメントの記載に従い、プロジェクトフォルダ配下に npm i element-ui -S を実行して、
ここにアクセス 画像の説明を挿入2.
要素の
インポート インポートは、フル インポートとオンデマンド インポートの 2 つのモードに分かれています。オンデマンド インポートはプロジェクトのサイズを小さくできます。ここではフル インポートを選択します。
ドキュメントによると、main.js を次のように変更する必要があります。
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
5.2 axiosのインストール
プロジェクト フォルダーに移動し、
npm install --save axios を実行してこのモジュールをインストールします。
5.3 Vuex のインストール
Vuex は、Vue 用に特別に開発された状態管理ソリューションで、各コンポーネントで渡され使用される必要がある変数とメソッドを定義できます。これまで使ったことがないので、さまざまなコンポーネントから値を渡すのは頭の痛いことですし、さまざまなコンポーネントの値を呼び出すために多くの冗長なコードを書かなければならないので、慣れておくことをお勧めします最初からこの管理方法です。
npm install vuex --save を実行します。
その後、src ディレクトリにフォルダー ストアを作成し、そのディレクトリに新しいindex.js ファイルを作成し、そのファイルに vue と vuex を導入します。コードは次のとおりです。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
5.4 VueRouterのインストール
npm install vue-router --save-dev
Vue-router は Vue.js の公式ルーティング プラグインで、vue.js と深く統合されており、シングルページ アプリケーションの構築に適しています。Vue のシングルページ アプリケーションはルーティングとコンポーネントに基づいており、ルーティングはアクセス パスの設定、パスとコンポーネントのマップに使用されます。
router フォルダーの下に、ルーティング設定ファイルであるindex.jsがあります。'/index'、'/list' など、複数のルートを設定できます。もちろん、最初にコンポーネントを導入し、次にコンポーネントのルートを設定する必要があります。
5.5 font-awesome のインストール
npm install font-awesome
2. ログインページのデザイン
1. ページスタイルのデザイン
インターフェイスを設計するために注目する必要があるのは、<template> タグ内の html と <style> タグ内の css です。通常、フォームを使用してログイン ボックスを作成し、要素コンポーネント ドキュメント (http://element-cn.eleme.io/#/zh-CN/component/) を開くと、豊富なフォーム コンポーネントが提供されることがわかります。 , 「コードを表示」をクリックして、必要な部分をコピーできます。
ただし、アプリケーション シナリオに特に適した形式がないか、これらは比較的複雑であり、必要なのはほんの一部であるようです。ページをプルダウンすると、このコンポーネントのプロパティ、イベント、メソッドなどに関するドキュメントが表示され、これに従って必要なフォームを自分で構築することができます。
2. ログインページのコード - views/Login.vue
確認コードはバックエンド経由で画像を返します。フォームはルールを通じてルールをバインドし、props を通じて要素に属性を追加し、ルール内にルールを記述します。検証方法: this.$refs.loginForm.validate。
/captcha は情報を返します
/login ログイン返信メッセージ
ログインに成功した後、ユーザー トークンを sessionStorage に保存します。トークンがリクエスト インターセプターに存在するかどうかを判断し、各リクエストのトークンを検証します。存在する場合は、トークンの保持をリクエストし、Authorization パラメータに入れます。バックエンドは検証します。トークン。
フロントエンドのログインが成功したら、this.$router.replace('/home') を使用してホームページにジャンプします。replace メソッドを置き換えた後、ブラウザの戻るボタンをクリックしてもログイン ページにはジャンプしません。ログインが失敗した場合、バックエンドは失敗の理由を返します。
ユーザーがログインしていない場合、ユーザーがhttp://localhost:8080/#/でログイン ページにアクセスせず、ログイン後にのみアクセスできるルート ( http://localhost:8080など) にアクセスした場合/#/sys /basic。状況に応じて議論する必要があります: 1. ユーザーがホームページのアドレスまたは間違ったアドレスを入力し、ログインに成功した後にホームページにジャンプさせることができます; 2. それ以外の場合、ユーザーは正常に入力したアドレスにジャンプします。
this.$router.replace((パス === '/' || パス === 未定義) ? '/home' : パス)
<template>
<div>
<el-form
v-loading="loading"
element-loading-text="正在登录......"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
ref="loginForm" :model="loginForm" :rules="rules" class="loginContainer">
<h3 class="loginTitle">系统登录</h3>
<el-form-item prop="username">
<el-input type="text" v-model="loginForm.username" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item prop="password">
<el-input type="password" v-model="loginForm.password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item prop="code">
<el-input type="text" v-model="loginForm.code" placeholder="点击图片更换验证码"
style="width: 250px;margin-right: 5px;"></el-input>
<img :src="captchaUrl" @click="updateCaptcha">
</el-form-item>
<el-button type="primary" style="width: 100%" @click="submitLogin">登录</el-button>
</el-form>
</div>
</template>
<script>
export default {
name: 'Login',
components: {},
props: [],
data() {
return {
// 验证码
captchaUrl:'api/captcha?time=' + new Date(),//获取响应码后端接口
loginForm: {
username: 'admin',
password: '123',
code: '',
},
loading: false, // 加载中
checked: true,
//校验规则,与表单绑定
rules: {
username: [{required: true, message: '请输入用户名', trigger: 'blur'}],
password: [{required: true, message: '请输入密码', trigger: 'blur'}],
code: [{required: true, message: '请输入验证码', trigger: 'blur'}]
}
}
},
mounted(){
},
methods: {
// 点击刷新验证码
updateCaptcha() {
this.captchaUrl="api/captcha?time="+new Date();
},
submitLogin() {
// 登录
this.$refs.loginForm.validate((valid) => {
if (valid) {
this.loading = true;//准备调登录接口时,出现正在加载
//第一个参数请求后端的地址,第二个参数,传给后端的数据
this.postRequest('/login', this.loginForm).then(resp => {
this.loading = false;//登录成功后关闭
if (resp) {
// 存储用户 token 到 sessionStorage
const tokenStr = resp.obj.tokenHead + resp.obj.token;
window.sessionStorage.setItem('tokenStr', tokenStr);
// 跳转到首页
// this.$router.push('/home') // 路由跳转,可以回退到上一页
this.$router.replace('/home') // 路径替换,无法回退到上一页
// 页面跳转
// 拿到用户要跳转的路径
let path = this.$route.query.redirect;
// 用户可能输入首页地址或错误地址,让他跳到首页,否则跳转到他输入的地址
this.$router.replace((path === '/' || path === undefined) ? '/home' : path)
}
})
} else {
this.$message.error('请输入所有字段!');
return false;
}
})
}
}
}
</script>
<style>
.loginContainer {
border-radius: 15px;
background-clip: padding-box;
/*属性规定背景的绘制区域 背景被裁剪到内边距框。 margin: 180 px auto;*/
margin: 180px auto;
width: 350px;
padding: 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
box-shadow: 0 0 25px #cac6c6;
/* X轴偏移量 Y轴偏移量 [阴影模糊半径] [阴影扩展] [阴影颜色] [投影方式]; */
}
.loginTitle {
margin: 0 auto 40px auto;
text-align: center;
}
.loginRemember {
text-align: left;
margin: 0 0 15px 0;
}
/*验证码*/
.el-form-item__content {
display: flex;
align-items: center;
}
</style>
SessionStorage.setItem()では、axiosが次のリクエスト時にトークン認証を取得できるようにするため、ログイン後、トークンを取得してsessionStrorageに置きます。
// ユーザートークンを sessionStorage に保存します
const tokenStr = resp.obj.tokenHead + resp.obj.token;
window.sessionStorage.setItem('tokenStr', tokenStr);
3. ページルーティングの構成 - router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from "@/views/Login";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Login',
component: Login,
hidden: true // 不会被循环遍历出来
},
]
})
4. フロントエンドとバックエンドのクロスドメインを解決する
フロントエンド ポートのデフォルトは 8080 です。バックエンド ポートが 8081 であるとすると、8080 は 8081 のデータにどのようにアクセスしますか? Node.js を通じて自動ポート転送を実装します。ブラウザの同一オリジン ポリシー: 2 つのページは同じプロトコル (プロトコル) ホスト (ホスト) ポート番号 (ポート) を持つ必要があります。
インターフェイスを要求すると、Access-Control-Allow-Origin などが表示され、要求がクロスドメインであることを示します。vue でクロスドメインを解決する方法: vue.config.js ファイルを設定します。設定されていない場合は、自分で新しいファイルを作成します。
原理:
1. ドメイン名をローカルサーバー (localhost:8080) に送信します。
2. 次に、ローカルサーバーが実サーバーを要求します。
3. リクエストはサーバーから送信されるため、クロスドメインの問題はありません。
vue では、node.js によって自動的に行われます。
4.1 フロントエンド リバース プロキシ
main.jsを変更する
src\main.js コードを次のように変更します。
import Vue from 'vue'
import App from './App'
import router from './router'
// 设置反向代理,前端请求默认发送到 http://localhost:8081/api
var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8081/api'
// 全局注册,之后可在其他组件中通过 this.$axios 发送数据
Vue.prototype.$axios = axios
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
vue.config.jsを変更する
proxyTable リクエスト アドレスを、node.js の後のバックエンド アドレス 8081 にプロキシするように変更します。
proxyTable: {
'/': {
changeOrigin: true, //跨域
target: 'http://localhost:8081',
pathRewrite: {
// '^/api': ''
}
},
},
5. ログインインターセプタ
インターセプタは、名前が示すとおり、リクエスト インターセプタとレスポンス インターセプタであるリクエストをインターセプトします。実行順序は、リクエスト インターセプタ -> API リクエスト -> レスポンス インターセプタです。インターセプターの機能: a. API がリクエストからデータを返すのに必要な時間をカウントする; b. パブリック リクエスト ヘッダーを設定し、ポップアップ ウィンドウをロードするなど; c. 応答ステータス コードをインターセプトして返す400 または 500 をバックエンドのステータス コードと比較すると、対応するエラー メッセージが返されます。
5.1 axiosリクエストインターセプタリクエスト
Vue プロジェクトでは、通常、バックグラウンド データと対話するためにaxiosを使用します。Axios は、ブラウザーおよびノード環境で実行できる Promise ベースのライブラリです。リクエスト インターセプタ リクエストの機能: リクエストが送信される前に特定の操作を均一に実行し、リクエスト ヘッダー内のトークンの処理などによく使用されます。
リクエストインターセプターを追加する方法
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
})
5.2 Axios 応答インターセプター応答
返されるオブジェクト応答には、response.status: Http 応答コード、response.data: バックエンドによって返される Json オブジェクト (response.data.code ビジネス ロジック応答コードを含む)、response.data.message: バックエンドによって返される応答プロンプト メッセージが含まれます。 ;
レスポンスインターセプターメソッドを追加
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
}
5.3 パッケージリクエスト
このプロジェクトでは、axios を直接使用せず、1 つのレイヤーにカプセル化します。URL と params を受信してから axios オブジェクトを受信する postRequest メソッドを定義するなど、エクスポートを通じてカプセル化されたリクエストをエクスポートします。実際のインターフェース呼び出し操作はaxiosで実行します。
export const postRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params
})
}
5.4 コード実装 src/utils/api.js
import axios from "axios";
import {Message} from "element-ui";
import router from "@/router";
// 请求拦截器
axios.interceptors.request.use(config => {
// 如果存在 token,请求携带这个 token( 登录的时候 把 token 存入了 sessionStorage )
if (window.sessionStorage.getItem("tokenStr")) {
// token 的key : Authorization ; value: tokenStr
config.headers['Authorization'] = window.sessionStorage.getItem('tokenStr')
}
return config;
},error => {
console.log(error)
})
// 响应拦截器 - 统一处理消息提示
axios.interceptors.response.use(success => {
// 业务逻辑错误
if (success.status && success.status === 200) { // 调到接口
// 后端:500 业务逻辑错误,401 未登录,403 无权访问;
if (success.data.code === 500 || success.data.code === 401 || success.data.code === 403) {
Message.error({message: success.data.message})
return
}
if (success.data.message) { // 输出后端 添加成功 之类的信息
Message.success({message: success.data.message})
}
}
return success.data
}, error => { // 没访问到后端接口
if (error.response.code === 504 || error.response.code === 404) {
Message.error({message: '服务器不存在'})
} else if (error.response.code === 403) {
Message.error({message: '权限不足,请联系管理员!'})
} else if (error.response.code === 401) {
Message.error({message: '您还未登录,请登录!'})
router.replace('/') // 路由替换
} else {
if (error.response.data.message) {
Message.error({message: error.response.data.message})
} else {
Message.error({message: '未知错误!'})
}
}
return
})
// 预备前置路径
let base = '';
// 传送 json 格式的 post 请求
export const postRequest = (url, params) => {
return axios({
method: 'post',
url: `${base}${url}`,
data: params
})
}
// 传送 json 格式的 get 请求
export const getRequest = (url, params) => {
return axios({
method: 'get',
url: `${base}${url}`,
data: params
})
}
// 传送 json 格式的 put 请求
export const putRequest = (url, params) => {
return axios({
method: 'put',
url: `${base}${url}`,
data: params
})
}
// 传送 json 格式的 delete 请求
export const deleteRequest = (url, params) => {
return axios({
method: 'delete',
url: `${base}${url}`,
data: params
})
}
5.5 main.js はカプセル化リクエストをグローバルに導入します
このメソッドは main.js を通じてグローバルに導入され、プラグインを通じて使用されます。呼び出すときは this.putRequest(url, params) の形式を使用します。
import {postRequest} from "@/utils/api";
import {putRequest} from "@/utils/api";
import {getRequest} from "@/utils/api";
import {deleteRequest} from "@/utils/api";
Vue.prototype.postRequest = postRequest
Vue.prototype.putRequest = putRequest
Vue.prototype.getRequest = getRequest
Vue.prototype.deleteRequest = deleteRequest
6. フロントエンドルーティングナビゲーションガード
ログイン ページの開発は比較的完了しているように見えますが、実際にはまだ完成していません。このログイン ページは実際には役に立たず、他のユーザーがホームページの URL を直接入力することでログイン ページをバイパスできるからです。これを機能させるには、インターセプターも開発する必要があります。フック関数を使用して、関数および特定のタイミングで呼び出される関数をインターセプトするかどうかを決定します。ここでは、router.beforeEach() を使用します。これは、各ルートにアクセスする前に呼び出すことを意味します。to は移動するルート、from はどこからのルート、next() は解放します。
sessionStorage.getItem('user') を通じてユーザーのトークンを取得します。トークンが存在しない場合は、ログインする必要があります。
if (to.path == '/') ランディング ページかどうかを判断し、そうであればそのままにし、それ以外の場合はユーザーが指定したルートに従ってログインします。
main.jsの補足
// 使用 router.beforeEach 注册一个全局前置守卫
router.beforeEach((to, from, next) => {
// to 要去的路由; from 来自哪里的路由 ; next() 放行
// 用户登录成功时,把 token 存入 sessionStorage,如果携带 token,初始化菜单,放行
if (window.sessionStorage.getItem('tokenStr')) {
// 如果用户不存在
//待首页功能部分完善后补充
} else {
if (to.path === '/') {
next()
} else {
next('/?redirect=' + to.path)
}
}
})
7. プロジェクトを実行する
次
B ステーション クラウド E オフィス Vue+SpringBoot フロントエンドとバックエンドの分離プロジェクト - フロントエンドはメニュー ディレクトリを動的に取得します