当前位置:   article > 正文

超详细的前后端实战项目(Spring系列加上vue3)前端篇(一)(一步步实现+源码)_vue+spring

vue+spring

最近想着一步步搭建一个前后端项目,将每一步详细的做出来。(如果有不足或者建议,也希望大佬们指出哦)

前端初始化

1.根据vue脚手架创建vue项目

这里可以用很多方法创建vue项目,大家看着创建吧,只要能创建出来就可以了(用的vue3)

这里我加了router和vuex,emm,就不用ts了(感觉还是js用的更好一点)

OK,项目创建完毕,即可开始写前端代码了。

2.安装依赖:

        1.挑一个自己喜欢的组件库引用一手,这里我选用arco design(也没必要只用Element-ui,可以试试其他的)

npm install --save-dev @arco-design/web-vue

OKOK,开始下载

安装好了之后,我们还要安装一些必要的依赖,比如axios,sass这些,emmmm,目前就安装这几个吧。

npm install axios

npm install sass -D

然后根据组件库官网的操作进行引入

  1. import { createApp } from 'vue'
  2. import ArcoVue from '@arco-design/web-vue';
  3. import App from './App.vue';
  4. import '@arco-design/web-vue/dist/arco.css';
  5. const app = createApp(App);
  6. app.use(ArcoVue);
  7. app.mount('#app');

改造一下main.js中的代码

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import store from './store'
  5. import ArcoVue from '@arco-design/web-vue';
  6. import '@arco-design/web-vue/dist/arco.css';
  7. createApp(App).use(store).use(ArcoVue).use(router).mount('#app')

注意注意引入组件库之后,可以找个组件看看能不能使用该组件库,以防万一;

呐,这里我们就去官网看看

很好,就是你了,表单布局,我们点击其下方代码,将其放入App.vue试试能不能用

好嘞,随机找一串串代码放到App.vue中试试(不要试着从图片中照抄我的哈,自己去官网找一个试试Arco Design Vue)咱,主打一个快速。

嚯,出现了!那么组件库是能用哒!

好,第二步也就完成了。

这里我建议每做几步就开启调试一下。

3.调整目录,初始化项目:

        1.清空components(把HelloWorld.vue删了)

        2.新建目录api,utils,views

        3.把App.vue中用不到的代码都给删了,留一个  <router-view />就好了,然后,把router的index.js的代码全给注释了(emmm,直接删了感觉太麻烦,注释了后面写起来好做参照)

目前的目录结构就是这样了;

(App.vue就变成这样啦)

4.定义请求工具:

大家不要一开始写前端就直奔优美的”可跳转“页面,这边先整体规定一个向后端发请求的工具request.js

        在utils目录下创建request.js文件:

  1. import axios from 'axios';//导入axios
  2. //定义前缀
  3. const URL = 'http://localhost:8080';
  4. const instance = axios.create({URL})
  5. //来一个响应拦截器
  6. instance.interceptors.response.use(
  7. result=>{
  8. if(result.data.code == 0){
  9. return result.data;
  10. }
  11. //如果不为0则表示失败
  12. alert(result.data.message||'出现错误')
  13. return Promise.reject(err);//异步的状态转化成失败的状态
  14. },
  15. err=>{
  16. alert('服务异常');
  17. return Promise.reject(err);//异步的状态转化成失败的状态
  18. }
  19. )
  20. export default instance;

