vite tailwindcss naive-ui 1

703 阅读1分钟
$ 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.jsprettier.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.tscomponents.d.ts两个类型声明文件。将类型声明文件components.d.ts添加到tsconfig.jsoninclude配置项中,鼠标移动到组件上时会自动出现类型提示信息。

$ 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>