0


完整创建一个vite前端项目

废话少说,直接上步骤!

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包。
标签: 前端

本文转载自: https://blog.csdn.net/m0_63624484/article/details/140577718
版权归原作者 凌晨去看海 所有, 如有侵权,请联系我们删除。

“完整创建一个vite前端项目”的评论:

还没有评论