解释一下这段代码:引入发请求的axios,然后定义一个开发时期的请求必有前缀(这里直接写http://localhost:8080其实是有问题的,对于后面出现的跨域问题....emmmm,其实前端后端都有方式解决,看情况吧,后面再讲),做一个相应拦截器,对结果进行判断,然后导出

(这里需要提示一下统一相应有哪些(不然可能会不太好理解))

后端那一块统一相应数据:code:0表示成功,1表示失败;msg: 提示信息;data:数据

前端代码编写开始!!

OK啊各位,初始化完成我们便要开始编写代码了。

首先,我们先明确一波步骤:

        确定布局  --> 填充各部分代码 -->  后端插入

(如果涉及与后端的交互,遵循以下步骤

        1.搭建页面(html,css)-> 2.绑定数据与事件 -> 3.调用后端接口)

好嘞,熟悉了吗各位,不熟练也没事,我们先找一个练练手。

先从组件库这里找到布局:

这布局,看似普通,实则帅的雅痞,就它了。引入代码

回到目录component下,创建一个新的文件GlobalPage.vue

(众所周知的小技巧:<vue>可快速构建vue文件)

  1. <template>
  2. <a-layout style="height: 400px;">
  3. <a-layout-header>Header</a-layout-header>
  4. <a-layout>
  5. <a-layout-sider theme="dark">Sider</a-layout-sider>
  6. <a-layout-content>Content</a-layout-content>
  7. </a-layout>
  8. <a-layout-footer>Footer</a-layout-footer>
  9. </a-layout>
  10. </template>
  11. <script>
  12. export default {
  13. }
  14. </script>
  15. <style scoped>
  16. .layout-demo :deep(.arco-layout-header),
  17. .layout-demo :deep(.arco-layout-footer),
  18. .layout-demo :deep(.arco-layout-sider-children),
  19. .layout-demo :deep(.arco-layout-content) {
  20. display: flex;
  21. flex-direction: column;
  22. justify-content: center;
  23. color: var(--color-white);
  24. font-size: 16px;
  25. font-stretch: condensed;
  26. text-align: center;
  27. }
  28. .layout-demo :deep(.arco-layout-header),
  29. .layout-demo :deep(.arco-layout-footer) {
  30. height: 64px;
  31. background-color: var(--color-primary-light-4);
  32. }
  33. .layout-demo :deep(.arco-layout-sider) {
  34. width: 206px;
  35. background-color: var(--color-primary-light-3);
  36. }
  37. .layout-demo :deep(.arco-layout-content) {
  38. background-color: rgb(var(--arcoblue-6));
  39. }
  40. </style>

然后我们改一下index.js文件(将GlobalPage引入)(要是看着那些注解感觉不美观的话就直接删了)

  1. import { createRouter, createWebHashHistory } from 'vue-router'
  2. import MainPage from '../components/GlobalPage.vue'
  3. const routes = [
  4. // {
  5. // path: '/',
  6. // name: 'home',
  7. // component: HomeView
  8. // },
  9. // {
  10. // path: '/about',
  11. // name: 'about',
  12. // // route level code-splitting
  13. // // this generates a separate chunk (about.[hash].js) for this route
  14. // // which is lazy-loaded when the route is visited.
  15. // component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  16. // }
  17. {
  18. path: '/',
  19. name: 'mainPage',
  20. component: MainPage
  21. }
  22. ]
  23. const router = createRouter({
  24. history: createWebHashHistory(),
  25. routes
  26. })
  27. export default router

运行一手看看(记得每次有一些大改就要看看情况,改多再看就会很麻烦,bug也不好排查)

运行出来就是这么个界面

搭建Header和Footer代码

先把头部和尾部的代码解决了。

先来尾部吧,我觉得这个比较简单(哈)

一般来说,网站的底部都是一些网站运营的介绍什么的(大多都是哈,也不一定全是)

这里我就以大家都爱的4399为例(大多都是哈,也不一定全是,哈哈哈)

emmm,这里我们可以把Footer这一块封装为一个组件,因为虽然定义的GlobalPage属于是全局的页面,但万一之后会跳转到其他的页面呢,这里我觉得封装成组件更好一些(看起来也更轻巧一些)

在views目录下创建GlobalFooter.vue

  1. <template>
  2. <div id="header">由Heath ceTide 创作的网站 XXX 有限公司</div>
  3. </template>
  4. <script>
  5. export default {};
  6. </script>
  7. <style>
  8. #header {
  9. font-family: "Satisfy", cursive;
  10. font-size: 16px;
  11. color: rgb(102, 149, 164);
  12. margin-right: 20px;
  13. }
  14. </style>

差不多了,将其替换掉GlobalPage的header

  1. <template>
  2. <a-layout style="height: 400px;">
  3. <a-layout-header>Header</a-layout-header>
  4. <a-layout>
  5. <a-layout-sider theme="dark">Sider</a-layout-sider>
  6. <a-layout-content>Content</a-layout-content>
  7. </a-layout>
  8. <a-layout-footer>
  9. <global-footer></global-footer>
  10. </a-layout-footer>
  11. </a-layout>
  12. </template>
  13. <script>
  14. import GlobalFooter from '../views/GlobalFooter.vue'
  15. export default {
  16. components: { GlobalFooter },
  17. }
  18. </script>

展示出了样式就行了,(之后可以美化以下),好,然后我们开始整Header,

这一块导航栏,我觉得吧,还是用组件比较合适(倒不是不会整,毕竟也麻烦,不用自己手敲的绝不自己手敲代码)

就选这个深色模式导航啦,新建GlobalHeader.vue文件把代码用CV大法放进去

  1. <template>
  2. <div class="menu-demo">
  3. <a-menu mode="horizontal" theme="dark" :default-selected-keys="['1']">
  4. <a-menu-item key="0" :style="{ padding: 0, marginRight: '38px' }" disabled>
  5. <div
  6. :style="{
  7. width: '80px',
  8. height: '30px',
  9. background: 'var(--color-fill-3)',
  10. cursor: 'text',
  11. }"
  12. />
  13. </a-menu-item>
  14. <a-menu-item key="1">Home</a-menu-item>
  15. <a-menu-item key="2">Solution</a-menu-item>
  16. <a-menu-item key="3">Cloud Service</a-menu-item>
  17. <a-menu-item key="4">Cooperation</a-menu-item>
  18. </a-menu>
  19. </div>
  20. </template>
  21. <style scoped>
  22. .menu-demo {
  23. box-sizing: border-box;
  24. width: 100%;
  25. background-color: var(--color-neutral-2);
  26. }
  27. </style>
  1. <template>
  2. <a-layout style="height: 400px">
  3. <a-layout-header><global-header></global-header></a-layout-header>
  4. <a-layout>
  5. <a-layout-sider theme="dark">Sider</a-layout-sider>
  6. <a-layout-content>Content</a-layout-content>
  7. </a-layout>
  8. <a-layout-footer>
  9. <global-footer class="footer"></global-footer>
  10. </a-layout-footer>
  11. </a-layout>
  12. </template>
  13. <script>
  14. import GlobalFooter from "../views/GlobalFooter.vue";
  15. import GlobalHeader from "../views/GlobalHeader.vue";
  16. export default {
  17. components: { GlobalFooter, GlobalHeader },
  18. };
  19. </script>
  20. <style scoped>
  21. .layout-demo :deep(.arco-layout-header),
  22. .layout-demo :deep(.arco-layout-footer),
  23. .layout-demo :deep(.arco-layout-sider-children),
  24. .layout-demo :deep(.arco-layout-content) {
  25. display: flex;
  26. flex-direction: column;
  27. justify-content: center;
  28. color: var(--color-white);
  29. font-size: 16px;
  30. font-stretch: condensed;
  31. text-align: center;
  32. }
  33. .layout-demo :deep(.arco-layout-header),
  34. .layout-demo :deep(.arco-layout-footer) {
  35. height: 64px;
  36. background-color: var(--color-primary-light-4);
  37. }
  38. .layout-demo :deep(.arco-layout-sider) {
  39. width: 206px;
  40. background-color: var(--color-primary-light-3);
  41. }
  42. .layout-demo :deep(.arco-layout-content) {
  43. background-color: rgb(var(--arcoblue-6));
  44. }
  45. .footer {
  46. background-color: aliceblue;
  47. padding: 16px;
  48. position: sticky;
  49. bottom: 0;
  50. left: 0;
  51. right: 0;
  52. text-align: center;
  53. letter-spacing: 3px;
  54. }
  55. </style>

