首页IT科技vue框架vant官网(vue3+vite+vant4手机端项目实录)

vue框架vant官网(vue3+vite+vant4手机端项目实录)

时间2025-05-04 16:30:31分类IT科技浏览3430
导读:目录...

目录

一           、项目介绍

二                、项目的搭建

1.vite的安装

2.启动vite项目

 3.vant4的引入与使用

3.1安装指令

npm i vant

3.2引入vant4

4.路由router的引入

4.1安装指令

4.2路由配置

5.路径别名设置

6.json-server

6.1json-server安装

6.2json-server启动项配置

6.3启动命令:npm run mock

7.axios请求数据

7.1安装axios依赖

7.2简单封装axios

7.3项目使用axios

三     、登录注册模块

1.登录页面

2.注册页面

3.修改密码

4.开始页面

四      、用户端模块

1.职位模块

 1.1职位详情页面

2.求职申请页面

2.1求职申请详情页

3.我的页面

3.1我的页面信息修改

3.2我的在线简历页面

         3.3我的意见反馈模块

 四                、总结

一          、项目介绍

一款在线招聘App           ,有四个模块分别为登录注册模块      、用户端模块                 、企业端模块          、管理员模块

二、项目的搭建

1.vite的安装

npm init vite@latest my-vue-app --template vue
# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue

2.启动vite项目

指令:npm run dev 

 3.vant4的引入与使用

vant4是轻量                 、可定制的移动端 Vue 组件库

3.1安装指令

npm i vant

3.2引入vant4

main.js

import { createApp } from vue import ./style.css import App from ./App.vue import vant from vant; import { Icon } from vant; import vant/lib/index.css; // 导入router配置文件 import router from "./router" // 导入阿里图标 import ./assets/font/iconfont.css // 导入vuex import store from ./store createApp(App).use(router).use(vant).use(Icon).use(store).mount(#app)

4.路由router的引入

4.1安装指令

npm install vue-router@4

4.2路由配置

router/index.js
//1. 导入vue-router相关函数 import { createRouter, createWebHashHistory } from "vue-router" // 2.路由规则 const routes = [ {      path:"路由地址",      name:"路由名称",      component:组件名称   } ] // 3.路由对象实例化 const router = createRouter({    history: createWebHashHistory(),    routes }) // 暴露导出 export default router
main.js 
import { createApp } from vue import ./style.css import App from ./App.vue import vant from vant; import { Icon } from vant; import vant/lib/index.css; // 导入router配置文件 import router from "./router" // 导入阿里图标 import ./assets/font/iconfont.css // 导入vuex import store from ./store createApp(App).use(router).use(vant).use(Icon).use(store).mount(#app)

5.路径别名设置

vite.config.js 文件
import vue from @vitejs/plugin-vue import { defineConfig } from vite import WindiCSS from vite-plugin-windicss // 1.导入node的path路径模块 import path from "path" // https://vitejs.dev/config/ export default defineConfig({  resolve: {    alias: {      // 配置别名      "~": path.resolve(__dirname, "src")   } } })

6.json-server

6.1json-server安装

npm install json-server

6.2json-server启动项配置

在src的同级目录先创建文件夹mock                ,并创建mock/db.json文件,添加数据

{ "infomation": [ { "id": 1, "title": "json-server 的第1条数据", "desc": "奥特曼不想打小怪兽     ,明明可以做好朋友的", "author": "被奥特曼打了很久的怪兽" }, { "id": 2, "title": "json-server 的第2条数据", "desc": "葫芦娃不想去救爷爷      ,一个一个的去送不好", "author": "种出七个葫芦的爷爷" }, { "id": 1, "title": "json-server 的第一条数据", "desc": "王者荣耀其实不是很好玩                ,这并不是我内心的真话", "author": "想玩游戏的我" } ], "infomation2": [ { "id": 11, "title": "json-server 的第11条数据", "desc": "奥特曼不想打小怪兽          ,明明可以做好朋友的", "author": "被奥特曼打了很久的怪兽" }, { "id": 12, "title": "json-server 的第12条数据", "desc": "葫芦娃不想去救爷爷      ,一个一个的去送不好", "author": "种出七个葫芦的爷爷" }, { "id": 12, "title": "json-server 的第13条数据", "desc": "王者荣耀其实不是很好玩                 ,这并不是我内心的真话", "author": "想玩游戏的我" } ] }

