vue3+vite脚手架配置
环境要求:vite及vue3需要node版本大于12
# 1. vue3的优势
- 性能比Vue2.x快1.2~2倍
- diff方法优化: vue2中的虚拟dom是全量的对比(每个节点不论写死的还是动态的都会比较), vue3新增了静态标记(patchflag)与上次虚拟节点对比时,只对比带有patch flag的节点(动态数据所在的节点);可通过flag信息得知当前节点要对比的具体内容
- 静态提升 vue2无论元素是否参与更新,每次都会重新创建然后再渲染 vue3对于不参与更新的元素,会做静态提升,只会被创建一次,在渲染时直接复用即可
- 时间侦听器缓存 默认情况下onClick会被视为动态绑定,所以每次都会追踪它的变化 但是因为是同一个函数,所以不用追踪变化,直接缓存起来复用即可
- 按需编译,体积比vue2.x更小
- 组合API(类似react hooks)
- 更好的Ts支持
- ...
# 2. vite的优势
就一个字:快
这个快体现在开发时的编译和热更新上。 webpack会先打包,然后启动开发服务器,请求服务器时直接给予打包结果。
而vite是直接启动开发服务器,请求哪个模块再对该模块进行实时编译。 由于现代浏览器本身就支持ES Module,会自动向依赖的Module发出请求。vite充分利用这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,而不是像webpack那样进行打包合并。
由于vite在启动的时候不需要打包,也就意味着不需要分析模块的依赖、不需要编译,因此启动速度非常快。当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。 在HMR(热更新)方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。
- 简洁的说,就是vite在开发编译的时候,动态编译,哪个改了编译哪个。而webpack是要把该模块的相关依赖模块编译一次
- 注意点: 由于vite利用的是ES Module,因此在代码中(除了vite.config.js里面,这里是node的执行环境)不可以使用CommonJS. 也就是说不能使用require
# 3. 创建一个vite项目
cmd 进入你想要创建项目的文件夹
npm init @vitejs / app
//然后按提示操作
@vitejs/create-app is deprecated, use npm init vite instead
√ Project name: ... test project
√ Package name: ... test-project
√ Select a framework: » vue
√ Select a variant: » vue-ts
Scaffolding project in D:\zhuyunjing\src\test\test project...
Done. Now run:
cd test project
npm install
npm run dev
安装好依赖启动就可以了
也可以直接命令行添加参数
# npm 6. x
npm init @vitejs / app my - vue - app--template vue
# npm 7 + , 需要额外的双横线:
npm init @vitejs / app my - vue - app-- --template vue
# yarn
yarn create @vitejs / app my - vue - app--template vue
# 4. vite.config.js
这个文件就相当于vue.config.js的作用,基本写法也类似
import {
defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'
import {
resolve
} from 'path'
import copy from 'rollup-plugin-copy' //引入插件
import viteCompression from 'vite-plugin-compression';
export default defineConfig({
plugins: [
vue(),
// viteCompression(), //gzip压缩,需要服务端支持
],
resolve: {
alias: {
'@': resolve('./src'),
},
}, //别名
base: './',
server: {
port: 8010, // 服务端口号
open: true, // 服务启动时是否自动打开浏览器
cors: true, // 允许跨域
proxy: {
'/dealerWebApi': {
target: 'http://192.168.100.107:30058/',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/dealerWebApi/, ''),
},
},
},
// 生产环境移除console
build: {
terserOptions: {
compress: {
drop_console: true,
},
},
rollupOptions: {
output: {
//设置打包后的路径
entryFileNames: `js/app.[hash].js`,
chunkFileNames: `js/chunk.[hash].js`,
assetFileNames: `assets/[hash].[ext]`
}
}
}
})
# 5. Router的配置
// 利用createRouter方法创建路由。有createWebHistory和createWebHashHistory良种模式
import {
createRouter,
createWebHashHistory
} from 'vue-router'
const routes = [{
path: '/userinfo',
name: 'UserInfo',
component: () => import('../views/UserInfo.vue')
}]
// hash模式
const router = createRouter({
history: createWebHashHistory(),
routes,
})
// histtory模式
const router = createRouter({
history: createWebHistory(
import.meta.env.VITE_APP_BASE_API),
routes
})
# 6. postCss适配
安装 "postcss-pxtorem",然后添加postcss.config.js
module.exports = {
plugins: {
'autoprefixer': {
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8"
//'last 2 versions', // 所有主流浏览器最近2个版本
],
grid: true
},
'postcss-pxtorem': {
rootValue: 100, //结果为:设计稿元素尺寸/100,比如元素宽100px,最终页面会换算成 1rem
propList: ['*'], //对于哪些css生效,可以写['*', '!border*']意思是排除带有border的属性
selectorBlackList: []. //忽略的选择器,可以将vant或者ant的文件去除,但是不推荐,因为去除了就不能适配了。
}
}
}
然后创建一个rem.js
export default class RemInit {
public setRem(): void {
// 基准大小
const baseSize = 100
const basePc = baseSize / 1920 // 表示1920的设计图,使用100PX的默认值
let vW = window.innerWidth // 当前窗口的宽度
const vH = window.innerHeight // 当前窗口的高度
// 非正常屏幕下的尺寸换算
const dueH = (vW * 937) / 1920 // PC 去掉地址栏高度取 设计稿取 1920 * 937
if (vH < dueH) {
// 当前屏幕高度小于应有的屏幕高度,就需要根据当前屏幕高度重新计算屏幕宽度
vW = (vH * 1920) / 1080
}
const rem = vW * basePc // 以默认比例值乘以当前窗口宽度,得到该宽度下的相应font-size值
document.documentElement.style.fontSize = rem + 'Px'
}
}
export const remInit = new RemInit()
在main.js引入一下
import { remInit } from './utils/RemInit'
remInit.setRem()
window.onresize = function () {
remInit.setRem()
}
这样设置之后,在css写100px,在渲染时会自动变成1rem。而根元素的fontSize会根据实际的比例进行缩放,默认是100.这样的话,在1920*1080的分辨率下,写100px,页面会渲染成1rem,且对应的实际尺寸还是100px。就正常按设计稿的尺寸去写就醒了。
# 7. 环境变量
除了内置的变量以外,其他的要以VITE_APP_XXXX开头。 使用的时候 import.meta.env. VITE_APP_BASE_API。其他的和webpack一样的,再packge.js设置不同的mode
# 8. 全局注册组件
因为vite环境里用不了require,所以找了替代方法,效果差不多
import {
App
} from 'vue'
/*
**全局注册组件
** 放在components/global文件夹下
*/
const modulesFiles =
import.meta.globEager('/src/component/global/*.vue') /// import.meta.globEager用来代替require因为vite不支持node语法require
const globalResult = Object.keys(modulesFiles).filter(item => true)
export default (app: App < Element > ) => {
globalResult.forEach(item => {
const component = modulesFiles[item]?.default
app.component(component.name, component)
})
}
# 9. Composition-API 的优势实现代码分离。
- 代替mixins 用多了会比较混乱,由于API是基于函数的,因此可以有效地组织和编写可重用的代码。实现代码分离。
- 在Vue应用程序中更好地使用TypeScript。
- Composition-API 不是给你写一堆代码再setup里面的,要适当地分离、组织
# 10. setUp函数拆分
//创建一个js
import {
ref
} from 'vue'
export function useBigImg(pageOption ? : PageOption) {
const bigImgShow = ref < boolean > (false)
const bigImgSrc = ref < string > ('')
const showModal = (src: string) => {
bigImgSrc.value = src
bigImgShow.value = true;
};
onMounted(() => {
console.log('111111)
})
return {
bigImgShow,
bigImgSrc,
showModal
}
}
然后在vue文件中引用,就可以再html里用了
import {
useBigImg
} from './index
export default defineComponent({
name: 'ITable',
props,
emits: ['handleTableChange'],
setup(props, context) {
//预览图放大功能
const {
bigImgSrc,
showModal,
bigImgShow
} = useBigImg()
return {
bigImgSrc,
showModal,
bigImgShow,
}
},
})
这种拆分可以在任何文件里倒入,类似于hooks的方法。一般以useXXX命名