其实这个空的区域可以加一个logo或者其他什么的

呐,就像这样

OK,目前的页面就是这个样子了;

搭建搜索页面

好的,下面整一个全局的搜索框页面吧

创建一个SearchPage.vue 文件

从组件库中找到一个合适的搜索框

  1. <!--SearchPage.vue代码-->
  2. <template>
  3. <a-space direction="vertical" size="large">
  4. <a-input-search
  5. :style="{ width: '320px' }"
  6. placeholder="Please enter something"
  7. button-text="Search"
  8. search-button
  9. />
  10. </a-space>
  11. </template>
  12. <script>
  13. export default {};
  14. </script>
  15. <style>
  16. </style>

将新组件放到GlobalPage中(暂时的,之后还是要处理路由的)

  1. <template>
  2. <a-layout style="height: 400px">
  3. <a-layout-header><global-header></global-header></a-layout-header>
  4. <a-layout>
  5. <a-layout-sider theme="dark">Sider</a-layout-sider>
  6. <a-layout-content><search-page></search-page></a-layout-content>
  7. </a-layout>
  8. <a-layout-footer>
  9. <global-footer class="footer"></global-footer>
  10. </a-layout-footer>
  11. </a-layout>
  12. </template>
  13. <script>
  14. import GlobalFooter from "../views/GlobalFooter.vue";
  15. import GlobalHeader from "../views/GlobalHeader.vue";
  16. import SearchPage from '../views/SearchPage.vue';
  17. export default {
  18. components: { GlobalFooter, GlobalHeader, SearchPage },
  19. };
  20. </script>

现在搜索框就出来了,(这里最右边加了一点点小细节(不重要)之后会把代码发出来)

这里其实可以加一个搜索框等待效果

  1. <template>
  2. <div id="search">
  3. <a-space direction="vertical" size="large">
  4. <a-input-search
  5. :style="{ width: '320px' }"
  6. placeholder="Please enter something"
  7. button-text="Search"
  8. search-button
  9. />
  10. </a-space>
  11. <a-space direction="vertical" size="large">
  12. <a-input-search
  13. :style="{ width: '320px' }"
  14. placeholder="Please enter something"
  15. button-text="Search"
  16. search-button
  17. loading
  18. />
  19. </a-space>
  20. </div>
  21. </template>
  22. <script>
  23. export default {};
  24. </script>
  25. <style>
  26. </style>

这里其实是复制了两个搜索框代码,不过另外一个加上了loading属性,这样就能表现出等待中的效果

呐呐呐,就是这样,然后我们再用v-if定义一下它的显示和隐藏就可以了

ok,演示一下:

先设置script 为setup,然后引入ref

  1. <script setup>
  2. import {ref} from 'vue';

 还记得之前说的三部曲吗: 1.搭建页面(html,css)-> 2.绑定数据与实践 -> 3.调用后端接口)

那我们以及写好了搜索框了,也该进行数据绑定了(这里暂时不进行后端接口调用,(毕竟还没开发))

对于一个组件的显示和隐藏我们直接写

  1. <script setup>
  2. import {ref} from 'vue';
  3. const isSearch = ref(false)

然后呢,两个搜索框绑定该属性(一个是isSearch,一个是!isSearch),这样就能保持一个显示,一个隐藏了。那么,如何实现转换呢,平时在搜索的时候,当我们点击了搜索按钮的时候就会出现转换效果,如果网比较好的话,估计也就直接跳转了,(如果网不好的话,搜索框转圈转了一会儿就会恢复原样)

那么,我们定义一个函数,在正常情况下点击搜索的时候触发,转换为搜索中的样式,然后过几秒就恢复原状。

那么开始定义吧;

  1. <script setup>
  2. import {ref} from 'vue';
  3. const isSearch = ref(false)
  4. const onSearch = () => {
  5. isSearch.value = true;
  6. setTimeout(() => {
  7. isSearch.value = false;
  8. }, 5000);
  9. };
  10. </script>