(举例数据)

6.3启动命令:npm run mock

7.axios请求数据

7.1安装axios依赖

npm install axios

7.2简单封装axios

在src文件在下创建utils文件夹          ,在utils里创建 http.js文件

//引入安装好的axios插件 import axios from "axios"; // 查询数据 const get = (url) => { return axios.get(url); }; // 添加数据 const post = (url, data) => { return axios.post(url, data); }; // 修改数据 const put = (url, data) => { return axios.put(url, data); }; // 局部修改 const patch = (url, data) => { return axios.patch(url, data); }; // 删除数据 const del = (url) => { return axios.delete(url); }; //将二次封装好的axios导出 export { get, post, put, del, patch };

7.3项目使用axios

项目的端口为8080,然后json文件的端口为3000,这样就会涉及到跨域                 ,解决跨域的方式很多种                ,此处讲解一下配置proxy代理 在根目录下创建文件vue.config.js,覆盖webpack的一些内容           。

vite.config.js

server: { proxy: { /api: { target: http://localhost:3000, changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, ) } } }

三                、登录注册模块

1.登录页面

代码:

<template> <van-nav-bar title="登录" left-text="返回" left-arrow @click-left="onClickLeft" /> <div class="login"> <img :src="img" alt="" /> <van-form @submit="onSubmit"> <van-cell-group inset> <van-field v-model="username" left-icon="phone-o" name="username" placeholder="手机号码" :rules="[{ required: true, message: 请填写用户名 }]" /> <van-field v-model="password" left-icon="manager-o" type="password" name="password" placeholder="密码" :rules="[{ required: true, message: 请填写密码 }]" /> </van-cell-group> <div style="margin: 16px"> <van-button round block type="primary" native-type="submit"> 提交 </van-button> </div> </van-form> </div> <div class="find"> <router-link to="/enroll"><span>注册新用户</span></router-link> <router-link to="/verify"><span>找回密码</span></router-link> </div> <div class="ways"> <span>其他登录方式</span> <div> <span class="iconfont"></span> <span class="iconfont"></span> <span class="iconfont"></span> </div> </div> </template> <!-- 逻辑层 --> <script setup> import { reactive, ref } from "vue"; import { get, post, put, del } from "~/axios/http"; import { showDialog } from "vant"; // 本地图片引入 import img from "../../assets/images/avatar.svg"; // 导入useRouter方法 import { useRouter } from "vue-router"; const router = useRouter(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; // 表单 const username = ref(""); const password = ref(""); //点击登录按钮事件 async function onSubmit(values) { console.log(values); //axios调用json-server数据 let res = await get("/api/infomation"); //foreach循环判断填入的手机号和密码是否正确 res.data.forEach((element) => { if ( element.iphone == values.username && element.password == values.password ) { //本地存储数据的id值 localStorage.setItem("key", JSON.stringify(element.id)); router.push("/start"); throw new Error(); } else { username.value = ""; password.value = ""; } }); } </script> <!-- 样式层 --> <style scoped> .login { width: 100%; margin-top: 22.6667vw; } .login img { margin-left: 50vw; transform: translate(-50%, 0); } .find { display: flex; width: 70%; margin: 0 auto; justify-content: space-between; } .find span { color: #0079fe; } .ways { width: 80%; margin: 7.6667vw auto; text-align: center; } .ways > span { display: block; margin-bottom: 5.3333vw; color: #999999; } .ways div { display: flex; width: 80%; margin: 0 auto; justify-content: space-around; } .ways div span { font-size: 8.3333vw; } </style>

效果图:

登录模块静态页面主要使用vant4组件库中的组件           ,主要实现了通过vant表单的数据提交和axios方法获取本地数据来判断手机号与密码是否正确                。同时成功就通过路由跳转

2.注册页面

代码:

<!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-12 10:03:12 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-03 14:08:54 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\login\Login.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: "; // 导入useRouter方法 import { useRouter } from "vue-router"; const router = useRouter(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; // 表单 const username = ref(""); const captcha = ref(""); const password = ref(""); const passwordT = ref(""); const checked = ref(true); async function onSubmit(values) { //两次输入密码一致 if (values.password == values.passwordT) { let res = await get("/api/infomation"); console.log(res); res.data.some((element) => { if (element.iphone == values.username) { showDialog({ title: "提示", message: "手机号已被注册", }); } else if (values.password.length < 6 && values.passwordT.length < 6) { showDialog({ title: "提示", message: "密码不低于六位", }); } else { //增加数据 let res3 = post("/api/infomation", { iphone: values.username, password: values.password, name: "", gender: "", state: "", degree: "", num1: [], num2: [], num3: [], num4: [], num5:[], num6:[], num7:[], img:"" }); router.push("/login"); throw new Error(); } }); } else { showDialog({ title: "提示", message: "确定密码跟密码不一致", }); } } </script> <!-- 样式层 --> <style scoped> .login { width: 100%; margin-top: 12.6667vw; } .login img { margin-left: 50vw; transform: translate(-50%, 0); } .find { width: 70%; margin: 0 auto; } .find span { display: block; width: 100%; color: #0079fe; text-align: center; } .ways { width: 80%; margin: 7.6667vw auto; text-align: center; } .ways > span { display: block; margin-bottom: 5.3333vw; color: #999999; } .ways div { display: flex; width: 80%; margin: 0 auto; justify-content: space-around; } .ways div span { font-size: 8.3333vw; } a { color: #0079fe; } </style>

效果图:

注册模块静态页面主要使用vant4组件库中的组件                ,主要实现了通过vant表单的数据提交和axios方法获取本地数据来判断两次密码是否一致     ,一致就通过axios增加本地数据     。验证码功能未实现

3.修改密码

代码:

<!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-14 15:25:58 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-05 22:52:02 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\login\Verify.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE --> <!-- 视图层 --> <template> <van-nav-bar title="验证" left-text="返回" left-arrow @click-left="onClickLeft" /> <van-tabs v-model:active="active" title-active-color="#0079FE" color="#fff"> <van-tab title="1.验证手机号码"> <van-form @submit="onSubmit"> <van-cell-group inset> <van-field v-model="username" left-icon="phone-o" name="username" placeholder="请输入注册手机号码" :rules="[{ required: true, message: 请填写手机号码 }]" /> <van-field v-model="password" center left-icon="sign" name="password" placeholder="请输入验证码" :rules="[{ required: true, message: 请填写验证码 }]" > <template #button> <van-button size="small" type="primary">发送验证码</van-button> </template> </van-field> </van-cell-group> <div style="margin: 16px"> <van-button round block type="primary" native-type="submit"> 下一步 </van-button> </div> </van-form> </van-tab> <van-tab title="2.设置新密码" disabled></van-tab> </van-tabs> </template> <!-- 逻辑层 --> <script setup> import { get, post, put, del } from "~/axios/http"; import { showDialog } from "vant"; import { ref } from "vue"; // 导入useRouter方法 import { useRouter } from "vue-router"; const router = useRouter(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; // 表单 const username = ref(""); const password = ref(""); async function onSubmit(values) { let res = await get("/api/infomation"); res.data.forEach((element) => { if (element.iphone == values.username) { //传出id值 router.push({ path: "/revise", query: { id: element.id, }, }); throw new Error(); } else { username.value = ""; password.value = ""; } }); } </script> <!-- 样式层 --> <style scoped> </style> <!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-14 15:25:58 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-02 10:43:38 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\login\Verify.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE --> <!-- 视图层 --> <template> <van-nav-bar title="设置密码" left-text="返回" left-arrow @click-left="onClickLeft" /> <van-tabs v-model:active="active" title-active-color="#0079FE" color="#fff"> <van-tab title="1.验证手机号码" disabled> </van-tab> <van-tab title="2.设置新密码"> <van-form @submit="onSubmit"> <van-cell-group inset> <van-field v-model="password" left-icon="manager-o" name="password" type="password" placeholder="请设置6-20位新的登录密码" :rules="[{ required: true, message: 请填写新密码 }]" /> <van-field v-model="passwordT" type="password" left-icon="manager-o" name="passwordT" placeholder="请再次输入新的登录密码" :rules="[{ required: true, message: 请填写新密码 }]" > </van-field> </van-cell-group> <div style="margin: 16px"> <van-button round block type="primary" native-type="submit"> 提交 </van-button> </div> </van-form> </van-tab> </van-tabs> </template> <!-- 逻辑层 --> <script setup> import { get, post, put, del,patch } from "~/axios/http"; import { showDialog } from "vant"; import { ref, reactive } from "vue"; // 导入useRouter方法 import { useRouter, useRoute } from "vue-router"; const router = useRouter(); const route = useRoute(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; // 表单 const password = ref(""); const passwordT = ref(""); async function onSubmit(values) { //route方法传入id值 let data = reactive({ id: route.query.id, }); if (values.password.length < 6 && values.passwordT.length < 6) { showDialog({ title: "提示", message: "密码不低于六位", }); } else if (values.password == values.passwordT) { let res2 = await get(`/api/infomation/${data.id}`); let res = await patch(`/api/infomation/${data.id}`, { password: values.password, }); showDialog({ title: "提示", message: "修改成功", }); router.push("/login"); } else { showDialog({ title: "提示", message: "两次密码不一致", }); } } </script> <!-- 样式层 --> <style scoped> </style>

效果图:

修改密码由两个页面组成           ,通过输入手机号用axios得到本地数据才能进入修改密码页面                ,同时通过router方法传进一个id值同时用route方法接受id值     ,修改指定账号的密码

4.开始页面

代码:

<!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-14 18:55:58 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-01 09:59:13 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\login\Start.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE --> <!-- 视图层 --> <template> <van-nav-bar title="注册" left-text="返回" left-arrow @click-left="onClickLeft" /> <div class="user" @click="runUser">我是求职者</div> <div class="enterprise" @click="runEnterprise">我是招聘者</div> <div class="admin">我是管理员</div> <div></div> </template> <!-- 逻辑层 --> <script setup> // 导入useRouter方法 import { useRouter } from "vue-router"; const router = useRouter(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; // 跳转用户端 const runUser = () => { router.push("/user"); }; //跳转企业端 const runEnterprise = () => { router.push("/tabber"); }; </script> <!-- 样式层 --> <style scoped> .user { background-color: rgba(0, 121, 254, 1); width: 80%; height: 18.6667vw; border-radius: 1.3333vw; color: #fff; text-align: center; line-height: 18.6667vw; margin: 10.3333vw auto; margin-top: 23.3333vw; } .enterprise { background-color: rgba(75, 216, 99, 1); width: 80%; height: 18.6667vw; border-radius: 1.3333vw; color: #fff; text-align: center; line-height: 18.6667vw; margin: 10.3333vw auto; } .admin { background-color: rgba(254, 148, 0, 1); width: 80%; height: 18.6667vw; border-radius: 1.3333vw; color: #fff; text-align: center; line-height: 18.6667vw; margin: 10.3333vw auto; } </style>

效果图:

该页面主要进行三个端口的跳转      ,通过router路由的push方法进行路由跳转

四、用户端模块

分为职位           、求职申请                、我的三个主页面

1.职位模块

代码:

<!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-14 19:31:55 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-02 15:58:50 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\user\Posts.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE --> <!-- 视图层 --> <template> <div class="body"> <van-nav-bar title="岗位" left-text="返回" left-arrow @click-left="onClickLeft" /> <van-search v-model="value" placeholder="请输入搜索关键词" @search="onSearch" /> <div class="classify"> <div> <span v-for="(item, index) in arr" :key="index" @click="change(index)" :class="{ active: index == nowIndex }" >{{ item }}</span > </div> <van-button type="default">筛选</van-button> </div> <div class="mainstay"> <div class="main" v-for="(item, index) in arr1" :key="index" v-if="nowIndex == 0" @click="runDetail(item.id)" v-show="item.fell == recommend" > <div> <span>{{ item.name }}</span> <span>{{ item.money }}</span> </div> <div> {{ item.city }}<span>|</span>{{ item.time }}<span>|</span >{{ item.degree }} </div> <div> <span>{{ item.company }}</span> <span>{{ item.people }}</span> </div> </div> <div class="main" v-for="(item, index) in arr1" :key="index" v-if="nowIndex == 1" v-show="item.fell == hot" @click="runDetail(item.id)" > <div> <span>{{ item.name }}</span> <span>{{ item.money }}</span> </div> <div> {{ item.city }}<span>|</span>{{ item.time }}<span>|</span >{{ item.degree }} </div> <div> <span>{{ item.company }}</span> <span>{{ item.people }}</span> </div> </div> </div> </div> </template> <!-- 逻辑层 --> <script setup> import { get, post, put, del } from "~/axios/http"; import { reactive, ref, computed } from "vue"; import { useRouter, useRoute } from "vue-router"; const router = useRouter(); const route = useRoute(); const value = ref(""); const arr = ref(["推荐", "热门职位"]); const nowIndex = ref(0); const change = (index) => { nowIndex.value = index; }; const arr1 = ref([]); async function sendRequest() { let res = await get("/api/infomation2"); arr1.value = res.data; } sendRequest(); async function onSearch(val) { console.log(val); //模糊搜索 let res2 = await get(`/api/infomation2?name_like=${val}`); console.log(res2.data); arr1.value = res2.data; } const runDetail = (value) => { router.push({ path: "/postsDetail", query: { id: value, }, }); }; </script> <!-- 样式层 --> <style scoped> .body { background-color: #f2f2f2; } .classify { display: flex; width: 100%; align-items: center; margin: 0 auto; justify-content: space-around; background-color: #fff; } .classify div { width: 70%; } .classify div span:nth-child(1) { margin-right: 5.3333vw; } .active { color: #0079fe; } .mainstay { padding-bottom: 13.3333vw; } .main { background-color: #fff; overflow: hidden; margin-bottom: 2.6667vw; } .main div:nth-child(1) { display: flex; width: 90%; margin: 0 auto; justify-content: space-between; margin-top: 2.6667vw; } .main div:nth-child(1) span:nth-child(2) { font-size: 5.3333vw; color: #0079fe; } .main div:nth-child(2) { margin: 1.6667vw 0; margin-left: 4.8333vw; } .main div:nth-child(2) span { margin: 0 0.8vw; color: #e4e4e4; } .main div:nth-child(3) { margin-left: 4.8333vw; margin-top: 1.6667vw; margin-bottom: 4vw; } .main div:nth-child(3) span:nth-child(1) { margin-right: 5.3333vw; } </style>

效果图:

该页面主要通过v-for进行数据遍历                ,axios.get方法进行数据引用     、搜索栏静态效果主要用vant4组件          ,模糊搜索用了await get(`/api/infomation2?name_like=${val}`)的方法      。

 1.1职位详情页面

代码:

<!-- * @Author: wu07 1732042133@qq.com * @Date: 2023-01-15 18:07:48 * @LastEditors: wu07 1732042133@qq.com * @LastEditTime: 2023-02-03 11:29:04 * @FilePath: \recruitAPP\recruitApp\recruitApp\src\pages\user\PostsDetail.vue * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE --> <!-- 视图层 --> <template> <van-nav-bar title="职位详情" left-text="返回" left-arrow @click-left="onClickLeft" /> <div class="name"> <span>{{ arr.name }}</span> <span>{{ arr.money }}</span> <div> <span>{{ arr.city }}</span ><span>|</span><span>{{ arr.time }}</span ><span>|</span><span>{{ arr.degree }}</span> </div> </div> <div class="introduce"> <span>职位描述</span> <p>{{ arr.introduce }}</p> </div> <div class="company"> <span>公司简介</span> <div> <span>{{ arr.company }}</span ><span>{{ arr.people }}</span> <p>{{ arr.description }}</p> </div> </div> <div class="bt"> <van-button square type="default" @click="change">{{ a }}</van-button> <van-button square type="primary" @click="td">投递简历</van-button> </div> </template> <!-- 逻辑层 --> <script setup> import { get, post, put, del, patch } from "~/axios/http"; import { showDialog } from "vant"; import { ref, reactive } from "vue"; // 导入useRouter方法 import { useRouter, useRoute } from "vue-router"; const router = useRouter(); const route = useRoute(); // 返回上一页 const onClickLeft = () => { router.go(-1); }; const arr = ref({}); const a = ref(""); async function find() { let data = reactive({ id: route.query.id, }); let res2 = await get(`/api/infomation2/${data.id}`); arr.value = res2.data; a.value = res2.data.interest; } find(); const flag = ref(true); async function change() { flag.value = !flag.value; if (flag.value == true) { a.value = "感兴趣"; let data %

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
宁波宁海县最火企业网站搭建(搜索宁海在线)