Vueプロジェクトの作成
jingxi_shop_projectフォルダ内にfrontendフォルダを作成し、フロントエンドプロジェクトを格納します。
/jingxi_shop_project
/backend
/jingxi_shop_project
......
/frontend
/jingxi_shop_web
......
まずnode.jsとVue CLIをインストールし、プロジェクトディレクトリ内でプロジェクトを作成します。
vue create jingxi_shop_webコマンドを実行し、このプロジェクトではVue3、Router、Vuex、CSS Pre-processorsを基本設定として選択しました。
プロジェクトリソースの準備
まずsrcディレクトリ(通常の開発はsrcディレクトリで行います)
CSS
src配下のassetsディレクトリにcssフォルダを作成し、CSSの基本設定を格納します(CSSスタイルコードは直接利用可能です)
assets/css/base.js:
@charset "utf-8"
@import "./base/.css";
/* グローバルリセットと基本スタイル */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
outline: none;
}
* {
margin: 0;
padding: 0;
outline: none;
}
body {
font-size: 12px !important;
font-family: '微软雅黑', Helvetica, Arial, sans-serif, '宋体', Verdana;
background-color: #fff;
color: #333;
}
li{
list-style: none;
}
img{
border: 0 none;
vertical-align: middle;
}
a {
color: #333;
text-decoration: none !important;
outline: none;
cursor: pointer;
}
a:focus{
outline: none;
}
.clearfix::after{
visibility: hidden;
clear: both;
height: 0px;
display: block;
content: "";
}
input{
vertical-align: middle;
border: none;
background-color: none;
}
select{
vertical-align: middle;
border: none;
background-color: none;
}
button{
text-align: center;
border: 0;
cursor: pointer;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: normal;
font-size: 12px;
}
textarea,
input {
word-wrap: break-word;
word-break: break-all;
padding: 0px;
background: none;
}
label{
cursor: pointer;
}
input[type="button"]::-moz-focus-inner,
input[type="submit"]::-moz-focus-inner{
border: none;
}
input[type="button"],
input[type="submit"]{
cursor: pointer;
}
input:focus {
outline: none;
}
.fl{
float: left;
}
.fr{
float: right;
}
.cs{
cursor: pointer;
}
/* 1行を超える内容は...に変換 */
.dian1{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
/* 2行を超える内容は...に変換 */
.dian2{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
/* 3行を超える内容は...に変換 */
.dian3{
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
assets/css/config.js:
@import './base.css';
/* グローバル変数の定義 */
:root {
--font-red: #ef0115;
--font-gray: #999;
--content-width: 1200px;
--el-color-danger: #e2231a !important;
}
iconfont
Iconfontは、アイコンをフォント形式でウェブページに埋め込む技術です。開発者は簡単なCSSクラスでアイコンを利用・制御でき、プラットフォーム間の一貫性、拡張性、スタイルの一貫性を提供します。同時にHTTPリクエストとアイコンファイルのサイズを削減し、ウェブパフォーマンスと開発効率を最適化します。
iconfont公式サイトで必要なアイコンスタイルを選択し、プロジェクトにダウンロードして使用できます。
element-Plus
今後element-Plusも使用するため、事前にインストールします:npm install element-Plus
main.jsへのインポート
main.jsエントリーファイルに先ほどダウンロードしたリソースをインポートすることで、プロジェクト内で使用できるようになります。
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// CSSスタイルのインポート
import '@/assets/css/config.css'
// iconfontスタイルのインポート
import '@/iconfont/iconfont.css'
// ElementPlusのインポート
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
createApp(App).use(store).use(router).use(ElementPlus).mount('#app')
フロントエンドとバックエンドの連携
srcディレクトリ下にnetworkフォルダを作成し、ネットワークリクエストを処理します。
axiosリクエストを2つのファイルに分割してパッケージ化できます。共通部分をaxiosの基本設定(ベースURL、タイムアウト、リクエストとレスポンスインターセプターなど)としてパッケージ化し、実際のリクエスト関数を含むファイルを定義します。
src/network/requestConfig.js:
import axios from 'axios';
export function apiRequest(config){
const service = axios.create({
baseURL: "http://localhost:8000",
timeout: 5000
})
// リクエストインターセプター
service.interceptors.request.use(config=>{
console.log('リクエスト送信中:', config.url);
return config;
}, error=>{
console.error('リクエストエラー:', error);
})
// レスポンスインターセプター
service.interceptors.response.use(response=>{
console.log('レスポンス受信:', response.config.url);
return response.data ? response.data : response;
}, error=>{
console.error('レスポンスエラー:', error);
})
return service(config);
}
src/network/home.js:
import { apiRequest } from './requestConfig.js'
export function fetchMainMenu(){
return apiRequest({
url: "/menu/main_menu",
method: "GET"
})
}
フロントエンドとバックエンドの接続確認
ページコンポーネントで上記でパッケージ化したリクエスト関数を呼び出します。
<script setup>
import { fetchMainMenu } from "@/network/home.js"
import { onMounted, ref } from "vue"
const leftMenuData = ref([])
onMounted(()=>{
fetchMainMenu().then(response=>{
console.log(response);
}).catch(error=>{
console.error('データ取得エラー:', error);
})
})
</script>
クロスドメイン問題の解決
Access to XMLHttpRequest at 'http://localhost:8000/menu/main_menu/' (redirected from 'http://localhost:8000/menu/main_menu') from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
この時点でフロントエンドとバックエンドを実行すると、コンソールにクロスドメイン問題が表示されます。これはポート番号が異なるためリクエストが失敗したためです。バックエンドプロジェクトのsettings.pyでCORSを設定し、異なるソース(ドメイン、プロトコル、ポート)からのウェブページがサーバーリソースにアクセスできるようにする必要があります。
- django-cors-headerをインストール
- INSTALLED_APPSに
'corsheaders'を追加 - MIDDLEWAREに
'corsheaders.middleware.CorsMiddleware'を追加 - settingsの下部で異なるソースからのアクセスを許可する設定を追加
settings.py
...
ALLOWED_HOSTS = ['*']
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_HEADERS = ('*')
これでコンソールにバックエンドのデータが正常に表示されます。
ソースコードリポジトリ
https://gitee.com/duan-peitong/jignxi_shop_project