徒手搭建Vue3+TS+Pinia框架

95 阅读3分钟

创建Vue3项目,TS配置、安装和配置路由、状态管理Pinia、UI库Element-Plus以及axios请求库等操作

参考:vue官网

一、创建vite项目

1.0、打开终端输入命令

确保你安装了最新版本的 Node.js,并且你的当前工作目录正是打算创建项目的目录。在命令行中运行以下命令 (不要带上 $ 符号):

npm create vite@latest

vite创建.png

2.0、创建好之后,结构目录如下

项目结构.png

二、启动vue3项目

2.0、安装依赖

启动项目前需要先npm i

npm run dev  //启动项目

运行后界面.png

三、增加工程化插件

3.0、安装sass

sass模块是使用scss文件必备的工具

npm install sass -D
3.1、安装路由
npm i vue-router

安装成功之后,来使用一下
(1)、在src下创建pages文件夹,在pages文件夹下创建login和home.vue文件 pages文件夹.png

//login.vue
<template>
     <div @click="toLogin">登录界面</div>
 </template>
 <script lang="ts" setup>
 import { useRouter } from 'vue-router'
 
 const router = useRouter()
 
 function toLogin(){
     router.push({
         name: 'home'
     })
 }
 </script>
//home.vue
<template>
     <div >首页</div>
 </template>
 
 <script lang="ts" setup>


 </script>

(2)、写好页面之后,我们来创建路由,在 src 路径下新建 router/index.ts

import { createRouter, createWebHistory, } from 'vue-router'
import Login from '../pages/login.vue';

export const routes = [
    {
        path: '/',
        redirect: '/login'
    },
    {
        name: 'login',
        path: '/login',
        component: Login
    },
    {
        name: 'index',
        path: '/index',
        component: () => import("../pages/home.vue")
    }
]
const router = createRouter({
    scrollBehavior: () => ({ left: 0, top: 0 }),
    history: createWebHistory(),
    routes,
})
router.beforeEach((to, from, next) => {
    next()
})
export default router

(3)、在main.ts中引入

import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

import router from './router/index'
app.use(router)


app.mount('#app')

(4)、在app.vue设置routerview

<script setup lang="ts">
</script>

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

<style scoped>
</style>

运行代码 登录界面.png 到此处,基础架子应完成

四、安装pinia

Pinia 是 Vue.js 的一个状态管理库,用于在 Vue 应用程序中管理共享状态。它是 Vuex 的后继者,提供了一个简单、直观且灵活的方式来处理应用中的全局状态,比如用户登录信息、应用配置、购物车数据等。

Vuex 相比,Pinia 有更简洁的 API 和更好的类型支持(在 Type - Script 项目中),使得开发者能够更高效地管理应用状态

4.0、安装pinia

用你最喜欢的包管理器安装 pinia

npm install pinia
4.1、使用pinia

在main.ts中引入

import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
//引入router
import router from './router/index'
app.use(router)

//引入pinia
import { createPinia } from 'pinia'
app.use(createPinia())

app.mount('#app')
4.2、创建store文件夹,增加 store/index.ts(和vuex一样)
//store/index.ts
import { defineStore, acceptHMRUpdate } from "pinia";
// 官方推荐命名与hooks一样,use开头
export const useStatusStore = defineStore("statusStore", {
    //存储数据的地方-Pinia唯一的数据源
     state: () => ({name: "原来的数据",}),
     getters: {
        myName: (state:any) => {
            return `getters ${state.name}`
        }
     },
     actions: {
          changeName(name: string) {
            this.name = name
        }
     },
});
if (import.meta.hot) {
    import.meta.hot.accept(acceptHMRUpdate(useStatusStore, import.meta.hot))
}

//pages/login.vue
<template>
     <div @click="toLogin">登录界面</div>
     <span>展示数据:{{ statusStore.name }}</span>
     <button @click="changeName">修改状态值</button>
 </template>
 <script lang="ts" setup>
 import { useRouter } from 'vue-router'
 import {useStatusStore} from '../store/index'
 
 const router = useRouter()
 const statusStore = useStatusStore()

 function toLogin(){
     router.push({
         name: 'home'
     })
 }
 //点击改变值
 function changeName(){
     statusStore.name = '我是修改后的名字'
 }
 </script>

改变的值.png

五、安装element-plus

npm install element-plus

(1)、在main.ts中引入

import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)

import router from './router/index'
app.use(router)

import { createPinia } from 'pinia' 
app.use(createPinia())

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
app.use(ElementPlus)     

app.mount('#app')

(2)、使用组件查看是否引入成功 ElementPlus使用.png 开关.png

六、登录页面添加样式修改

千库网找了一张背景图作为背景基调,让页面内容更丰富 背景.png 在src下assets文件夹内新建images目录,将背景图片添加至此

