1 vite安装
以红色操作步骤为准
如果是内部构建源,需要指定源:
npm set registry http://192.168.0.251:2333
查看
npm config list 可以看到metircs-registry 的指向到内网
1.1 介绍的步骤有
npm install -g create-vite-app //安装全局create-vite-app
create-vite-app vue3-vite //使用工具create-vite-app创建项目名为vue3-vite的vue3项目
1.2 实用步骤
npm init @vitejs/app vite_vue_ts_v1 --template vue-ts
cd vue3-vite //进入项目文件夹
npm install //初始化项目
npm run dev //运行项目
npm run build //打包
npm run serve //运行
包含了ts安装
2 安装ts(独立)
npm install -D typescript
安装全局ts
npm install -g typescript
初始化配置文件tsconfig.json,就可以直接使用.ts文件开发了
npx tsc --init
执行时却产生:
error TS5054: A 'tsconfig.json' file is already defined at: 'D:/....../tsconfig.json'.
编写ts配置文件
// tsconfig.json
{
"compilerOptions": {
// TypeScript 默认会把代码编译为 ECMAScript 3
// esnext 表示仅仅校验转换 TypeScript 类型,不进行语法编译
"target": "esnext",
"module": "esnext",
// 开启严格模式,这使得对“this”的数据属性进行更严格的推断成为可能
"strict": true,
"jsx": "preserve",
"moduleResolution": "node"
},
// 配置需要校验的文件
"include": [
"src/**/*.ts",
"src/**/*.vue"
],
// 排除不需要 TypeScript 校验的文件
"exclude": [
"node_modules"
]
}
3 安装elementplus
1) 安装 npm install element-plus --save
目前element-plus默認語言是英文版的,所以如果想改成默認中文的話,需要在vite.config.js中添加插件配置
// 引入第三方的配置
optimizeDeps: {
include: ["element-plus/lib/locale/lang/zh-cn", "axios"],
},
4 安装less
# 安装less
npm install less -D
为了解决 ts 文件中cannot find module vue的问题,还需要做以下设置。
在tsconfig.json中加入
"plugins": [
{
"name": "@vuedx/typescript-plugin-vue"
}
],
vite 使用less 必须要将 package.json 中的 less 和less-loader写在 devDependencies 里面
5 安装axios
# 安装 axios,用于网络请求
npm install axios
6 安装vuex
# 安装 Vuex,用于管理状态
npm install vuex --save
如果出现错误Could not resolve dependency: npm ERR! peer vue@"^2.0.0" from vuex@3.6.2
就替换为如下安装,可以解决问题:
npm install vuex@next --save
7 安装vueRouter
# 安装 路由,用于实现两个 Vue 页面的跳转
npm install vue-router
安装vue-router@next,最新版路由
npm install vue-router@next --save
8 增加views目录和所属页面
login.vue
<template>
<H1>login</H1>
</template>
<script>
export default {
name: "login"
}
</script>
<style scoped>
</style>
9 增加router路目录及index.ts
index.ts
import {createRouter,createWebHashHistory} from "vue-router";
import login from "../views/login.vue"
const routes=[
{
path:"/",
redirect:'/login'
},
{
path:"/login",
component:login
}
]
export default createRouter({
history:createWebHashHistory(),
routes
})
如果是引入 router而不是router@next 则以上第一行编译会发生错误
10 app.vue中引入路由
主要是增加路由
<div id="app">
<router-view/> <!-- 路由的出入口,路由的内容将被显示在这里 -->
</div>
代码如下:
<script setup lang="ts">
</script>
<template>
<div id="app">
<router-view/><!-- 路由的出入口,路由的内容将被显示在这里 -->
</div>
</template>
<script lang="ts">
export default {
name: 'App'
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
11 main.ts 完成框架引用
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'
createApp(App).use(router).use(ElementPlus,{locale}).mount('#app')
//createApp(App).mount('#app') //注解原有这行
代码如下
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'
createApp(App).use(router).use(ElementPlus,{locale}).mount('#app')
12 系统测试
l
13 完善登录界面的测试
login替换后的代码如下:
<template>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
alert(1)
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>
<style scoped>
</style>
14 改写main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/theme-chalk/index.css'
import locale from 'element-plus/lib/locale/lang/zh-cn'
import axios from 'axios'
const app = createApp(App).use(router).use(ElementPlus,{locale})
app.config.globalProperties.myaxios = axios
app.mount("#app")
//createApp(App).use(router).use(ElementPlus,{locale}).mount('#app')
15 重构目录
在src/components/下新建 back 后台这个目录,在 components/back下新建login.vue, main.vue, main_menu.vue, maintitle.vue,以及子菜单的三个网页,如dome.vue, product.vue, capital.vue等
16 重写router/index.ts
import {createRouter,createWebHashHistory} from "vue-router";
import login from "../components/back/login.vue"
import home from "../components/home.vue"
import main from "../components/back/main.vue"
import dome from "../components/back/dome.vue"
import product from "../components/back/product.vue"
import capital from "../components/back/capital.vue"
const routes=[
{path:"/", redirect:'/login'},
{path:"/login", component:login},
{path:"/home", component:home},
{path:"/main", component:main,
children:[
{path:"/main/dome", component:dome},
{path:"/main/product", component:product},
{path:"/main/capital", component:capital},
]
}
]
export default createRouter({history:createWebHashHistory(),routes})
17 重写login.vue
<template>
<H1>Login</h1>
<el-form ref="form" :model="form" >
<el-form-item label="账号"> <el-input v-model="form.usr"></el-input></el-form-item>
<el-form-item label="密码"> <el-input v-model="form.pwd"></el-input></el-form-item>
<el-form-item > <el-button @click="onsubmit"> 登录</el-button></el-form-item>
</el-form>
</template>
<script>
export default {
name:"login",
data(){return {form:{usr:'',pwd:''}}
mounted(){},
methods:{
onsubmit(){
alert("usr"+this.form.usr);
this.myaxios.get("http://127.0.0.1:7999/lmes/sys/login?usr"+this.form.usr + "&pwd="+this.form.pwd).then((req,res) => {
let data = req.data;
if(data["msg"]=="success"&&data.code==200)
this.$router.push("/main");
console.log("get data:",req);
});
this.$router.push("/main");
console.log("llllllll");
}
},
}
</script>
<style scoped>
</style>
18 编写components/back/main_menu.vue
<template>
<el-row class="tac">
<el-menu
active-text-color="#ffd04b"
background-color="#2e3e55"
class="el-menu-vertical-demo"
default-active="2"
text-color="#fff"
style="..."
:collapse="menuOpenOrCloseStutic"
@open="handleOpen"
@close="handleClose"
router
>
<el-sub-menu index="1">
<template #title><i class="el-icon-location"></i><el-icon :size="16" :color="'#fff'"> <i-edit /> </el-icon> <span>设备管理</span></template>
<el-sub-menu index="1-4">
<template #title><el-icon :size="16" :color="'#fff'"> <i-edit /> </el-icon> 选项1 </template>
<el-menu-item index="/home/login"> 选项2 </el-menu-item>
</el-sub-menu>
</el--sub-menu>
<el-menu-item index="/main/dome"><el-icon><i-icon-menu /> </el-icon><span>订单管理></span></el-menu-item>
<el-menu-item index="/main/capital"><el-icon><i-document /> </el-icon><span>资金管理></span></el-menu-item>
<el-menu-item index="/main/product"><el-icon><i-setting /> </el-icon><span>产品管理></span></el-menu-item>
</el-menu>
</el-row>
</template>
<script lang="ts">
export default{
name:"menu",
props:{menuOpenOrClossStutic:Boolean,},
data(){return {};},
methods:{handleOpen(key:String,keyPath:string){},
handleClose(key:String,keyPath:string){},
},
},
};
</script>
<style lang="less">
.main_body{
.el-aside{box-shadow:0;back-ground:#2e3e55 !important;}
.el-menu{border:0;}
.el-menu-vertical-demo(.el-menu--collapse){width:100px;min-height:80px;}
}
</style>
19 编写components/back/main.vue
<template>
<div class="main_body">
<h1>111</h1>
<el-container>
<el-header height="50px"><main-title @menuChangeStatus="menuChangeStuts"></main-title></el-header>
<el-container>
<el-aside :class="menuOpenOrCloseStutic?'el-asideSelfno':''">
<div class="main-menu"><Menu :menuOpenOrCloseStutic="menuOpenOrCloseStutic"></Menu></div>
</el-aside>
<el-main><router-view></router-view></el-main>
</el-container>
</div>
</template>
<script>
import maintitle from "../back/maintitle.vue";
import Menu from "./main_menu.vue";
export default {
name:"main",
components:{"main-title":maintitle,Menu:Menu,}
}
</script>
<style scoped>
</style>
20 编写components/back/maintitle.vue
<template>
<div class="main-title">
<div :class="menuOpenOrClassSwitch?'site-navbar__headerNo':'site-navbar__header'">
<a v-if="menuOpenOrClassSwitch === false">管理子系统</a>
</div>
<el-button style="..." @click="ChangeStuts" >
<el-icon size="22" color="#0e0606" v-if="menuOpenOrClassSwitch===false"><i-arrow-left-bold /> </el-icon>
<el-icon size="22" color="#0e0606" v-if="menuOpenOrClassSwitch===true"><i-arrow-left-bold /> </el-icon>
</el-button>
</div>
</template>
<script lang="ts">
export default {
name:"maintitle",
data(){return{menuOpenOrClassSwitch:false,};},
setup(){},
methods:{
changeStuts{this.menuOpenOrClassSwitch = !this.menuOpenOrClassSwitch;
this.$emit("menuChangeStuts",this.menuOpenOrClassSwitch);
}
}
</script>
<style scoped>
.site-navbar__header{
width:180px; text-align:center; float:left; line-height:60px; background:#2c3e50; color:#ffffff; font-size:20px;
}
.site-navbar__headerNo{
width:80px; text-align:center; float:left; line-height:60px; background:#2c3e50; color:#ffffff; font-size:20px; overflow:hidden
}
</style>
21 编写components/back/dome.vue
<template>
<div class="main_body">
<h1 class="dome">这是订单系统 </h1>
</div>
</template>
<script>
export default{}
</script>
<style scoped>
.dome{width:300px;height:300px;background:tomato;}
</style>
22 编写components/back/capital.vue
<template>
<div class="main_body">
<h1 class="dome">这是资金管理系统 </h1>
</div>
</template>
<script>
export default{}
</script>
<style scoped>
.dome{width:300px;height:300px;background:tomato;}
</style>
23 编写components/back/product.vue
<template>
<div class="main_body">
<h1 class="dome">这是产品系统 </h1>
</div>
</template>
<script>
export default{}
</script>
<style scoped>
.dome{width:300px;height:300px;background:tomato;}
</style>
24 编写components/home.vue
<template>
</template>
<script>
export default{name:"home"}
</script>
<style scoped>
</style>
26 相关参考引用
Home | Vite中文网 vitejs.cn
vite+vue3+element-plus项目搭建基本流程配置_superKM的博客-CSDN博客_vue3+element
(https://blog.csdn.net/superKM/article/details/111328781)
Vue实战系列(一) - 最简化登录页面 - Master HaKu - 博客园