下载脚手架(根据提示进行操作)
npm init @vitejs/app
vite内部支持less,scss,stylus预处理,不过需要进行本地的下载
npm install -D sass ( less| stylus )
在脚手架中起别名(使用别名后,当前方法不会有提示,对IDE不友好)
在vite.config.js配置文件中进行操作
-
使用绝对路径
在页面中引入组件的时候,直接使用
import HelloWorld from '@/HelloWorld.vue'
注意:
1、vite中对于setup可以有两种写法,一种是在script标签上进行写setup,但是接收props要用defineProps({msg: String})这种写法还有emits等,不过不需要进行return导出
2、还有就是在script下写setup,不过需要return导出
使用动态的组件进行切换
- 首先在当前的父组件中引入子组件,并进行注册
- 使用component标签进行展示,使用:is进行组件的切换
- 动态组件之间的传值,我们可以使用computed计算属性加v-bind进行传递
当前的父组件
helloworld组件
{{ msg }}
test组件
测试Vue中声明变量的属性
{{name}}
声明响应式的属性
- 1、ref
- 一般用于声明基本数据类型
- 使用ref声明的变量,操作时需要使用.value进行
- 使用ref声明的变量是个深度的响应式数据
- 可以进行一层的解构赋值,不能进行深度的解构,否则数据就不是响应式的数据了(会导致页面的视图不更新)
ref.js文件
import { ref } from "vue";
export function testRef() {
let count = ref(0);
let list = ref({
arg: { c: 1, obj: { _c: 2 } }
});
const testRefBtn = () => {
count.value++;
list.value.arg.c++;
list.value.arg.obj._c++;
};
return {
count,
list,
testRefBtn
};
}
-
在当前的页面中引入ref.js文件进行解构并导出就可以了
-
2、reactive
- 一般用来声明引用数据的
- 使用reactive声明的数据不能使用解构赋值,否则解构出的数据就不是响应式的数据,可以使用toRefs+扩展运算符将数据在转化为ref,然后再进行解构(好像还是只能解构一层,深层次的解构待查资料中)
- 一般在导出的时候,我们可以使用...扩展运算符进行展开,不过要是用toRefs属性进行包裹
reactivejs
import { reactive } from 'vue'
export function reactiveTest(){
let r_arr = reactive([]);
let r_list = reactive({
r_c:0,
r_arg:{
r_num:1,
r_obj:{
r_count:2
}
}
})
const reactiveBtn = () =>{
r_list.r_c++;
r_arr.push(r_list.r_c);
r_list.r_arg.r_num++;
r_list.r_arg.r_obj.r_count++;
console.log(r_list);
}
return {
r_arr,
r_list,
reactiveBtn
}
}
推荐使用图片下的第二个红框,使用扩展运算符搭配toRefs进行展开
-
3、readonly
- 可以将ref,reactive等进行声明的响应式变量转化为只读的,不允许用户进行修改,否则会触发警告
- 是深层次的只读变量
-
4、isProxy
- 检查对象是否是由
reactive
或readonly
创建的 proxy。
- 检查对象是否是由
-
5、isReactive
- 检查对象是否是由reactive创建的响应式变量
- 如果是用reactive创建的变量之后又使用readonly进行包裹,那么也会返回true
- 如果使用reactive创建的变量之后又使用toRefs进行包裹,那么返回false
- 如果reactive中声明的对象属性是常量,那么返回false,只有声明的变量中有对象或者是数组等引用类型,才会返回true
let r = reactive([0]);
let _r = readonly(r);
let t = toRefs(r)
console.log('使用reactive+readonly------',isReactive(_r));//todo true
console.log('使用reactive+toRefs------',isReactive(t));//todo false
- 6、isReadonly
- 检查变量是否由readonly创建的变量
- 由reactive创建在用readonly包裹返回true
- 有ref创建基本/引用类型+readonly包裹返回true
- 直接使用readonly创建基本数据类型返回false
- 直接使用readonly创建引用数据类型返回true
let r = reactive([0]);
let _r = readonly(r);
let t = readonly(0);
let _t = readonly({num:0});
let f = ref(0)
let tt = readonly(f);
console.log('使用reactive+readonly------',isReadonly(_r));//todo true
console.log('使用readonly基本类型------',isReadonly(t));//todo false
console.log('使用readonly引用类型------',isReadonly(_t));//todo true
console.log('使用readonly+ref------',isReadonly(f));//todo false
console.log('使用readonly+ref------',isReadonly(tt));//todo true
- 7、toRaw
- 就是返回使用reactive或者readonly创建的原始数据(不是响应式的数据)
- 不推荐经常使用
let init = [0]
let r = reactive(init);
let _to = toRaw(r)
console.log('使用reactive+toRaw------',_to);//todo [0]
console.log('使用reactive+toRaw------',_to===init);//todo true
- 8、markRaw
- 标记一个对象,使其永远不会转换为 proxy。返回对象本身。
- 当前声明的对象是原始值,但是对象中的属性是可以在被reactive等转化为响应式的对象的
- 转化后的响应式的属性值不等于原始的属性值
let foo = markRaw({
num:1
})
let _r = reactive({
num:foo.num
})
const btn = ()=>{
foo.num++;
_r.num++;
console.log('reactive----------',_r);//Proxy {num: 2}
console.log('markRaw----------',foo);//{num: 2, __v_skip: true}
}
- 9、shallowReactive
- 也是声明响应式数据的,但是这个可以说是reactive的一种优化
- reactive声明的数据是深度的响应式,这个属性声明的响应式数据是浅度的
- 可以对reactive中的数据进行优化
- 使用这个属性声明的变量在视图上也是可以进行更新的,但是当前变量中的对象或数组等引用数据类型不会是proxy对象(创建一个响应式代理,它跟踪其自身 property 的响应性,但不执行嵌套对象的深层响应式转换 (暴露原始值))
const noQiao = shallowReactive({
count2:3,
obj1:{
num:3,
obj2:{
aa:3
}
}
})
console.log(isReactive(noQiao.obj1))//false。
isReactive只检测引用的数据类型
- 10、shallowReadonly
- 创建一个proxy对象,使其自身为可读属性(浅度)
- 第一层属性为只读,不可进行修改,否则报黄色警告
- 第二层或者多层嵌套,可以进行修改
- 当修改嵌套中的属性的时候,页面视图是不会进行更新的
export function TestshallowReadonly(){
let test_readonly = shallowReadonly({
t_n:0,//浅度不可修改
t_arg:{//深度可进行修改
t_c:2
}
})
const add3 = ()=>{
test_readonly.t_n++;
test_readonly.t_arg.t_c++
console.log(test_readonly);
}
return{
...toRefs(test_readonly),add3
}
}
-
11、unref
- 如果参数是一个
ref
,则返回内部值,否则返回参数本身。这是val = isRef(val) ? val.value : val
的语法糖函数。 - 总之都会返回值,就是返回值的类型不同,一个是普通变量,一个是响应式的变量
- 如果参数是一个
-
12、toRef
- 会为某个属性创建一个ref响应式链接的数据
- 有两个属性,一个是当前的值,必须是对象,第二个是对象中的key
- 可以为reactive数据中的某个属性,单独的在创建一个ref响应式的,也可以让props中的属性为单一的响应式数据
- 不能将reactive中的数据解构后在使用toRef,会找不到数据
export function testToRef(){
let reactive_list = reactive({
re_foo:1,
re_arg:{
re_c:2
},
re_num:3
})
let toref_foo = toRef(reactive_list,'re_foo');
const add_toref = () =>{
reactive_list.re_foo++;
reactive_list.re_arg.re_c++;
由于reactive是响应式的,转化为ref也是响应式的,所以当reactive声明的属性进行加的时候,ref中声明的属性是会跟着变得
console.log('-reactive_list-----------',reactive_list);
console.log('-----toref_foo----------',toref_foo.value);
}
return{
...toRefs(reactive_list),
toref_foo,
add_toref
}
}
-
13、toRefs
- 是为当前对象中的每个属性创建一个ref响应式的链接
- 一般使其包裹reactive声明的变量,这样解构的时候,就不会将数据的响应式丢失
-
14、isRef
- 检查当前的变量是否是ref声明的变量
- 是的话,直接返回true,不是的话,false
- 跟isReactive不同,ref声明的不管是引用类型,还是基本类型都是可以进行检查的
-
15、customRef
- 可以自定义的创建ref响应式的数据
- 必须是一个工厂函数
- 有两个参数track,trigger,返回的参数要有get,set对象
// 自定义ref响应式数据
export function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
track();
console.log(track());
console.log(value);
return value
},
set(newValue) {
clearTimeout(timeout)
timeout = setTimeout(() => {
value = newValue
trigger()
}, delay)
}
}
})
}
export default {
setup() {
return {
searchVal : useDebouncedRef(0)
}
}
}
- 16、computed 计算属性
- 返回一个不可进行修改的ref响应式数据
const count = ref(1)
const plusOne = computed(() => count.value + 1)
const plusTwo = reactive({
num: count.value*2
})
const plusThree = computed({
get: () => count.value + 1,
set: val => {
count.value = val - 1
}
})
plusOne.value = 1 //这是设置的时候,value-1
console.log(count.value) // 0
- 17、watchEffect
- 这是初始化页面的时候就会进行监听
- 有两个属性,操作的时机不同flush: 'post'/'async'
- 也可以直接使用watchPostEffect,watchSyncEffect这两个函数,是上面的别名(刷新的时机不同,详情百度或者看)
官方文档介绍
- 页面卸载的时候会自动进行停止监听,也可以返回一个函数进行手动停止监听
const count = ref(0);
watchEffect(() => {
console.log(count.value);----0,----1
})
setTimeout(() => {
count.value++;------1
}, 200);
const stop = watchEffect(() => {
/* ... */
})
// later
stop()---------可以将这个停止监听的事件放到点击事件中
- 18、watch
- 跟watchEffect相比较,他是惰性的
- 监听reactive声明的变量,使用函数返回的方式
- 监听ref声明的变量,直接写就可以
- 可以监听多种方式,使用数组进行包裹就可以
export function testWatch(){
let test_reactive = reactive({
state:0
})
let test_ref = ref(1);
const add_ref = () =>{
test_ref.value++
}
const add_reactive = ()=>{
test_reactive.state++
}
watch(test_ref,(newValue,oldValue)=>{
console.log('---------ref----新---',newValue)
console.log('---------ref----旧---',oldValue)
})
watch(()=>test_reactive.state,(newV,oldV)=>{
console.log('---------reactive----新---',newV)
console.log('---------reactive----旧---',oldV)
})
watch([test_ref,()=>test_reactive.state],([newV,newV1],[oldV,oldV1])=>{
console.log('----------test_ref----新',newV);
console.log('----------test_reactive----新',newV1);
console.log('----------test_ref----旧',oldV);
console.log('----------test_reactive----旧',oldV1);
})
return{
test_ref,
...toRefs(test_reactive),
add_ref,
add_reactive
}
}
- 19、expose
- 如果父组件不通过emit事件进行修改子组件中的数据,而是直接调用子组件中的其他的方法,通过ref是拿不到的
- 需要通过expose将方法暴露出去,父组件才可以通过ref进行取到数据
// expose 只能被调用一次。
// 如果需要暴露多个 property,则它们
// 必须全部包含在传递给 expose 的对象中。
expose({
//将要暴露出去的方法
})
- 20、在script标签上使用setup
- 我们引入的import方法,组件等会被自动解包,直接在模板中使用就可以了
- 要是接收props使用
defineProps
接收,emit使用defineEmits
,expose使用defineExpose
- 在组件中我们可以直接在模板中使用attrs,要是在js中使用通过
useSlots,useAttrs
可以跟普通的script标签一起搭配使用
-
21、全局组件
- 新建一个all.vue文件,在main.js中引入,注册,在需要引入的地方直接写就可以了
-
在vite中可能会有缓存,需要修改引入全局组件的父组件,全局组件才会进行显示
-
22、使用defineProps 和 defineEmits接收和传递
- 在父组件中正常的使用v-bind:属性值,或@自定义事件名
- 在子组件中使用script setup这种写法进行接收参数和调用
父组件
测试组件,传值
子组件
我是全局的测试组件之{{num}}
{{count}}
- 23、 defineExpose
- 将当前的子组件中的方法,属性,暴露给父组件
- 在父组件中只能在onMounted生命周期中获取,其他的地方或者生命周期获取不到
子组件
父组件
测试组件,传值
-
24、directive(全局)或directives(局部)自定义指令
- 具体可以查看
文档
- 具体可以查看
main.js中全局的自定义指令
const app = createApp(App)
// app.component('all-h4', all)
app.directive('format',{
mounted(el,binding){
console.log(el);
console.log(binding);
el.innerText = Number(binding.value).toFixed(2);
}
})
app.mount('#app')
- 在组件中使用自定义指令
vite中env进行生产测试环境变量的切换
- 1、在当前的项目根目录下创建文件.env.['模式']
- 2、.env 这个文件是在测试、生产环境中都是可以获取到的,可以进行公共的路径进行提取
- 3、.env.development 这是测试环境中,我们的请求接口路径
- 4、.env.production 这是生产环境的
- 5、.env.local或者是.ent.development/production.local 是提交到git上可以进行忽略不上传
- 6、在环境变量的文件中要是用VITE_进行开头,否则变量在全局是不会进行暴露,获取不到的
# 本地环境
ENV = 'development / production' 线上和测试这个要进行指定,env公共的就不需要了
# 本地环境接口地址
VITE_API_URL = '2222' 这个是请求的数据接口路径
在js文件中使用import.meta.env.VITE_API_URL【这个是自己定义的变量】这种方式进行获取就可以了
vite中进行配置axios
- 下载axios
npm i axios -S-D
- 新建一个request.js文件进行简单的配置搭配element-plus
import axios from 'axios';
import { ElLoading, ElMessage } from 'element-plus';
const instance = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 1000,
headers: { 'X-Custom-Header': 'foobar' },
});
let loading;
// 正在请求的数量
let requestCount = 0;
// 显示loading
const showLoading = () => {
if (requestCount === 0 && !loading) {
loading = ElLoading.service({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)',
});
}
requestCount++;
};
// 隐藏loading
const hideLoading = () => {
requestCount--;
if (requestCount === 0) {
loading.close();
}
};
// 请求拦截器
instance.interceptors.request.use(
(config) => {
const reqConfig = config;
// showLoading()
// 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
// const token = window.localStorage.getItem('token')
// if (token) {
// reqConfig.headers.Authorization = token
// }
// 若请求方式为post,则将data参数转为JSON字符串
// if (reqConfig.method.toLocaleUpperCase() === 'POST') {
// reqConfig.data = JSON.stringify(reqConfig.data)
// }
return reqConfig;
},
(error) =>
// 对请求错误做些什么
Promise.reject(error)
);
// 响应拦截器
instance.interceptors.response.use(
(response) => {
// hideLoading()
// 响应成功
return response.data;
},
(error) => {
// 响应错误
if (error.response && error.response.status) {
const { status } = error.response;
let message = '';
const actions = {
400: '请求错误',
401: '请求错误',
404: '请求地址出错',
408: '请求超时',
500: '服务器内部错误!',
501: '服务未实现!',
502: '网关错误!',
503: '服务不可用!',
504: '网关超时!',
505: 'HTTP版本不受支持',
20000: '请求失败',
};
message = actions[status] ? actions[status] : actions['20000'];
ElMessage.error(message);
return Promise.reject(error);
}
return Promise.reject(error);
}
);
const request = (url, method, data = {}, isloading = false) => {
!isloading && showLoading(); //todo 也可以放到请求拦截的里面中,这里更方便的进行控制
return new Promise((resolve, reject) => {
instance({
method: method,
url: url,
data: data,
})
.then((res) => {
console.log('成功-------', res);
resolve(res);
})
.catch((msg) => {
console.log('失败-------', msg);
ElMessage.error(msg);
reject(msg);
})
.finally(() => {
!isloading && hideLoading(); //todo 这个可以放到响应拦截器中,这里进行方便的控制
});
});
};
export default request;
vite配置mock,进行模拟请求
- 首先下载mockjs
npm i mockjs vite-plugin-mock cross-env -D
- 在vite.config.js中进行配置
import { defineConfig } from 'vite';
import { resolve } from 'path';
import vue from '@vitejs/plugin-vue';
import { viteMockServe } from 'vite-plugin-mock'; 这里进行引入
import Components from 'unplugin-vue-components/vite';
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
import ElementPlus from 'unplugin-element-plus/vite';
// https://vitejs.dev/config/
export default defineConfig({
// 公共路径测试是绝对路径,生产是相对路径
base: process.env.NODE_ENV === 'production' ? process.env.VITE_PUBLIC_PATH : './',
plugins: [
vue(),
ElementPlus({
//elementui的样式插件
importStyle: 'sass',
useSource: true,
}),
Components({
//elementui 组件的自动导入插件
resolvers: [ElementPlusResolver()],
}),
//todo 配置mockjs模拟请求数据的
viteMockServe({ supportTs: false }), 这里配置mockjs
],
resolve: {
//todo 配置别名
alias: {
'/@': resolve(__dirname, './src/components'),
},
},
server: {
proxy: {配置跨域
//代理(解决跨域问题)
'/api': {
target: 'http://localhost:3000/',
ws: true,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
// build: {
// outDir: 'dist',
// minify: 'esbuild',
// sourcemap: false,//打包后不生成sourcemap文件
// chunkSizeWarningLimit: 1500,
// },
});
- 要是项目中有.env.development文件,将里面的默认路径跟vite.config.js中的配置跨域的路径保持一致
- 最后在项目的根目录下创建一个mock的文件夹,新建一个index.js文件进行模拟接口数据
export default [数组的形式,可以写多个对象形式的接口,也可以只返回一个对象
{
url: '/api/get',
method: 'get',
response: () => {
return {
code: 0,
data: {
name: 'vben',
},
}
},
},
]
- 在src文件下,新建一个api文件夹,在新建一个test.js专门将接口进行统一管理
import request from './request';
export const test = () => {
return request('/api/get', 'get');
};
- 随便在一个.vue文件中进行请求调用
import { test } from '../api/test.js'
setup(){
onMounted(()=>{
这是使用axios进行封装的调用接口
test().then(data => console.log(data)).catch(msg => console.log(msg))
这是直接使用内置的fetch进行接口的调用请求
fetch('/api/get').then(res => res.json()).then(m => console.log(m)).catch(a => {
console.log(a);
})
})
}
vite中进行简单的配置eslint+prettierrc(目前配置的不是很准确,后面会进行深入的)
npm install --save-dev eslint eslint-plugin-vue 这个是没有加ts的eslint,下面的配置是加了ts的eslint,到时候报错的话可以进行下载下或者将下面的配置文件中的ts的eslint进行删除就可以了
- 在根目录下新建一个.eslintrc.js文件然后就可以进行简单的一些提示
module.exports = {
root: true,
env: {
browser: true,
es2021: true,
node: true,
},
parser: 'vue-eslint-parser',
parserOptions: {
ecmaVersion: 12,
parser: '@typescript-eslint/parser',
sourceType: 'module',
},
extends: ['plugin:vue/vue3-essential', 'plugin:vue/essential', 'eslint:recommended'],
plugins: ['vue', '@typescript-eslint'],
rules: {
// http://eslint.cn/docs/rules/
// https://eslint.vuejs.org/rules/
'@type-eslint/ban-ts-ignore': 'off',
'@type-eslint/explicit-function-return-type': 'off',
'@type-eslint/no-explicit-any': 'off',
'@type-eslint/no-var-requires': 'off',
'@type-eslint/no-empty-function': 'off',
'@type-eslint/no-use-before-define': 'off',
'@type-eslint/ban-ts-comment': 'off',
'@type-eslint/ban-types': 'off',
'@type-eslint/no-non-null-assertion': 'off',
'@type-eslint/explicit-module-boundary-types': 'off',
'vue/custom-event-name-casing': 'off',
'vue/attributes-order': 'off',
'vue/one-component-per-file': 'off',
'vue/html-closing-bracket-newline': 'off',
'vue/max-attributes-per-line': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/singleline-html-element-content-newline': 'off',
'vue/attribute-hyphenation': 'off',
'vue/html-self-closing': 'off',
'vue/no-multiple-template-root': 'off',
'vue/require-default-prop': 'off',
'vue/no-v-model-argument': 'off',
'vue/no-arrow-functions-in-watch': 'off',
'vue/no-template-key': 'off',
'vue/no-v-html': 'off',
'vue/comment-directive': 'off',
'vue/no-parsing-error': 'off',
'vue/no-deprecated-v-on-native-modifier': 'off',
'no-useless-escape': 'off',
'no-sparse-arrays': 'off',
'no-prototype-builtins': 'off', //禁止直接调用 Object.prototypes 的内置属性off关闭
'no-constant-condition': 'off', //禁止在条件中使用常量表达式
'no-use-before-define': 'off',
'no-restricted-globals': 'off',
'no-restricted-syntax': 'off',
'generator-star-spacing': 'off',
'no-unreachable': 'off',
'no-multiple-template-root': 'off',
'no-unused-vars': 'error',
'no-v-model-argument': 'off',
'no-case-declarations': 'off',
'no-undef': 'off',
'no-var': 'error', //禁止使用变量var进行声明,修复为let,const
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
//强制使用单引号
quotes: ['error', 'single'],
//强制不使用分号结尾
semi: ['error', 'never'],
},
};
- 在package.json文件中的script中进行配置一个指令
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
- 每次进行输入指令npm run lint-fix 就会检查出我们项目中的src目录下的所有文件的语法是否错误,一些简单会自动的帮我们进行修复
- 根目录下有个.vscode文件夹,在新建一个settings.json(prettierrc这个文件中的配置可能不起作用,只好在这个文件中进行配置了)
{
"eslint.alwaysShowStatus": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
//保存自动格式化
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.workingDirectories": [{ "mode": "auto" }],
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
//根据文件后缀名定义vue文件类型
"files.associations": {
"*.vue": "vue"
},
//开启 eslint 支持
"prettier.eslintIntegration": true,
//使用单引号
"prettier.singleQuote": false,
//结尾不加分号
"prettier.semi": true
}
- 在项目的根目录下新建一个.prettierrc.js文件
module.exports = {
// 一行最多多少个字符
printWidth: 150,
// 指定每个缩进级别的空格数
tabWidth: 2,
// 使用制表符而不是空格缩进行
useTabs: true,
// 在语句末尾打印分号
semi: true,
// 使用单引号而不是双引号
singleQuote: true,
// 更改引用对象属性的时间 可选值""
quoteProps: "as-needed",
// 在JSX中使用单引号而不是双引号
jsxSingleQuote: false,
// 多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"",默认none
trailingComma: "es5",
// 在对象文字中的括号之间打印空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x
arrowParens: "always",
// 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码
rangeStart: 0,
rangeEnd: Infinity,
// 指定要使用的解析器,不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准 always\never\preserve
proseWrap: "preserve",
// 指定HTML文件的全局空格敏感度 css\strict\ignore
htmlWhitespaceSensitivity: "css",
// Vue文件脚本和样式标签缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf 结尾是 可选值""
endOfLine: "lf",
}
vite配置postcss
- 这个插件有很多的功能,具体可以在GitHub上查看下,这里简单的介绍下几个
- 可以参考这篇文章https://www.jianshu.com/p/21be605c6ad1
- vite中是内置支持postcss的,只需要我们将插件进行引入在vite.config.js中进行配置就可以使用了
- autoprefixer这个插件是当我们使用新的css时,为了兼容老的浏览器,会自动将我们的代码加个前缀
npm install autoprefixer -D
- 在vite.config.js中进行配置
import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import autoprefixer from "autoprefixer"//引入插件
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
css: {
postcss: {
plugins: [autoprefixer],//进行注册
},
},
})
-
还需要进行兼容浏览器的版本,不可能是全部浏览器的版本都可以进行添加,那就太多了,需要有个限制进行约束在package.json中
- 或者在根目录下新建.browserslistrc文件,不用逗号,换行就行
> 1%
last 2 versions
- 具体可以参考这篇文章https://www.jianshu.com/writer#/notebooks/49948771/notes/86532182/preview
- 然后当我们的项目打包后,就会将display:flex;加上一些前缀