这里定义了一个函数,点击之后,isSearch改变,等到五秒之后,值恢复。来试试吧

  1. <template>
  2. <div id="search">
  3. <a-space direction="vertical" size="large" v-if="!isSearch">
  4. <a-input-search
  5. :style="{ width: '320px' }"
  6. placeholder="Please enter something"
  7. button-text="Search"
  8. search-button
  9. @click=onSearch
  10. />
  11. </a-space>
  12. <a-space direction="vertical" size="large" v-if="isSearch">
  13. <a-input-search
  14. :style="{ width: '320px' }"
  15. placeholder="Please enter something"
  16. button-text="Search"
  17. search-button
  18. loading
  19. />
  20. </a-space>
  21. </div>
  22. </template>
  23. <script setup>
  24. import {ref} from 'vue';
  25. const isSearch = ref(false)
  26. const onSearch = () => {
  27. isSearch.value = true;
  28. setTimeout(() => {
  29. isSearch.value = false;
  30. }, 5000);
  31. };
  32. </script>

成功了,那再来完善一下

有搜索框,当然要有显示搜索内容的区域,

再去组件库看看有没有什么合适的

就用这个吧,

  1. <template>
  2. <div id="searchPage">
  3. <div class="search">
  4. <a-space direction="vertical" size="large" v-if="!isSearch">
  5. <a-input-search
  6. :style="{ width: '620px' }"
  7. placeholder="Please enter something"
  8. button-text="Search"
  9. search-button
  10. @click="onSearch"
  11. />
  12. </a-space>
  13. <a-space direction="vertical" size="large" v-if="isSearch">
  14. <a-input-search
  15. :style="{ width: '620px' }"
  16. placeholder="Please enter something"
  17. button-text="Search"
  18. search-button
  19. loading
  20. />
  21. </a-space>
  22. </div>
  23. <a-space direction="vertical" size="large">
  24. <a-radio-group v-model="type" type="button">
  25. <a-radio value="line">Line</a-radio>
  26. <a-radio value="card">Card</a-radio>
  27. <a-radio value="card-gutter">Card Gutter</a-radio>
  28. <a-radio value="text">Text</a-radio>
  29. <a-radio value="rounded">Rounded</a-radio>
  30. <a-radio value="capsule">Capsule</a-radio>
  31. </a-radio-group>
  32. <a-radio-group v-model="size" type="button">
  33. <a-radio value="mini">Mini</a-radio>
  34. <a-radio value="small">Small</a-radio>
  35. <a-radio value="medium">Medium</a-radio>
  36. <a-radio value="large">Large</a-radio>
  37. </a-radio-group>
  38. <a-tabs :type="type" :size="size">
  39. <a-tab-pane key="1" title="Tab 1"> Content of Tab Panel 1 </a-tab-pane>
  40. <a-tab-pane key="2" title="Tab 2"> Content of Tab Panel 2 </a-tab-pane>
  41. <a-tab-pane key="3" title="Tab 3"> Content of Tab Panel 3 </a-tab-pane>
  42. </a-tabs>
  43. </a-space>
  44. </div>
  45. </template>
  46. <script setup>
  47. import { ref } from "vue";
  48. const isSearch = ref(false);
  49. const onSearch = () => {
  50. isSearch.value = true;
  51. setTimeout(() => {
  52. isSearch.value = false;
  53. }, 5000);
  54. };
  55. </script>
  56. <style scoped>
  57. .search{
  58. margin: 30px auto;
  59. }
  60. </style>

添加代码并做一些优化

目前就是这个样子了。

emmm,感觉不太对,好像有点快了,要不还是做一个登录注册页面吧。。。

搭建登录注册页面

创建LoginPage.vue

