Mac快速搭建前端环境&创建前端项目
官网:
- vue:https://cn.vuejs.org/
- vue-router:https://www.axios-http.cn/
- pinia:https://pinia.vuejs.org/zh/getting-started.html
- axios:https://www.axios-http.cn/
- ant-design:https://www.antdv.com/
1 开发环境搭建
①安装node(nvm)
下载:https://nodejs.org/en
Mac可以安装配置nvm(管理node的工具)
- https://github.com/nvm-sh/nvm
- 如果安装过程中出现443,表明可能被墙了
- 解决:打开网站https://www.ipaddress.com/
查询一下 raw.githubusercontent.com对应的IP 地址,然后修改本机的vim /etc/hosts文件
| 185.199.108.133 raw.githubusercontent.com |
复制
| |
| curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash |
| |
| |
| export NVM_DIR="$HOME/.nvm" |
| [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" |
| |
| |
| nvm |
| |
| |
| |
| nvm install 13.0.1 |
| |
| nvm list | grep 13 |
| |
| nvm use 13.0.1 |
复制

②配置npm
| |
| npm config set registry https://registry.npmmirror.com |
| npm config get registry |
| |
| npm init: 项目初始化; |
| npm init -y:默认一路yes,不用挨个输入信息 |
| npm install 包名:安装js包到项目中(仅当前项目有效)。指定 包名,或者 包名@版本号 |
| npm install -g: 全局安装,所有都能用 |
| 可以去 npm仓库 搜索第三方库 |
| npm update 包名:升级包到最新版本 |
| npm uninstall 包名:卸载包 |
| npm run:项目运行 |
复制
③安装vite(脚手架)
vite:快速创建前端项目脚手架。包括react、vue等项目
官网:https://cn.vitejs.dev
| npm create vite |
| |
| npm install |
| |
| npm install axios |
| npm install -g xxx |
| |
| |
| npm run dev |
| |
| |
| |
| |
| npm run build |
复制

问题:如果出现报错:node:77305) Warning: require() of ES modules is not supported.,表明node版本过低不支持。通过nvm升级node版本即可。nvm use v18.20.2
④vue浏览器插件:Vue.js devtools

使用:

⑤VSCode/WebStorm
- VSCode官网(轻量级):https://code.visualstudio.com/Download

- WebStorm官网:https://www.jetbrains.com/webstorm/download/#section=mac

2 快速搭建简易登录页面
使用技术:vue+vue-router-pinia+axios+ant-design
官网:
- vue:https://cn.vuejs.org/
- vue-router:https://www.axios-http.cn/
- pinia:https://pinia.vuejs.org/zh/getting-started.html
- axios:https://www.axios-http.cn/
- ant-design:https://www.antdv.com/
🚀全部代码
:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/front_demo/vue/vue-all
2.1 创建vue项目
①vite创建vue基础项目
| |
| npm create vite |
| |
| cd vue-all |
| npm install |
| |
| |
| npm run dev |
复制

②引入ant-design
| |
| npm i --save ant-design-vue@4.x |
| |
| |
| import { createApp } from 'vue'; |
| import App from './App'; |
| import Antd from 'ant-design-vue'; |
| import 'ant-design-vue/dist/reset.css'; |
| |
| const app = createApp(App); |
| |
| app.use(Antd).mount('#app'); |
复制
2.2 使用ant-design快速搭建页面

