vue3+pinia+ts+vite+elementplus 实战踩坑
前言
本文是基于 @mk 大佬的模板vite-vue3-template进一步优化。在项目实际开发中遇到其他的坑,基本上实际开发中需要踩的坑都记录一下分享给大伙。下载这个模板,直接可以开始你的项目开发,非常好用!
- 开箱即用模板下载地址: gitee.com/jokerchen54…
pinia
-
响应尤大的号召,采用了pinia的状态管理库。pinia的好处自然是不言而喻的。除了可以更贴合vue3的setup编程、更好的支持ts、比之前的vuex使用起来更加方便。出于种种原因,本模板采用了pinia库。
-
本模板对于pinia进行了统一的全局注册,在业务逻辑复杂的系统里,能更好的管理store的各模块状态。
-
那么对于pinia的基本用法这里就赘述了,大伙可以参考一下南山种子外卖选手的Pinia进阶使用
-
本模板也简单的写了一些使用案例,在/src/views/Home.vue中。
element-plus的集成
参考官网例子进行一个按需加载
- 首先安装 unplugin-vue-components
` npm install unplugin-vue-components -D `
- 然后把下面代码加到在vite配置文件里面
// vite.config.ts
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
plugins: [
// ...
Components({
resolvers: [ElementPlusResolver()],
}),
],
}
// main.ts
import { createApp } from 'vue';
import { ElImage } from 'element-plus';
import App from './App.vue';
import router from './router/index';
import 'vue-global-api';
import store from './store';
import 'element-plus/dist/index.css';
createApp(App)
.use(router)
.use(store)
.use(ElImage)
.mount('#app');
中文包使用
// App.vue
<script setup lang="ts">
import { ElConfigProvider } from 'element-plus';
import zhCn from 'element-plus/lib/locale/lang/zh-cn';
const locale = ref(zhCn);
</script>
<template>
<el-config-provider :locale="locale">
<router-view />
</el-config-provider>
</template>
移动端适配 px2rem
本模块已配置屏幕自适应,宽度是按照设计稿1920px规格转化,可直接在样式代码填写px值,打包后会自动转化为rem
- 例子中,直接填写设计稿中的标定值既可
.box {
width: 100px;
height: 50px;
}
- 配置postcss插件
// postcss.config.js
module.exports = {
plugins: {
// 兼容浏览器,添加前缀
autoprefixer: {
overrideBrowserslist: [
'Android 4.1',
'iOS 7.1',
'Chrome > 31',
'ff > 31',
'ie >= 8',
'last 10 versions', // 所有主流浏览器最近10版本用
],
grid: true,
},
'postcss-pxtorem': {
rootValue: 16, // 根节点字号
propList: ['*'], // 是一个存储哪些将被转换的属性列表,这里设置为['*']全部,假设需要仅对边框进行设置,可以写['*', '!border*']
unitPrecision: 5, // 保留rem小数点多少位
selectorBlackList: ['px'], // 则是一个对css选择器进行过滤的数组,比如你设置为['px'],那例如px-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。
replace: true, // 这个真不知到干嘛用的。有知道的告诉我一下
mediaQuery: false, // 媒体查询( @media screen 之类的)中不生效
minPixelValue: 12, // px小于12的不会被转换
},
},
};
- 配置html根字号自适应,其中1920为设计稿初始屏幕宽度,可根据需要修改
// /src/utils/rem.ts
(() => {
const baseSize = 16;
function setRem() {
const scale = document.documentElement.clientWidth / 1920; // 1920为设计稿初始屏幕宽度,可根据需要修改
document.documentElement.style.fontSize = `${baseSize * Math.min(scale, 2)}px`;
}
window.onresize = () => {
setRem();
};
})();
vite配置
@别名定义和使用
- 别名定义,首先在vite.config.js定义变量,在tsconfig.json配置paths
\\ vite.config.js
resolve: {
alias: {
'@': resolve(__dirname, 'src'), // 设置 `@` 指向 `src` 目录
'@comp': resolve(__dirname, 'src/components'),
},
}
\\ tsconfig.json
compilerOptions: {
"paths":{
"@": ["./src"],
"@/*": ["./src/*"],
"@comp/*": ["./src/components/*"],
}
}
环境变量定义和使用
- 首先在项目根目录下创建环境文件
- 注意变量前缀必须是 VITE_APP_
# .env.development
VITE_APP_BASE_PATH = /
- 在.vue .ts文件中使用环境变量
console.log(`环境变量BASE_PATH${import.meta.env.VITE_APP_BASE_PATH}`);
- 在vite.config.js文件中使用环境变量
import {
loadEnv, ConfigEnv, UserConfigExport,
} from 'vite';
import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
const envResolve = (mode: string, env: string) => loadEnv(mode, process.cwd())[env];
export default ({ command, mode }: ConfigEnv): UserConfigExport => {
console.log('🚀 ~ process.env.NODE_ENV ~ 打包路径:', envResolve(mode, 'VITE_APP_BASE_PATH'));
return {
plugins: [
vue(),
Components({
resolvers: [ElementPlusResolver()],
}),
],
};
};
本地图片动态加载
- 由于vite取消了require,需要使用new URL(),进行一个引入。
\\ 封装一个引入图片方法
function getImageUrl(name) {
return new URL(`../assets/blogPhotos/${name}.jpg`, import.meta.url).href;
}
\\ App.vue
<img :src="" alt="getImageUrl(name)" />
svg-icon通用组件
- 为了更方便使用svg图标,封装一个svg-icon组件。用到的一个插件vite-plugin-svg-icons。
- 首先安装插件
yarn add vite-plugin-svg-icons -D 或者 npm i vite-plugin-svg-icons -D - 配置vite.config.js
import viteSvgIcons from 'vite-plugin-svg-icons';
import path from 'path'; // ts如果报错 npm i @types/node -D
export default () => {
return {
plugins: [
viteSvgIcons({
// 配置路劲在你的src里的svg存放文件
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
symbolId: 'icon-[dir]-[name]',
}),
],
};
};
- icon文件存放路径 /src/assets/icons
# src/assets/icons
icon1.svg
icon2.svg
icon3.svg
dir/icon1.svg
- 定义svg-icon 组件
<template>
<svg :class="svgClass" aria-hidden="true">
<use :xlink:href="iconName" :fill="color" />
</svg>
</template>
<script lang="ts">
import { computed, defineComponent } from 'vue';
export default defineComponent({
props: {
iconClass: {
type: String,
required: true,
},
className: {
type: String,
default: '',
},
color: {
type: String,
default: '#889aa4',
},
},
setup(props) {
return {
iconName: computed(() => `#icon-${props.iconClass}`),
svgClass: computed(() => {
if (props.className) {
return `svg-icon ${props.className}`;
}
return 'svg-icon';
}),
};
},
});
</script>
<style scope>
.svg-icon {
width: 1em;
height: 1em;
fill: currentColor;
vertical-align: middle;
}
</style>
- 全局注册通用组件
// main.ts
// svg-icons通用组件
import 'vite-plugin-svg-icons/register';
import svgIcon from './components/common/SvgIcon/index.vue';
app.component('svg-icon', svgIcon)
- 组件的使用方法
<div>
<svg-icon icon-class="icon1" />
</div>
CSS预处理模块
- 本模块使用less预处理,使用全局变量配置,配置后可以在.vue文件中使用全局变量
// vite.config.js
export default {
css: {
preprocessorOptions: {
less: {
modifyVars: {
hack: `true; @import (reference) "${resolve('src/assets/style/config.less')}";`,
},
javascriptEnabled: true,
}
}
},
}
script setup 语法糖
props,emit在script setup 语法糖里面的用法
<script setup lang="ts">
import { defineProps, defineEmits } from 'vue';
const props = defineProps({
isShow: Boolean,
foo: String,
});
const emits = defineEmits(['update:foo', 'updateShow']);
const changeHandle = () => {
emits('update:foo', 'dd');
};
const changeIsShow = () => {
emits('updateShow', !props.isShow);
};
</script>
vue-import-global插件,全局默认导入vue的一些基本方法,不用再手动导入,搭配setup语法糖,减少了超级多冗余的代码,直接起飞!
- 不使用script setup 语法糖
<script lang="ts">
import { onMounted, reactive, toRefs, computed, watch, onUnmounted } from 'vue'
const state = reactive({})
onMounted = ()=>{
console.log('开始啦')
}
const handle = ()=>{}
return {
...toRefs(state),
handle
}
</script>
- npm install vue-import-global -D 导入后可以直接使用
<script setup lang="ts">
const state = reactive({})
console.log('开始啦')
</script>