这一块我觉得还挺容易的,先给个示例代码吧

  1. <template>
  2. <div class="container">
  3. <div class="login-box">
  4. <!-- Login Form -->
  5. <form action="">
  6. <h2>Login</h2>
  7. <div class="input-box">
  8. <span class="icon"><i class="fa-solid fa-envelope"></i></span>
  9. <input type="email" required placeholder="Email" />
  10. </div>
  11. <div class="input-box">
  12. <span class="icon"><i class="fa-solid fa-lock"></i></span>
  13. <input type="password" placeholder="Password" required />
  14. </div>
  15. <div class="remember-forget">
  16. <label><input type="checkbox" />Remember Me</label>
  17. <a href="#">Forgot Password?</a>
  18. </div>
  19. <button type="submit">Login</button>
  20. <div class="register-link">
  21. <a href="#">Don't have an account? Create Now!</a>
  22. </div>
  23. </form>
  24. </div>
  25. </div>
  26. </template>
  27. <script>
  28. export default {
  29. }
  30. </script>
  31. <style scoped>
  32. * {
  33. margin: 0;
  34. padding: 0;
  35. box-sizing: border-box;
  36. font-family: "Poppins", sans-serif;
  37. }
  38. .container {
  39. width: 100%;
  40. height: 100vh;
  41. background: url("../assets/background.jpg") no-repeat;
  42. background-size: cover;
  43. background-position: center;
  44. display: flex;
  45. justify-content: center;
  46. align-items: center;
  47. }
  48. .container .login-box {
  49. position: relative;
  50. width: 390px;
  51. height: 420px;
  52. background-color: transparent;
  53. border: 2px solid rgba(255, 255, 255, 0.5);
  54. border-radius: 20px;
  55. display: flex;
  56. justify-content: center;
  57. align-items: center;
  58. backdrop-filter: blur(15px);
  59. }
  60. .login-box h2 {
  61. font-size: 28px;
  62. color: #fff;
  63. text-align: center;
  64. }
  65. .login-box .input-box {
  66. position: relative;
  67. width: 310px;
  68. margin: 30px 0;
  69. border-bottom: 2px solid #fff;
  70. }
  71. .input-box input {
  72. width: 100%;
  73. height: 50px;
  74. background: transparent;
  75. border: none;
  76. outline: none;
  77. font-size: 16px;
  78. color: #fff;
  79. padding: 0 35px 0 5px;
  80. }
  81. .input-box input::placeholder {
  82. color: #f9f9f9;
  83. }
  84. .input-box .icon {
  85. position: absolute;
  86. right: 8px;
  87. color: #fff;
  88. font-size: 18px;
  89. line-height: 50px;
  90. }
  91. .login-box .remember-forget {
  92. margin: -15px 0 15px;
  93. font-size: 15px;
  94. color: #fff;
  95. display: flex;
  96. justify-content: space-between;
  97. }
  98. .remember-forget label input {
  99. margin-right: 3px;
  100. }
  101. .login-box button {
  102. width: 100%;
  103. height: 40px;
  104. background: #fff;
  105. border: none;
  106. outline: none;
  107. border-radius: 40px;
  108. cursor: pointer;
  109. font-size: 16px;
  110. color: #000;
  111. transition: all 0.5s;
  112. }
  113. .login-box button:hover {
  114. background: #1f73c9;
  115. color: #fff;
  116. }
  117. .login-box .register-link {
  118. font-size: 15px;
  119. color: #fff;
  120. text-align: center;
  121. margin: 20px 0 10px;
  122. }
  123. .remember-forget a,
  124. .register-link a {
  125. color: #fff;
  126. text-decoration: none;
  127. }
  128. .remember-forget a:hover,
  129. .register-link a:hover {
  130. text-decoration: underline;
  131. }
  132. /* Responsive Design */
  133. @media (max-width: 460px) {
  134. .container .login-box {
  135. width: 350px;
  136. }
  137. .login-box .input-box {
  138. width: 290px;
  139. }
  140. }
  141. @media (max-width: 360px) {
  142. .container .login-box {
  143. width: 100%;
  144. height: 100vh;
  145. border: none;
  146. }
  147. }
  148. </style>

这一块代码是之前找到的一个登录页代码,我觉着就还挺好

不过吧,我决定还是不用这个代码,去组件库上找找吧(主要还是要加深一下组件库的使用)

好了就用这个

小改一下吧;

  1. <template>
  2. <div class="container">
  3. <div class="login-box">
  4. <a-form
  5. :model="form"
  6. :style="{ width: '600px' }"
  7. @submit="handleSubmit"
  8. class="input-box"
  9. >
  10. <h2 style="margin-bottom: 60px">Login</h2>
  11. <a-form-item
  12. field="name"
  13. tooltip="Please enter username"
  14. label="账号"
  15. class="element"
  16. >
  17. <a-input
  18. v-model="form.name"
  19. placeholder="please enter your username..."
  20. style="margin-right: 40px"
  21. />
  22. </a-form-item>
  23. <a-form-item field="post" label="密码" class="element">
  24. <a-input
  25. v-model="form.post"
  26. placeholder="please enter your password..."
  27. style="margin-right: 40px"
  28. />
  29. </a-form-item>
  30. <a-form-item field="isRead">
  31. <a-checkbox v-model="form.isRead">
  32. I have read the manual
  33. </a-checkbox>
  34. </a-form-item>
  35. <a-form-item>
  36. <a-button html-type="submit" class="input-box">Submit</a-button>
  37. </a-form-item>
  38. <div class="register-link">
  39. <a href="#">Don't have an account? Create Now!</a>
  40. </div>
  41. </a-form>
  42. </div>
  43. </div>
  44. </template>
  45. <script>
  46. </script>
  47. <style scoped>
  48. * {
  49. margin: 0;
  50. padding: 0;
  51. box-sizing: border-box;
  52. font-family: "Poppins", sans-serif;
  53. display: flex;
  54. justify-content: center;
  55. }
  56. .container {
  57. width: 100%;
  58. height: 100vh;
  59. background: url("../assets/background.jpg") no-repeat;
  60. background-size: cover;
  61. background-position: center;
  62. display: flex;
  63. justify-content: center;
  64. align-items: center;
  65. }
  66. .container .login-box {
  67. position: relative;
  68. width: 500px;
  69. height: 580px;
  70. background-color: transparent;
  71. border: 2px solid rgba(255, 255, 255, 0.5);
  72. border-radius: 20px;
  73. display: flex;
  74. justify-content: center;
  75. align-items: center;
  76. backdrop-filter: blur(15px);
  77. }
  78. .login-box h2 {
  79. font-size: 28px;
  80. color: #fff;
  81. text-align: center;
  82. }
  83. .login-box .input-box {
  84. position: relative;
  85. width: 310px;
  86. margin: 30px 0;
  87. }
  88. .input-box input {
  89. width: 80%;
  90. height: 60px;
  91. background: transparent;
  92. border: none;
  93. outline: none;
  94. font-size: 16px;
  95. color: #fff;
  96. padding: 0 2px 0 5px;
  97. }
  98. .input-box input::placeholder {
  99. color: #f9f9f9;
  100. }
  101. .input-box .icon {
  102. position: absolute;
  103. right: 8px;
  104. color: #fff;
  105. font-size: 16px;
  106. line-height: 25px;
  107. }
  108. .login-box .remember-forget {
  109. margin: -15px 0 15px;
  110. font-size: 15px;
  111. color: #fff;
  112. display: flex;
  113. justify-content: space-between;
  114. }
  115. .remember-forget label input {
  116. margin-right: 30px;
  117. }
  118. .login-box button {
  119. width: 100%;
  120. height: 40px;
  121. background: #fff;
  122. border: none;
  123. outline: none;
  124. border-radius: 40px;
  125. cursor: pointer;
  126. font-size: 16px;
  127. color: #000;
  128. transition: all 0.5s;
  129. }
  130. .login-box button:hover {
  131. background: #1f73c9;
  132. color: #fff;
  133. }
  134. .login-box .register-link {
  135. font-size: 15px;
  136. color: #fff;
  137. text-align: center;
  138. margin: 5px 0 5px;
  139. }
  140. .remember-forget a,
  141. .register-link a {
  142. color: #fff;
  143. text-decoration: none;
  144. }
  145. .remember-forget a:hover,
  146. .register-link a:hover {
  147. text-decoration: underline;
  148. }
  149. /* Responsive Design */
  150. @media (max-width: 460px) {
  151. .container .login-box {
  152. width: 350px;
  153. }
  154. .login-box .input-box {
  155. width: 290px;
  156. }
  157. }
  158. @media (max-width: 360px) {
  159. .container .login-box {
  160. width: 100%;
  161. height: 100vh;
  162. border: none;
  163. }
  164. }
  165. .element {
  166. margin: 20px 0;
  167. }
  168. </style>

