完整创建一个vite前端项目

news2025/2/3 20:59:43

目录

1.先创建一个vite项目

2.下载第三方依赖 

 ① 安装路由vue-router

 ② 安装vuex全局数据管理

③ 安装element-plus  

④ 安装element-plus图标

 ⑤ 安装axios发送请求

⑥ 完整main.js代码模板

3.开发组件

 4.登陆页面开发用例

 5. 完整项目代码


废话少说,直接上步骤!

1.先创建一个vite项目

2.下载第三方依赖 

 ① 安装路由vue-router

       -- 用于页面跳转切换

 npm install vue-router

--安装完之后,在src创建router目录, 在router目录创建index.js文件

--创建完后,在index.js文件中导入以下模板

//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

npm install vuex

--安装完成后,在src目录下创建store目录, 在store目录创建一个index.js

--然后再index.js文件中导入以下模板,用于配置全局数据

// 导入函数
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

npm install element-plus

-- 然后在main.js文件中配置

④ 安装element-plus图标

     --命令行安装

npm install @element-plus/icons-vue

 

--在main.js配置

import * as ElementPlusIconsVue from '@element-plus/icons-vue'

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
  app.component(key, component)
}

 ⑤ 安装axios发送请求

       --使用命令安装axios和qs

npm install axios

npm install qs

-- 在src目录创建一个http目录, 创建两个文件

--一个是 axios实例配置文件: config.js

   并且在里面配置如下模板:

//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

并且在里面配置如下模板:

import { 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代码模板
import { 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得到当前对象,只能导入。

// 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

<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">&nbsp;</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文件中配置这个路由

const routes = [
    {
        path:'/login',
        component:()=>import('../views/Login.vue'),
        name:'Login'
    },
    {
        path:'/',
        redirect:'/login'
    }
];

③ 修改APP.vue页面

<script setup>

</script>

<template>
   <router-view/>
</template>

<style scoped>

</style>

④ 运行项目

npm run dev

⑤ 运行页面效果展示

 5. 完整项目代码

        完整的项目代码我放在的我的资源《创建一个完整vite前端项目》打包成jar包。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1940397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】 string类的模拟实现

目录 一、我们先创建三个文件分别为 String.h&#xff08;声明&#xff09;、String.cpp&#xff08;定义&#xff09;、teat.cpp&#xff08;测试&#xff09; 二、成员函数 构造函数与析构函数 &#x1f31f;string() &#x1f31f;string(const char* str) &#x1f…

探索SideLlama:浏览器中的本地大型语言模型

在这个数字化时代&#xff0c;浏览器扩展程序已经成为我们日常网络体验中不可或缺的一部分。它们不仅为我们提供了便利&#xff0c;还为我们的浏览体验增添了更多的功能和乐趣。今天&#xff0c;我要介绍的是一个全新的Chrome浏览器扩展程序——SideLlama&#xff0c;它能够让你…

SOMEIPSRV_ONWIRE_03: 从请求中复制请求ID到响应消息

测试目的&#xff1a; 确保服务器在生成响应消息时将请求ID从请求消息复制到响应消息。 描述 本测试用例旨在验证DUT&#xff08;Device Under Test&#xff0c;被测试设备&#xff09;在处理SOME/IP请求和生成相应响应时&#xff0c;是否将请求消息中的请求ID正确复制到了响…

苹果相册里的视频删除了怎么恢复?只需3招,轻松拿捏

一个不小心手滑把苹果手机相册里的视频删除了怎么办&#xff1f;删除了是不是再也找不回来了&#xff1f;那些美好的回忆是不是也从此消散了&#xff1f;当然不是&#xff01;苹果手机相册里的视频删除了怎么恢复&#xff1f;小编这里有3个秘诀&#xff0c;可以让它重新出现在你…

中智讯与黄淮学院共建“嵌入式边缘计算创客工坊”正式签约

7月13日&#xff0c;中智讯(武汉)科技有限公司与黄淮学院共建“嵌入式边缘计算创客工坊”正式签约。出席签约仪式的有黄淮学院电子信息学院党委书记魏迎军同志、院长高有堂教授、副院长吴忠林教授、党委副书记从卫东同志及全体教职工&#xff0c;中智讯(武汉)科技有限公司技术副…

Jackson详解

文章目录 一、Jackson介绍二、基础序列化和反序列化1、快速入门2、序列化API3、反序列化API4、常用配置 三、常用注解1、JsonProperty2、JsonAlias3、JsonIgnore4、JsonIgnoreProperties5、JsonFormat6、JsonPropertyOrder 四、高级特性1、处理泛型1.1、反序列化List泛型1.2、反…

Nexus3 批量上传 jar 包、pom文件

Nexus3 Maven 私服搭建及各种使用 详见**Maven私服搭建及各种使用汇总2020** Maven 配置 Nexus 私服 在 Maven 项目中配置 Nexus 私服&#xff0c;需要在项目的 pom.xml 或 maven 的 settings.xml 文件中添加 Nexus 仓库的配置。 示例&#xff1a; 以下是一个项目的 pom.xml…

word 设置目录中英文字母大写改为小写

选中目录右击“字体”&#xff0c;设置“小型大写字母”。

【Django+Vue3 线上教育平台项目实战】Celery赋能:优化订单超时处理与自动化定时任务调度

文章目录 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6;一、Celery⭐1.基本概念及介绍:✨2.使用步骤&#x1f4ab; 二、订单超时 取消订单&#xff08;Celery&#xff09;&#x1f525;具体实现流程&#x1f4d6; 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6; 在构建复…

图解 Hadoop 架构 |Yarn、MapReduce

Hadoop Hadoop 是什么 Hadoop 是由 Apache 基金会所开发&#xff0c;维护的分布式系统基础架构主要解决海量数据的存储和海量数据的分析计算问题广义上来说&#xff0c;Hadoop 通常是指一个更广泛的概念——Hadoop 生态圈&#xff0c;包括 MapReduce&#xff0c;HDFS&#xf…

Python面试宝典第16题:跳跃游戏

题目 给你一个非负整数数组 nums &#xff0c;你最初位于数组的第一个下标 &#xff0c;数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true。否则&#xff0c;返回 false。 示例 1&#xff1a; 输…

Lowpoly Style Alpine Woodlands Environment(高山林地)

v1.1中的新增功能:添加了地形的额外网格。 使用此资产包构建您自己的山地或林地级别和景观!还包括一个demoscene。该包包含许多资产:植物、岩石、山脉、树木、建筑、营地和帐篷、墙壁、粒子效果等等。 性能:所有东西都共享一种材质和一种纹理,因此可以将所有东西分批在一起…

0401-403组合逻辑电路的分析设计竞争冒险

组合逻辑电路的分析设计&竞争冒险 4.组合逻辑电路1.目录2.教学基本要求3.序 关于组合逻辑电路 4.1组合逻辑电路分析与设计一、组合逻辑电路分析二、组合逻辑电路的分析步骤&#xff1a;三、组合逻辑电路的分析举例例1 奇校验电路例2.对输入的二进制求反码例3.一个工厂发电的…

git使用、git与idea结合、gitee、gitlab

本文章基于黑马程序javase模块中的"git"部分 先言:git在集成idea中,不同版本的idea中页面显示不同,操作时更注重基于选项的文字;git基于命令操作参考文档实现即可,idea工具继承使用重点掌握 1.git概述 git是目前世界上最先进的分布式文件版本控制系统 分布式:将…

2024年steam好玩的新游:《哈迪斯2》《雨中冒险: 回归》等

今天已经有不少新游上线&#xff0c;下面为大家整理了2024年好玩的steam游戏&#xff0c;一起来看看。 2024值得一玩的新游 1、《哈迪斯2》 哈迪斯2&#xff08;Hades II&#xff09;是Supergiant Games继其广受好评的作品《哈迪斯》之后开发的一款动作角色扮演游戏。 在《哈…

纯净IP的判断标准及代理深度分析

今天&#xff0c;我们测评团队将带大家深入探讨纯净IP的判断标准&#xff0c;并通过实测数据&#xff0c;对极光静态代理与独享云创这两家服务商进行深度剖析&#xff0c;为你揭秘如何挑选那些真正值得信赖的IP代理服务。 一、纯净IP的判断标准 历史记录检查&#xff1a;一个好…

@Resource注解 和 @Autowired 注解的区别!

Resource注解 和 Autowired 注解的区别! 前言: 实习时候第一次拉取了企业级代码(微服务),发现基本上都是Resource注解,自己之前平时没仔细思考 就是按照自己的习惯用的Autowired,平时开发也是单体架构的系统. 理解: Autowired Autowired是spring提供的一个注解,默认是根据类型…

[RL] 马尔可夫决策过程基础

文章结构 目录 一、马尔可夫过程 马尔可夫性质 二、马尔可夫奖励过程 回报&#xff08;Return&#xff09; 贝尔曼方程&#xff08;Bellman equation&#xff09; 贝尔曼方程解析解 蒙特卡洛方法​ 马尔可夫决策过程​ MDP和马尔可夫过程/马尔可夫奖励过程的区别 马…

循环机制(event loop)之宏任务和微任务

一、前言 js任务分为同步任务和异步任务&#xff0c;异步任务又分为宏任务和微任务&#xff0c;其中异步任务属于耗时的任务。 二、宏任务和微任务有哪些&#xff1f; 宏任务&#xff1a;整体代码script、setTimeout、setInterval、setImmediate&#xff08;Node.js&#xff…

nginx conf.d 模块化配置

文章目录 前言nginx conf.d 模块化配置1. 概述2. 优势3. 配置 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#xff0c…