目录
[① 安装路由vue-router](#① 安装路由vue-router)
[② 安装vuex全局数据管理](#② 安装vuex全局数据管理)
[③ 安装element-plus](#③ 安装element-plus)
[④ 安装element-plus图标](#④ 安装element-plus图标)
[⑤ 安装axios发送请求](#⑤ 安装axios发送请求)
[⑥ 完整main.js代码模板](#⑥ 完整main.js代码模板)
[5. 完整项目代码](#5. 完整项目代码)
废话少说,直接上步骤!
1.先创建一个vite项目
2.下载第三方依赖
① 安装路由vue-router
-- 用于页面跳转切换
npm install vue-router
--安装完之后,在src创建router目录, 在router目录创建index.js文件
--创建完后,在index.js文件中导入以下模板
javascript//vue-router配置文件 //1.从vue-router导入createRouter() 创建路由器对象 import { createRouter, createWebHistory, createWebHashHistory} from 'vue-router' //2.配置路由规则: 给组件绑定url const routes = [ //默认路由 { path:'/', //重定向 redirect:'/index' }, // 这是一个配置路由的示例 { path: "/index", component: ()=>import('../views/index.vue'), name:'indexPage', children:[ //配置子级路径 { // 这是resful风格的url写法 path:'/infor/:id' , component: ()=>import('../views/information.vue'), name:'infor', }, ] }, //配置404的组件 { path:'/:pathMatch(.*)*', component: ()=>import('../views/NotFound.vue'), name:'notFound', } ]; //3.创建路由器对象 const router = createRouter({ routes, //路由规则 history: createWebHashHistory(), linkActiveClass:'active' }); //4. 把路由器对象暴露出去 其他组件文件,导入 export default router;
--最后找到main.js文件,并在里面配置router
② 安装vuex全局数据管理
--通过命令安装vuex
javascriptnpm install vuex
--安装完成后,在src目录下创建store目录, 在store目录创建一个index.js
--然后再index.js文件中导入以下模板,用于配置全局数据
javascript// 导入函数 import { createStore } from "vuex"; // 定义一个状态 const state = { count:0, user:{ id:0, username:'张三', age:13 } } // 修改状态的函数集合 , 不能异步调用 const mutations = { addCount(state,payload){ // 修改state里面的count状态 state.count+=payload.num ; } } // actons : 操作集合(定义事件,让组件触发事件) const actions = { increment(context,payload){ // 发送ajax请求,异步通信 // 它只能调用mutations里面的方法才能修改数据,三个核心对象各司其职(主要是因为mutation不能异步调用,而actions可以,所以我们用actions去调用mutations) context.commit('addCount' , payload) } } // 调用createStore创建Store对象 const store = createStore({ state , mutations, actions }) // 暴露store对象 export default store //把它挂在到mian.js中去,就可以全局使用它
--最后在main.js文件里面配置store
③ 安装element-plus
--使用命令安装element-plus
javascriptnpm install element-plus
-- 然后在main.js文件中配置
④ 安装element-plus图标
--命令行安装
javascriptnpm install @element-plus/icons-vue
--在main.js配置
javascriptimport * as ElementPlusIconsVue from '@element-plus/icons-vue' for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) }
⑤ 安装axios发送请求
--使用命令安装axios和qs
javascriptnpm install axios npm install qs
-- 在src目录创建一个http目录, 创建两个文件
--一个是 axios实例配置文件: config.js
并且在里面配置如下模板:
javascript//axios的配置文件 export default { method: 'get', // 基础url前缀 baseUrl: 'http://localhost:8080', // 请求头信息 headers: { //默认的请求context-type: application/json 'Content-Type': 'application/json;charset=UTF-8' }, // 参数 data: {}, // 设置超时时间 timeout: 10000, // 携带凭证 是否携带cookie withCredentials: true, // 返回数据类型 responseType: 'json' }
--另外一个封装axios 工具库的文件 request.js
并且在里面配置如下模板:
javascriptimport { ElLoading,ElMessage } from 'element-plus' import axios from 'axios' import qs from 'qs' //把json进行序列化成key/value import config from './config' import $router from '../router' const instance = axios.create({ baseURL: config.baseUrl, headers: config.headers, timeout: config.timeout, withCredentials: config.withCredentials }) // request 拦截器 instance.interceptors.request.use( config => { let token = sessionStorage.getItem("token"); // 带上token if (token) { config.headers.token = token } return config }); const request = async function (loadtip, query) { let loading if (loadtip) { loading = ElLoading.service({ lock: true, text: '正在加载...', background: 'rgba(0, 0, 0, 0.7)', }) } const res = await instance.request(query) if (loadtip) { loading.close() } if (res.data.meta.status === 401) { //ElMessage.error(); $router.push({ path: '/login' }) return Promise.reject(res.data) //reject() catch捕获 } else if (res.data.meta.status === 500) { return Promise.reject(res.data) } else if (res.data.meta.status === 501) { return Promise.reject(res.data) } else if (res.data.meta.status === 502) { $router.push({ path: '/login' }) return Promise.reject(res.data) } else { return Promise.resolve(res.data) // then() } /* .catch(e => { if (loadtip) { loading.close() } return Promise.reject(e.msg) }) */ } const get = function (url, params) { const query = { url: url, method: 'get', withCredentials: true, timeout: 30000, params: params, //params: queryString headers: { 'request-ajax': true } } return request(false, query) } const post = function (url, params) { const query = { url: url, method: 'post', withCredentials: true, timeout: 30000, data: params, //请求体 headers: { 'Content-Type': 'application/json', 'request-ajax': true } } return request(false, query) } const postWithLoadTip = function (url, params) { const query = { url: url, method: 'post', withCredentials: true, timeout: 30000, data: params, headers: { 'Content-Type': 'application/json', 'request-ajax': true } } return request(true, query) } const postWithOutLoadTip = function (url, params) { const query = { url: url, method: 'post', withCredentials: true, timeout: 30000, data: params, headers: { 'Content-Type': 'application/json', 'request-ajax': true } } return request(false, query) } const postWithUrlEncoded = function (url, params) { const query = { url: url, method: 'post', withCredentials: true, timeout: 30000, data: qs.stringify(params), //params:json qs.stringify(json) --> 转换key/value headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'request-ajax': true } } return request(false, query) } const del = function (url, params) { const query = { url: url, method: 'DELETE', withCredentials: true, timeout: 30000, data: params, headers: { 'Content-Type': 'application/json', 'request-ajax': true } } return request(true, query) } const put = function (url, params) { const query = { url: url, method: 'PUT', withCredentials: true, timeout: 30000, data: params, headers: { 'Content-Type': 'application/json', 'request-ajax': true } } return request(true, query) } const form = function (url, params) { const query = { url: url, method: 'post', withCredentials: true, timeout: 30000, data: params, headers: { 'Content-Type': 'multipart/form-data', 'request-ajax': true } } return request(false, query) } export default { post, postWithLoadTip, postWithOutLoadTip, postWithUrlEncoded, get, form, del, put }
--最后在在main.js配置request.js文件
⑥ 完整main.js代码模板
javascriptimport { createApp } from 'vue' import './style.css' import App from './App.vue' const app = createApp(App) // 配置路由 import router from './router' app.use(router) // 配置vuex import store from './store' app.use(store) // 配置element-plus import ElementPlus from 'element-plus' import '../node_modules/element-plus/dist/index.css' app.use(ElementPlus) // 配置element-plus图标 import * as ElementPlusIconsVue from '../node_modules/@element-plus/icons-vue' for (const [key, component] of Object.entries(ElementPlusIconsVue)) { createApp(App).component(key, component) } // 配置axios import $http from './http/request.js' app.config.globalProperties.$http = $http // 注册一个全局路由守卫 router.beforeEach((to, from) => { console.log("to:"+to) return true }); app.mount('#app')
3.开发组件
组件分类:
局部功能组件: 放在src/components目录下面
页面/视图组件: 放在src/views(pages)目录下面
组合式api获取相关对象:--组合式不能用this得到当前对象,只能导入。
javascript// router route //第一步 从vue-router导入 useRoute() useRouter() import { useRoute, useRouter } from 'vue-router' //第二步: 调用函数useRouter() 得到router //得到路由对象 const router = useRouter(); //store对象 //第一步 从vuex导入 useStore() import {useStore} from 'vuex' //第二步:调用useStore得到store对象 const store = useStore();
4.登陆页面开发用例
① 登录页面开发: Login.vue
html<template> <div class="login"> <div class="login-context"> <!--头部图片--> <div class="login-logo"> <img src="../assets/vue.svg" alt=""> </div> <!--form表单--> <el-form :model="loginForm" :rules="loginFormRul" ref="loginFormRef" label-width="100px" class="login-box"> <el-form-item label="用户名:" prop="username"> <el-input v-model="loginForm.username"></el-input> </el-form-item> <el-form-item label="密码:" prop="password"> <el-input type="password" v-model="loginForm.password"></el-input> </el-form-item> <el-form-item> <el-col :span="12"> <el-form-item prop="captcha"> <el-input type="test" v-model="loginForm.captcha" auto-complete="off" placeholder="验证码, 单击图片刷新" style="width: 100%;"> </el-input> </el-form-item> </el-col> <el-col class="line" :span="1"> </el-col> <el-col :span="11"> <el-form-item> <img style="width: 100%;" class="pointer" :src="src" @click="refreshCaptcha"> </el-form-item> </el-col> </el-form-item> <el-form-item class="login-btn"> <el-button type="primary" @click="login(loginFormRef)">登录</el-button> <el-button @click="reset(loginFormRef)">重置</el-button> </el-form-item> </el-form> </div> </div> </template> <script setup> import { ElMessage } from 'element-plus' import { ref, reactive ,getCurrentInstance } from 'vue' import { useRoute, useRouter } from 'vue-router' import {useStore} from 'vuex' const store = useStore(); const loginForm = reactive({ username: '', password: '', captcha: '', }); const src = ref(''); //得到form对象 const loginFormRef = ref(); //验证规则 const loginFormRul = reactive({ username: [ { required: true, message: '请输入用户名', trigger: 'blur' }, { min: 2, max: 8, message: '长度在 2 到 8 个字符', trigger: 'blur' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 3, max: 8, message: '长度在 3 到 8 个字符', trigger: 'blur' } ] , captcha: [ { required: true, message: '请输入验证码', trigger: 'blur' } ] }); //得到路由对象 const router = useRouter(); //获取当前组件实例对象 const app = getCurrentInstance(); //获取app上的globalProperties属性 const $http = reactive(app.appContext.config.globalProperties.$http); //登录功能 function login(form) { if(!form) return; //提交表单之前进行表单验证 form.validate((valid) => { //校验失败 if (!valid) return; //校验成功 $http.post('login', loginForm).then((response) => { ElMessage({ showClose: true, message: '登录成功', type: 'success', }) //状态保存下来 window.sessionStorage.setItem("token", response.data); //跳转 router.push('/users'); }).catch((error) => { ElMessage({ showClose: true, message: error.meta.msg, type: 'error', }); //清空表单 form.resetFields(); }); }); } //重置功能 function reset(form) { if (!form) return form.resetFields(); } //刷新验证码 function refreshCaptcha() { //防止浏览器缓存 src.value = "http://localhost:8080/captcha.jpg?t=" + new Date().getTime(); } //调用这个函数显示验证码 refreshCaptcha(); </script> <style scoped> .login { height: 100%; background: rgb(43 75 107); } .login-context { width: 450px; height: 300px; background: #fff; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); box-shadow: 0 0 3px 2px #DDD; border-radius: 10px; } .login-logo { width: 150px; height: 150px; position: absolute; top: -80px; left: 50%; margin-left: -75px; border: 1px solid #eee; border-radius: 50%; background-color: #fff; padding: 10px; box-shadow: 0 0 3px 2px #fff; } .login-logo img { width: 100%; height: 100%; border-radius: 50%; background-color: rgb(238, 238, 238); } .login-box { width: 100%; position: absolute; bottom: 0; padding: 0 20px; box-sizing: border-box; } .login-btn { display: flex; justify-content: flex-end; } </style>
② 在router/index.js文件中配置这个路由
javascriptconst routes = [ { path:'/login', component:()=>import('../views/Login.vue'), name:'Login' }, { path:'/', redirect:'/login' } ];
③ 修改APP.vue页面
javascript<script setup> </script> <template> <router-view/> </template> <style scoped> </style>
④ 运行项目
javascriptnpm run dev
⑤ 运行页面效果展示
5. 完整项目代码
完整的项目代码我放在的我的资源《创建一个完整vite前端项目》打包成jar包。