emmm,这代码可谓一坨(发出来也需要些勇气啊。。)

大家如果有自己的写的规范代码就用自己的(hhh)

那么,我们开始前面的三部曲:搭建页面以及完成,可以开始绑定数据与事件了。

  1. <script setup>
  2. import {ref} from 'vue';
  3. const loginData = ref({
  4. username: '',
  5. password: '',
  6. isRead: false,
  7. })

先引入ref,然后创建loginData,然后v-model绑定数据

  1. <template>
  2. <div class="container">
  3. <div class="login-box">
  4. <a-form
  5. :model="loginData"
  6. :style="{ width: '600px' }"
  7. @submit="handleSubmit"
  8. class="input-box"
  9. >
  10. <h2 style="margin-bottom: 60px">Login</h2>
  11. <a-form-item
  12. field="name"
  13. tooltip="Please enter username"
  14. label="账号"
  15. class="element"
  16. :rules= "rules"
  17. >
  18. <a-input
  19. v-model="loginData.username"
  20. placeholder="please enter your username..."
  21. style="margin-right: 40px"
  22. />
  23. </a-form-item>
  24. <a-form-item field="post" label="密码" class="element" :rules= "rules">
  25. <a-input
  26. v-model="loginData.password"
  27. placeholder="please enter your password..."
  28. style="margin-right: 40px"
  29. />
  30. </a-form-item>
  31. <a-form-item field="isRead">
  32. <a-checkbox v-model="loginData.isRead">
  33. I have read the manual
  34. </a-checkbox>
  35. </a-form-item>
  36. <a-form-item>
  37. <a-button html-type="submit" class="input-box">Submit</a-button>
  38. </a-form-item>
  39. <div class="register-link">
  40. <a href="#">Don't have an account? Create Now!</a>
  41. </div>
  42. </a-form>
  43. </div>
  44. </div>
  45. </template>
  46. <script setup>
  47. import {ref} from 'vue';
  48. const loginData = ref({
  49. username: '',
  50. password: '',
  51. isRead: false,
  52. })
  53. const rules = [{
  54. validator: (value, cb) => {
  55. return new Promise(resolve => {
  56. window.setTimeout(() => {
  57. if (value !== ' ') {
  58. cb('content not empty')
  59. }
  60. resolve()
  61. }, 1000)
  62. })
  63. }
  64. }];
  65. </script>
  66. <style scoped>
  67. * {
  68. margin: 0;
  69. padding: 0;
  70. box-sizing: border-box;
  71. font-family: "Poppins", sans-serif;
  72. display: flex;
  73. justify-content: center;
  74. }
  75. .container {
  76. width: 100%;
  77. height: 100vh;
  78. background: url("../assets/background.jpg") no-repeat;
  79. background-size: cover;
  80. background-position: center;
  81. display: flex;
  82. justify-content: center;
  83. align-items: center;
  84. }
  85. .container .login-box {
  86. position: relative;
  87. width: 500px;
  88. height: 580px;
  89. background-color: transparent;
  90. border: 2px solid rgba(255, 255, 255, 0.5);
  91. border-radius: 20px;
  92. display: flex;
  93. justify-content: center;
  94. align-items: center;
  95. backdrop-filter: blur(15px);
  96. }
  97. .login-box h2 {
  98. font-size: 28px;
  99. color: #fff;
  100. text-align: center;
  101. }
  102. .login-box .input-box {
  103. position: relative;
  104. width: 310px;
  105. margin: 30px 0;
  106. }
  107. .input-box input {
  108. width: 80%;
  109. height: 60px;
  110. background: transparent;
  111. border: none;
  112. outline: none;
  113. font-size: 16px;
  114. color: #fff;
  115. padding: 0 2px 0 5px;
  116. }
  117. .input-box input::placeholder {
  118. color: #f9f9f9;
  119. }
  120. .input-box .icon {
  121. position: absolute;
  122. right: 8px;
  123. color: #fff;
  124. font-size: 16px;
  125. line-height: 25px;
  126. }
  127. .login-box .remember-forget {
  128. margin: -15px 0 15px;
  129. font-size: 15px;
  130. color: #fff;
  131. display: flex;
  132. justify-content: space-between;
  133. }
  134. .remember-forget label input {
  135. margin-right: 30px;
  136. }
  137. .login-box button {
  138. width: 100%;
  139. height: 40px;
  140. background: #fff;
  141. border: none;
  142. outline: none;
  143. border-radius: 40px;
  144. cursor: pointer;
  145. font-size: 16px;
  146. color: #000;
  147. transition: all 0.5s;
  148. }
  149. .login-box button:hover {
  150. background: #1f73c9;
  151. color: #fff;
  152. }
  153. .login-box .register-link {
  154. font-size: 15px;
  155. color: #fff;
  156. text-align: center;
  157. margin: 5px 0 5px;
  158. }
  159. .remember-forget a,
  160. .register-link a {
  161. color: #fff;
  162. text-decoration: none;
  163. }
  164. .remember-forget a:hover,
  165. .register-link a:hover {
  166. text-decoration: underline;
  167. }
  168. /* Responsive Design */
  169. @media (max-width: 460px) {
  170. .container .login-box {
  171. width: 350px;
  172. }
  173. .login-box .input-box {
  174. width: 290px;
  175. }
  176. }
  177. @media (max-width: 360px) {
  178. .container .login-box {
  179. width: 100%;
  180. height: 100vh;
  181. border: none;
  182. }
  183. }
  184. .element {
  185. margin: 20px 0;
  186. }
  187. </style>