6.1、修改登录页面布局样式-【完整代码】
<template>
     <div class="login">
        <el-form 
        ref="loginForm"  
        status-icon
        :rules="loginRules"
        class="login-form">
        <h3 class="title">{{ title }}</h3>
            <el-form-item prop="username">
                <el-input
                v-model="loginForm.username"
                type="text"
                size="large"
                auto-complete="off"
                placeholder="账号"
                >
                <template #prefix><el-icon><User /></el-icon></template>
                </el-input>
            </el-form-item>

            <el-form-item prop="password">
                <el-input
                v-model="loginForm.password"
                type="password"
                size="large"
                auto-complete="off"
                placeholder="密码"
                @keyup.enter="handleLogin"
                >
                <template #prefix><el-icon><Lock /></el-icon></template>
                </el-input>
            </el-form-item>
            <el-form-item prop="code" v-if="captchaEnabled">
                <el-input
                v-model="loginForm.code"
                size="large"
                auto-complete="off"
                placeholder="验证码"
                style="width: 63%"
                @keyup.enter="handleLogin"
                >
                <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template>
                </el-input>
                <div class="login-code">
                <img :src="codeUrl" @click="getCode" class="login-code-img"/>
                </div>
            </el-form-item>
            <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox>

            <el-form-item style="width:100%;">
                <el-button
                :loading="loading"
                size="large"
                type="primary"
                style="width:100%;"
                @click.prevent="handleLogin"
                >
                <span v-if="!loading">登 录</span>
                <span v-else>登 录 中...</span>
                </el-button>
                <div style="float: right;" v-if="register">
                <router-link class="link-type" :to="'/register'">立即注册</router-link>
                </div>
            </el-form-item>

        </el-form>
        <!--  底部  -->
        <div class="el-login-footer">
           <span>Copyright © 2025-2925 zongang.com All Rights Reserved.</span>
        </div>

     </div>
 </template>

 <script lang="ts" setup>
 import {  ref } from 'vue'

const title =  import.meta.env.VITE_APP_TITLE;
 
const loginForm = ref({
  username: "admin",
  password: "admin123",
  rememberMe: false,
  code: "",
  uuid: ""
});

const loginRules = {
  username: [{ required: true, trigger: "blur", message: "请输入您的账号" }],
  password: [{ required: true, trigger: "blur", message: "请输入您的密码" }],
  code: [{ required: true, trigger: "change", message: "请输入验证码" }]
};

// 验证码开关
const captchaEnabled = ref(true);
const codeUrl = ref("");
const loading = ref(false);
// 注册开关
const register = ref(false);

function handleLogin() {
  
}

function getCode() {

}
 </script>

 <style lang='scss' scoped>
 .login {
    display: flex;
    align-items: center;
    height: 100vh;
    width:100vw;
    background-image: url("../assets/images/login-background01.png");
    background-position: center;
    background-size: 100vw 100vh; 
    background-repeat: no-repeat;

    .login-form {
        border-radius: 6px;
        background: #ffffff;
        margin-left: 200px;
        width: 400px;
        padding: 25px 25px 5px 25px;

        .title {
            margin: 0px auto 30px auto;
            text-align: center;
            color: #707070;
        }

        .el-input {
            height: 40px;
            input {
            height: 40px;
            }
        }
        .input-icon {
            height: 39px;
            width: 14px;
            margin-left: 0px;
        }
    }
    .login-tip {
        font-size: 13px;
        text-align: center;
        color: #bfbfbf;
    }
    .login-code {
        width: 33%;
        height: 40px;
        float: right;
    img {
        cursor: pointer;
        vertical-align: middle;
    }
    }
    .el-login-footer {
        height: 40px;
        line-height: 40px;
        position: fixed;
        bottom: 0;
        width: 100%;
        text-align: center;
        color: #fff;
        font-family: Arial;
        font-size: 12px;
        letter-spacing: 1px;
    }
    .login-code-img {
        height: 40px;
        padding-left: 12px;
    }
 }
</style>

实现效果如图 最终效果.png

6.2、在src最外添加.env环境配置

env环境配置.png

.env.development

# 页面标题
VITE_APP_TITLE = 财务管理系统

# 开发环境配置
VITE_APP_ENV = 'development'

# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'

.env.production

# 页面标题
VITE_APP_TITLE = 财务管理系统

# 生产环境配置
VITE_APP_ENV = 'production'

# 财务管理系统/生产环境
VITE_APP_BASE_API = '/prod-api'

# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip

.env.staging

# 页面标题
VITE_APP_TITLE = 财务管理系统

# 生产环境配置
VITE_APP_ENV = 'staging'

# 财务管理系统/生产环境
VITE_APP_BASE_API = '/stage-api'

# 是否在打包时开启压缩,支持 gzip 和 brotli
VITE_BUILD_COMPRESS = gzip