$ node -v
v16.13.0
$ npm -v
9.4.0
vite
创建vite项目
$ npm init vite@latest
√ Project name: ... vn
√ Select a framework: » Vue
√ Select a variant: » TypeScript
项目名称设置为vn,框架采用Vue,语言采用TS。
查看版本
"vue": "^3.2.45"
"vite": "^4.1.0"
"typescript": "^4.9.3"
安装依赖并运行测试
$ cd vn
$ npm i
$ npm run dev
浏览器访问 http://127.0.0.1:5173
@types/node
@types/node包含Node.js的类型定义,当需要在Node中是用TS时,需要使用此包来加载所有的类型定义。
$ npm i -D @types/node
查看版本
"@types/node": "^18.13.0"
例如:当需要使用Node.js自带的path包来访问本地文件路径时
为TS配置@types/node
$ vim tsconfig.json
"compilerOptions": {
"typeRoots":["node_modules/@types", "src/types"],
"baseUrl":"./",
"paths":{"@":["src"], "@/*":["src/*"]}
}
为Vite配置@types/node
$ vim vite.config.js
import * as path from 'path'
export default defineConfig({
resolve:{
alias:{'@':path.resolve(__dirname, 'src')}
},
plugins: [vue()],
server:{port:8080, hmr:{host:'127.0.0.1', port:8080}, proxy:{'/api':{
target:'http://127.0.0.1:8770',
changeOrigin:true,
rewrite:(path:string)=>path.replace(/^\/api/, '')
}}}
})
在设置别名和代理时,均需要使用Node的path包下的方法来实现。
eslint
为统一代码的质量风格需安装ESLint
$ npm i -D eslint
添加eslint-plugin-vue插件,使TSLint可检查.vue文件中的<template>、<script>代码,以及JS文件中的Vue代码。
$ npm i -D eslint-plugin-vue
ESLint默认采用Espree进行语法解析,由于无法识别TS的部分语法,因此需安装@typescript-eslint/parser来替代默认解析器。
$ npm i -D @typescript-eslint/parser
@typescript-eslint/eslint-plugin作为ESLint默认规则的补充,可提供额外的适用于TS语法的规则。
$ npm i -D @typescript-eslint/eslint-plugin
为ESLint配置TS解析器@typescript-eslint/parser
$ vim .eslintrc.js
module.exports = {
parser:'vue-eslint-parser',
parserOption:{
parser:'@typescript-eslint/parser',
ecmaVersion:2020,
sourceType:'module',
ecmaFeature:{jsx:true}
},
extends:[
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
],
rules:{
}
}
排除ESLint检查文件范围
$ vim .eslintignore
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
Dockerfile
设置规则
$ vim .eslintrc.js
module.exports = {
root:true,
parser:'vue-eslint-parser',
parserOption:{
parser:'@typescript-eslint/parser',
ecmaVersion:2020,
sourceType:'module',
ecmaFeature:{jsx:true}
},
extends:[
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
//覆盖ESLint格式配置,需在extends最后。
'prettier',
//Prettier额外配置
'plugin:prettier/recommended'
],
rules:{
'vue/valid-template-root':'off',
'vue/no-multiple-template-root':'off',
'vue/multi-word-component-names':['error', {ignores:['index']}]
}
}
为VSCode配置ESLint自动修复
$ settings.json
{
"eslint.validate":["javascript", "javascriptreact", "typescript", "vue"],
"editor.codeActionsOnSave":{
"source.fixAll.eslint":true
},
"editor.formatOnSave":false
}
Prettier
Prettier是前端代码格式化工具,用于团队开发统一代码风格。
VS Code安装Prettier - Code formatter插件
安装Prettier
$ npm i -D prettier
由于ESLint中的样式规范和Prettier存在冲突,为了以Prettier为准需安装eslint-config-prettier。
$ npm i -D eslint-config-prettier
Prettier触发插件,将Prettier作为ESLint规则来使用,若代码不符合Prettier规范则报一个ESLint错误。
$ npm i -D eslint-plugin-prettier
为ESLint配置Prettier
$ vim .eslintrc.js
extends:[
'plugin:vue/vue3-recommended',
'plugin:@typescript-eslint/recommended',
//覆盖ESLint格式配置,需在extends最后。
'prettier',
//Prettier额外配置
'plugin:prettier/recommended'
],
rules:{
'prettier/prettier':'warn',
}
配置Prettier规则,创建名为.prettierrc.js或prettier.config.js的配置文件。
$ vim .prettierrc.js
.editorconfig
VS Ccode安装EditorConfig for VS Code插件
$ vim .editorconfig
root = true
[*] # 针对所有文件
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md] # 仅针对 md 文件
insert_final_newline = false
trim_trailing_whitespace = false
| 配置 | 说明 |
|---|---|
charset | 字符编码 |
indent_style | 缩进风格 |
end_of_line | 统一行尾符 |
样式
postcss
Vite默认配置CSS的参数
$ vim vite.config.js
export default defineConfig({
css:{
// CSS模块化配置
modules:{},
// CSS预处理器配置
preprocessorOptions:{}
}
})
由于CSS在不同浏览器下兼容性不同,某些特殊样式在不同浏览器前需添加与之对应的前缀来实现兼容。为实现浏览器兼容,需要将所有CSS前缀补齐,可使用postcss来实现。
postcss是一个用JS工具和插件转换CSS代码的工具,PostCSS本身是平台,需下载各种插件来实现对应功能。典型的如PostCSS Preset Env插件会将最新的CSS语法转化为大多数浏览器都能理解的语法。
安装PostCSS
$ npm i -D postcss
安装postcss-preset-env
$ npm i -D postcss-preset-env
创建PostCSS配置文件
$ vim postcss.config.js
module.exports = {
plugins:[
require('postcss-preset-env')
]
}
运行错误
[vite] Internal server error: Failed to load PostCSS config
This file is being treated as an ES module because it has a '.js' file extension and 'E:\yey\repo\vn\package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
将postcss.config.js文件名修改为postcss.config.cjs即可。
taiwindcss
$ npm i -D tailwindcss
$ npm view tailwindcss version
3.2.4
创建配置文件
$ npx tailwindcss init -p
命令执行后会生成tailwind.config.cjs配置文件
$ vim tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [],
theme: {
extend: {},
},
plugins: [],
}
同时还会创建postcss.config.cjs
$ vim postcss.config.js
module.exports = {
plugins:[
require("tailwindcss"),
require("postcss-preset-env"),
]
}
配置Tailwind来移除生产环境下没有使用的样式生命
$ vim tailwind.config.cjs
/** @type {import('tailwindcss').Config} */
module.exports = {
// darkMode: 'class',
plugins: [createEnterPlugin()],
content: {
enable: process.env.NODE_ENV === 'production',
content: ['./index.html', './src/**/*.{vue,ts,tsx}'],
},
corePlugins: {
preflight: false,
},
theme: {
extend: {
zIndex: {
'-1': '-1',
},
colors: {
primary: {
DEFAULT: '#0960bd',
// dark: primaryColorDark,
},
},
screens: {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
'2xl': '1600px',
},
},
},
};
/**
* Used for animation when the element is displayed
* @param maxOutput The larger the maxOutput output, the larger the generated css volume
*/
function createEnterPlugin(maxOutput = 6) {
const createCss = (index, d = 'x') => {
const upd = d.toUpperCase();
return {
[`*> .enter-${d}:nth-child(${index})`]: {
transform: `translate${upd}(50px)`,
},
[`*> .-enter-${d}:nth-child(${index})`]: {
transform: `translate${upd}(-50px)`,
},
[`* > .enter-${d}:nth-child(${index}),* > .-enter-${d}:nth-child(${index})`]: {
'z-index': `${10 - index}`,
opacity: '0',
animation: `enter-${d}-animation 0.4s ease-in-out 0.3s`,
'animation-fill-mode': 'forwards',
'animation-delay': `${(index * 1) / 10}s`,
},
};
};
const handler = ({ addBase }) => {
const addRawCss = {};
for (let index = 1; index < maxOutput; index++) {
Object.assign(addRawCss, {
...createCss(index, 'x'),
...createCss(index, 'y'),
});
}
addBase({
...addRawCss,
[`@keyframes enter-x-animation`]: {
to: {
opacity: '1',
transform: 'translateX(0)',
},
},
[`@keyframes enter-y-animation`]: {
to: {
opacity: '1',
transform: 'translateY(0)',
},
},
});
};
return { handler };
}
创建样式文件并引入
$ vim src/styles/tailwind.css
/*! @import */
@tailwind base;
@tailwind components;
@tailwind utilities;
在入口文件中引入
$ vim src/main.ts
import './styles/tailwind.css'
unocss
Tailwind原子样式会生成大量样式定义,全量的CSS文件体积会多达数MB,这对页面性能是完全不能接受的。若在开发时动态按需裁剪,会影响编译性能,降低开发体验。为解决性能问题,Antfu设计了UnoCSS,一个拥有高性能且灵活的即时原子化CSS引擎,可兼顾产物体积和开发性能。
UnoCSS作为CSS引擎本身并不提供任何类名,只为解决Tailwind、Windi的编译和打包性能问题。
$ npm i -D unocss
$ npm view unocss version
0.49.4
为Vite添加UnoCSS插件,UnoCSS已内置preset-uno以提供提供快捷类支持。
$ vim vite.config.js
import Unocss from 'unocss/vite'
export default defineConfig({
plugins: [
Unocss(),
],
})
全局主文件中引入Unocss
$ vim src/main.ts
import 'uno.css'
unocss/preset-uno
unocss/preset-uno是UnoCSS的插件支持包,导入后可在代码中使用Tailwind CSS、Windi CSS、Bootstrap、Tachyons等插件的快捷类。当你使用上述任意一种快捷类风格编码时(建议以TailwindCSS为准),UnoCSS将配合preset-uno自动对其匹配。
$ npm i -D @unocss/preset-uno
$ npm view @unocss/preset-uno version
0.49.4
配置
$ vim vite.config.js
import Unocss from 'unocss/vite'
import presetUno from '@unocss/preset-uno'
export default defineConfig({
plugins: [
Unocss({
presets:[
presetUno()
]
})
]
})
daisyUI
daisyUI是一个可定制的TailwindCSS组件库,类似Bootstrap。
$ npm i -D daisyui
$ npm view daisyui version
2.50.0
TailwindCSS配置daisyUI插件
$ vim src/tailwind.config.cjs
module.exports = {
plugins: [
require('daisyui')
],
}
异步组件
以往页面加载的过程是当所有组件都加载完毕后,页面才全部渲染。如果用户网速慢就需要等待一定时间后才能看到。使用异步组件,可以实现让已经加载完毕的组件先渲染到页面中显示。
异步组件使用<Suspense>标签作为占位符,使用提示信息占位还没有加载的组件,这样可以有效的改善用户体验。
runtime-core.esm-bundler.js:40
[Vue warn]: <Suspense> slots expect a single root node. at <App>
当在<Suspense>标签中插入多个组件时,需给每个标签包裹一个跟标签。即当多个组件嵌套使用时,需将每个组件包裹在<div>中。
$ vim App.vue
<template>
<Suspense>
<template #default>
<div><RouterView /></div>
</template>
<template #fallback>
<div></div>
</template>
</Suspense>
</template>
<Suspense>是一个实验特性,其API可能会改变。
<Suspense> is an experimental feature and its API will likely change.
vue-router
$ npm i -D vue-router
$ npm view vue-router version
4.1.6
创建路由文件
$ vim src/router/index.ts
import {createRouter, createWebHistory, RouteRecordRaw} from 'vue-router'
const routes:Array<RouteRecordRaw> = [
{
path:'/',
name:'Home',
component:()=>import('@/views/home/index.vue'),
meta:{title:'首页', keepAlive:true}
}
]
const router = createRouter({
history:createWebHistory(),
routes
})
export default router
入口文件使用路由
$ vim src/main.ts
import './styles/tailwind.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router'
const app = createApp(App)
app.use(router)
app.mount('#app')
修改框架页面
$ vim App.vue
<script setup lang="ts">
</script>
<template>
<RouterView />
</template>
<style scoped>
</style>
创建Home页
$ vim src/views/home/index.vue
<script setup lang="ts">
</script>
<template>
<div>HOME</div>
</template>
<style scoped>
</style>
VueUse
VueUse是一个基于Composition API组合式API的实用函数集合
安装
$ npm i @vueuse/core
vfonts
安装字体
$ npm i -D vfonts
入口文件配置字体
$ vim main.ts
// 通用字体
import 'vfonts/Lato.css'
// 等宽字体
import 'vfonts/FiraCode.css'
Naive UI
安装UI
$ npm i -D naive-ui
自动按需引入组件,免除手动引入。
$ npm i -D unplugin-auto-import
$ npm i -D unplugin-vue-components
配置插件
$ vim vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import {NaiveUiResolver} from 'unplugin-vue-components/resolvers'
export default defineConfig({
plugins: [
vue(),
AutoImport({
imports:['vue', {'naive-ui':['useDialog', 'useMessage', 'useNotification', 'useLoadingBar']}]
}),
Components({resolvers:[NaiveUiResolver()]})
],
});
执行npm run dev命令后会在根目录下生成auto-imports.d.ts和components.d.ts两个类型声明文件。将类型声明文件components.d.ts添加到tsconfig.json的include配置项中,鼠标移动到组件上时会自动出现类型提示信息。
$ vim tsconfig.json
{
"include": [
"src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue",
"components.d.ts"
],
}
测试效果:在首页文件中添加NativeUI组件,查看显示。
$ vim src/views/home/index.vue
<script setup lang="ts">
</script>
<template>
<n-space m-50>
<n-button>Default</n-button>
<n-button type="tertiary"> Tertiary </n-button>
<n-button type="primary"> Primary </n-button>
<n-button type="info"> Info </n-button>
<n-button type="success"> Success </n-button>
<n-button type="warning"> Warning </n-button>
<n-button type="error"> Error </n-button>
</n-space>
</template>
<style scoped>
</style>