这里可以添加一个校验规则,

在组件库这里找一下表单的校验规则

  1. <script setup>
  2. import {ref} from 'vue';
  3. const loginData = ref({
  4. username: '',
  5. password: '',
  6. isRead: false,
  7. })
  8. const rules = [{
  9. validator: (value, cb) => {
  10. return new Promise(resolve => {
  11. window.setTimeout(() => {
  12. if (value === ' ') {
  13. cb('content not empty')
  14. }
  15. resolve()
  16. }, 1000)
  17. })
  18. }
  19. }];
  20. </script>

随便定义了一个,大家可以自己定义看看,(emmm,这里我感觉element-ui的校验规则更好一丢丢)。

好了,既然定义好了登录界面,就可以试试向后端发起请求了。

这里开始在api文件夹下面创建一个文件user.js然后编写一个登录接口函数

  1. import request from '../utils/request'
  2. //创建一个调用登录接口函数
  3. export const userLoginService = (loginData) =>{
  4. //用urlSearchParams完成传递
  5. const params = new URLSearchParams()
  6. for(let key in loginData){
  7. params.append(key,loginData[key]);
  8. }
  9. return request.post('/user/login',params);
  10. }

定义之后就去登录页调用

  1. <a-form-item>
  2. <a-button html-type="submit" class="input-box" @click="login"
  3. >Submit</a-button
  4. >
  5. </a-form-item>

在submit提交这里加上@click="login"

然后定义方法:(获取信息,如果msg提示信息不为0,则显示消息,为0就表示登陆成功)

  1. const login = async()=>{
  2. let result = await userLoginService(loginData.value);
  3. alert(result.msg?result.msg:'登录成功');
  4. }

不过,这里用浏览器默认的alert感觉不太美观啊,毕竟都用组件库了,

消息类型:就决定是你了!

引入一手修改代码,

  1. <script setup>
  2. import { h } from 'vue';
  3. import { IconExclamationCircleFill } from '@arco-design/web-vue/es/icon';
  4. import { ref } from "vue";
  5. import {userLoginService} from '../api/user'
  6. const loginData = ref({
  7. username: "",
  8. password: "",
  9. isRead: false,
  10. });
  11. const rules = [
  12. {
  13. validator: (value, cb) => {
  14. return new Promise((resolve) => {
  15. window.setTimeout(() => {
  16. if (value !== " ") {
  17. cb("content not empty");
  18. }
  19. resolve();
  20. }, 1000);
  21. });
  22. },
  23. },
  24. ];
  25. const renderIcon = () => h(IconExclamationCircleFill);
  26. const login = async()=>{
  27. let result = await userLoginService(loginData.value);
  28. renderIcon(result.msg?result.msg:'登录成功');
  29. }
  30. </script>