①vue及路由配置
App.vue
| <script> |
| </script> |
| |
| <template> |
| <div> |
| <router-view/> |
| </div> |
| </template> |
| |
| <style scoped> |
| </style> |
复制
views/LoginVue.vue
| <script> |
| import {login} from "@/api/user.js"; |
| export default { |
| data() { |
| return { |
| loginUser: { |
| username: 'admin', |
| password: 'admin', |
| }, |
| }; |
| }, |
| methods: { |
| userLogin(){ |
| login(this.loginUser).then(res => { |
| console.log(res.status) |
| if(res.status === 200){ |
| alert('登录成功') |
| this.$router.push({path: `/userInfo/`}) |
| } |
| }, error => { |
| alert('登录失败') |
| }) |
| } |
| |
| |
| }, |
| } |
| </script> |
| |
| <template> |
| <div class="loginContainer"> |
| <div class="loginHeader"> |
| <span style="color: #2b92e4">ziyi后台管理系统</span> |
| </div> |
| <div class="loginMainWrapper"> |
| <div class="loginWrapper"> |
| <div class="loginTipsWrapper" style="color: #ffffff"> |
| <span class="siteSummaryTitle">ziy后台管理系统</span> |
| <div class="siteSummary"> |
| <ul> |
| <li> |
| <a-icon type="check-square" style="margin-right: 10px"/> |
| <span>统一方便的资源管理</span></li> |
| <li> |
| <a-icon type="check-square" style="margin-right: 10px"/> |
| <span>友好的界面展示,基于AntDesign组件库</span></li> |
| <li> |
| <a-icon type="check-square" style="margin-right: 10px"/> |
| <span>前后端分离,便于维护</span></li> |
| </ul> |
| </div> |
| </div> |
| <div class="loginBoxWrapper" align="center"> |
| <a-form-model :model="loginUser" style="width: 100%"> |
| <a-form-model-item style="color: palevioletred;text-align: center"> |
| <h1>欢迎登录</h1> |
| </a-form-model-item> |
| <a-form-model-item> |
| <a-input v-model:value="loginUser.username" placeholder="账号"> |
| <a-icon slot="prefix" type="user" style="color:rgba(0,0,0,.25)"/> |
| </a-input> |
| </a-form-model-item> |
| <a-form-model-item> |
| <a-input v-model:value="loginUser.password" type="password" placeholder="密码"> |
| <a-icon slot="prefix" type="lock" style="color:rgba(0,0,0,.25)"/> |
| </a-input> |
| </a-form-model-item> |
| <a-form-model-item> |
| </a-form-model-item> |
| <a-form-model-item> |
| <a-button type="primary" html-type="submit" style="width: 100%" @submit.prevent |
| @click="userLogin">立即登录 |
| </a-button> |
| <a-button style="width: 100%;margin-top: 10px">注册账号</a-button> |
| </a-form-model-item> |
| <a-form-model-item style="text-align: center"> |
| <a-space size="large"> |
| <a-icon type="weibo" style="font-size: 2em;cursor: pointer;color:#f50"/> |
| <a-icon type="qq" style="font-size: 2em;cursor: pointer;color:#2b92e4;"/> |
| <a-icon type="github" style="font-size: 2em;cursor: pointer;color:#333;"/> |
| </a-space> |
| </a-form-model-item> |
| </a-form-model> |
| </div> |
| </div> |
| <div class="loginFooter"> |
| © 2020-2024 CoreCmd 版权所有. 川ICP备18063315号-1 川公网安备 52158202001416号 |
| </div> |
| </div> |
| </div> |
| </template> |
| |
| <style scoped> |
| .loginContainer { |
| width: 100%; |
| position: relative; |
| background-attachment: fixed; |
| background-repeat: no-repeat !important; |
| background-size: cover; |
| background-position: center; |
| padding-top: 105px; |
| min-height: 100%; |
| } |
| |
| .loginHeader { |
| width: 100%; |
| height: 64px; |
| background-color: #ffffff; |
| position: fixed; |
| left: 0; |
| right: 0; |
| top: 0; |
| z-index: 1000; |
| box-shadow: 0 2px 15px rgba(0, 0, 0, .2); |
| display: flex; |
| align-items: center; |
| justify-content: flex-start; |
| flex-direction: row; |
| padding: 10px; |
| } |
| |
| .loginHeader span { |
| font-size: 25px; |
| font-weight: 700; |
| } |
| |
| .loginMainWrapper { |
| width: 100%; |
| display: flex; |
| justify-content: space-between; |
| flex-direction: column; |
| align-items: center; |
| } |
| |
| .loginWrapper { |
| width: 90%; |
| display: flex; |
| align-items: flex-start; |
| justify-content: right; |
| flex-direction: row; |
| height: 100%; |
| } |
| |
| .loginFooter { |
| width: 100%; |
| min-height: 64px; |
| display: flex; |
| justify-content: center; |
| align-items: flex-start; |
| flex-direction: row; |
| text-align: center; |
| color: #ffffff; |
| margin-top: 40px; |
| } |
| |
| .siteSummary ul { |
| list-style: none; |
| padding: 0; |
| } |
| |
| .siteSummary ul li { |
| margin-top: 10px; |
| list-style: none; |
| } |
| |
| @media screen and (min-width: 1200px) { |
| .loginTipsWrapper { |
| padding: 20px 30px; |
| display: flex; |
| align-items: flex-start; |
| justify-content: center; |
| flex-direction: column; |
| min-height: 100%; |
| } |
| |
| .loginBoxWrapper { |
| background-color: #ffffff; |
| padding: 20px; |
| width: 400px; |
| height: 100%; |
| border-radius: 5px; |
| } |
| } |
| |
| @media screen and (min-width: 769px) and (max-width: 1200px) { |
| .loginTipsWrapper { |
| padding: 20px 30px; |
| display: flex; |
| align-items: flex-start; |
| justify-content: center; |
| flex-direction: column; |
| height: 100%; |
| } |
| |
| .loginBoxWrapper { |
| background-color: #ffffff; |
| padding: 20px; |
| width: 400px; |
| height: 100%; |
| border-radius: 5px; |
| } |
| } |
| |
| @media screen and (max-width: 768px) { |
| .loginTipsWrapper { |
| display: none; |
| } |
| |
| .loginBoxWrapper { |
| background-color: #ffffff; |
| padding: 20px; |
| width: 100%; |
| border-radius: 5px; |
| } |
| } |
| |
| .siteSummaryTitle { |
| color: #ffffff; |
| font-size: 1.5rem; |
| font-weight: 700; |
| } |
| |
| .siteSummary { |
| margin-top: 25px; |
| color: #ffffff; |
| font-size: 1.2rem; |
| font-weight: 300; |
| } |
| </style> |
复制
views/UserInfo.vue
| <script setup> |
| |
| </script> |
| |
| <template> |
| <h1>用户中心</h1> |
| </template> |
| |
| <style scoped> |
| |
| </style> |
复制
router/index.js
| import {createRouter, createWebHistory} from 'vue-router' |
| import UserInfo from "@/views/UserInfo.vue"; |
| import LoginVue from "@/views/LoginVue.vue"; |
| |
| const router = createRouter({ |
| history: createWebHistory(import.meta.env.BASE_URL), |
| routes: [ |
| { |
| path: '/', |
| name: 'login', |
| component: LoginVue, |
| }, |
| { |
| path: '/userInfo', |
| name: 'userInfo', |
| component: UserInfo, |
| } |
| ] |
| }) |
| |
| export default router |
复制
②封装axios(util/http.js)
| import axios from "axios"; |
| |
| |
| const http = axios.create({ |
| baseURL: '/api', |
| timeout: 5000, |
| headers: { |
| 'Content-Type': 'application/json;charset=UTF-8' |
| }, |
| withCredentials:true, |
| }); |
| |
| |
| function get(url, params = {}) { |
| return new Promise((resolve, reject) => { |
| http.get(url, { |
| params: params |
| }).then(res => { |
| resolve(res.data); |
| }).catch(err => { |
| reject(err.data) |
| }) |
| }) |
| } |
| |
| function post(url, data = {}) { |
| return new Promise((resolve, reject) => { |
| http.post(url, data) |
| .then(response => { |
| resolve(response.data); |
| }) |
| .catch(err => { |
| reject(err) |
| }) |
| }) |
| } |
| |
| export default http; |
复制
③user.js
| import http from '../utils/http.js' |
| |
| export const login = (params) => http.post(`/login`, params) |
复制
2.4 vite.config.js解决跨域
| import {fileURLToPath, URL} from 'node:url' |
| |
| import {defineConfig} from 'vite' |
| import vue from '@vitejs/plugin-vue' |
| |
| |
| export default defineConfig({ |
| plugins: [ |
| vue(), |
| ], |
| resolve: { |
| alias: { |
| '@': fileURLToPath(new URL('./src', import.meta.url)) |
| } |
| }, |
| |
| server: { |
| proxy: { |
| '/api': { |
| target: 'http://localhost:8080', |
| changeOrigin: true, |
| rewrite: (path) => path.replace(/^\/api/, '') |
| } |
| } |
| } |
| }) |
复制
2.4 后端接口(Golang版)
为了代码简洁,这里直接使用硬编码,不再进行连接查询数据库等操作
| package main |
| |
| import ( |
| "fmt" |
| "github.com/kataras/iris/v12" |
| "github.com/kataras/iris/v12/context" |
| "net/http" |
| ) |
| |
| func main() { |
| app := iris.New() |
| app.Use(Cors) |
| app.Post("/login", login()) |
| app.Listen(":8080") |
| } |
| |
| func login() func(ctx *context.Context) { |
| return func(ctx *context.Context) { |
| tmp := make(map[string]interface{}) |
| err := ctx.ReadJSON(&tmp) |
| if err != nil { |
| ctx.StatusCode(http.StatusBadRequest) |
| return |
| } |
| username := tmp["username"] |
| password := tmp["password"] |
| fmt.Println("username:", username, "password:", password) |
| if username == "admin" && password == "admin" { |
| ctx.StatusCode(http.StatusOK) |
| return |
| } else { |
| ctx.StatusCode(http.StatusForbidden) |
| return |
| } |
| } |
| } |
| |
| func Cors(ctx iris.Context) { |
| |
| ctx.Header("Access-Control-Allow-Origin", "*") |
| if ctx.Method() == "OPTIONS" { |
| ctx.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS") |
| ctx.Header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization") |
| ctx.StatusCode(204) |
| return |
| } |
| ctx.Next() |
| } |
复制
2.5 测试
①启动项目
| |
| npm run dev |
| |
| |
| go run main.go |
复制
前端:

后端:

②验证
- 访问浏览器

- 点击登录按钮,请求后端

- 登录成功,跳转用户中心页面