好,感觉这样也就差不多了,下面展示一下登录页代码

  1. <template>
  2. <div class="container">
  3. <div class="login-box">
  4. <a-form
  5. :model="loginData"
  6. :style="{ width: '600px' }"
  7. @submit="handleSubmit"
  8. class="input-box"
  9. >
  10. <h2 style="margin-bottom: 60px">Login</h2>
  11. <a-form-item
  12. field="name"
  13. tooltip="Please enter username"
  14. label="账号"
  15. class="element"
  16. :rules="rules"
  17. >
  18. <a-input
  19. v-model="loginData.username"
  20. placeholder="please enter your username..."
  21. style="margin-right: 40px"
  22. />
  23. </a-form-item>
  24. <a-form-item field="post" label="密码" class="element" :rules="rules">
  25. <a-input
  26. v-model="loginData.password"
  27. placeholder="please enter your password..."
  28. style="margin-right: 40px"
  29. />
  30. </a-form-item>
  31. <a-form-item field="isRead">
  32. <a-checkbox v-model="loginData.isRead">
  33. I have read the manual
  34. </a-checkbox>
  35. </a-form-item>
  36. <a-form-item>
  37. <a-button html-type="submit" class="input-box" @click="login"
  38. >Submit</a-button
  39. >
  40. </a-form-item>
  41. <div class="register-link">
  42. <a href="#">Don't have an account? Create Now!</a>
  43. </div>
  44. </a-form>
  45. </div>
  46. </div>
  47. </template>
  48. <script setup>
  49. import { h } from 'vue';
  50. import { IconExclamationCircleFill } from '@arco-design/web-vue/es/icon';
  51. import { ref } from "vue";
  52. import {userLoginService} from '../api/user'
  53. const loginData = ref({
  54. username: "",
  55. password: "",
  56. isRead: false,
  57. });
  58. const rules = [
  59. {
  60. validator: (value, cb) => {
  61. return new Promise((resolve) => {
  62. window.setTimeout(() => {
  63. if (value !== " ") {
  64. cb("content not empty");
  65. }
  66. resolve();
  67. }, 1000);
  68. });
  69. },
  70. },
  71. ];
  72. const renderIcon = () => h(IconExclamationCircleFill);
  73. const login = async()=>{
  74. let result = await userLoginService(loginData.value);
  75. renderIcon(result.msg?result.msg:'登录成功');
  76. }
  77. </script>
  78. <style scoped>
  79. * {
  80. margin: 0;
  81. padding: 0;
  82. box-sizing: border-box;
  83. font-family: "Poppins", sans-serif;
  84. display: flex;
  85. justify-content: center;
  86. }
  87. .container {
  88. width: 100%;
  89. height: 100vh;
  90. background: url("../assets/background.jpg") no-repeat;
  91. background-size: cover;
  92. background-position: center;
  93. display: flex;
  94. justify-content: center;
  95. align-items: center;
  96. }
  97. .container .login-box {
  98. position: relative;
  99. width: 500px;
  100. height: 580px;
  101. background-color: transparent;
  102. border: 2px solid rgba(255, 255, 255, 0.5);
  103. border-radius: 20px;
  104. display: flex;
  105. justify-content: center;
  106. align-items: center;
  107. backdrop-filter: blur(15px);
  108. }
  109. .login-box h2 {
  110. font-size: 28px;
  111. color: #fff;
  112. text-align: center;
  113. }
  114. .login-box .input-box {
  115. position: relative;
  116. width: 310px;
  117. margin: 30px 0;
  118. }
  119. .input-box input {
  120. width: 80%;
  121. height: 60px;
  122. background: transparent;
  123. border: none;
  124. outline: none;
  125. font-size: 16px;
  126. color: #fff;
  127. padding: 0 2px 0 5px;
  128. }
  129. .input-box input::placeholder {
  130. color: #f9f9f9;
  131. }
  132. .input-box .icon {
  133. position: absolute;
  134. right: 8px;
  135. color: #fff;
  136. font-size: 16px;
  137. line-height: 25px;
  138. }
  139. .login-box .remember-forget {
  140. margin: -15px 0 15px;
  141. font-size: 15px;
  142. color: #fff;
  143. display: flex;
  144. justify-content: space-between;
  145. }
  146. .remember-forget label input {
  147. margin-right: 30px;
  148. }
  149. .login-box button {
  150. width: 100%;
  151. height: 40px;
  152. background: #fff;
  153. border: none;
  154. outline: none;
  155. border-radius: 40px;
  156. cursor: pointer;
  157. font-size: 16px;
  158. color: #000;
  159. transition: all 0.5s;
  160. }
  161. .login-box button:hover {
  162. background: #1f73c9;
  163. color: #fff;
  164. }
  165. .login-box .register-link {
  166. font-size: 15px;
  167. color: #fff;
  168. text-align: center;
  169. margin: 5px 0 5px;
  170. }
  171. .remember-forget a,
  172. .register-link a {
  173. color: #fff;
  174. text-decoration: none;
  175. }
  176. .remember-forget a:hover,
  177. .register-link a:hover {
  178. text-decoration: underline;
  179. }
  180. /* Responsive Design */
  181. @media (max-width: 460px) {
  182. .container .login-box {
  183. width: 350px;
  184. }
  185. .login-box .input-box {
  186. width: 290px;
  187. }
  188. }
  189. @media (max-width: 360px) {
  190. .container .login-box {
  191. width: 100%;
  192. height: 100vh;
  193. border: none;
  194. }
  195. }
  196. .element {
  197. margin: 20px 0;
  198. }
  199. </style>

好了,今天的前端就忙碌到这里吧(下一篇文章再见)。

总结一下:1.完成了前端初始化4步,2.完成了全局页面的布局,3.完成了搜索页的代码,和登录页的代码。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号