🌻 前言
我们不介绍所有接入方式,只介绍
推荐的接入方式
。并且一步一步解决遇到的问题和周边扩展本文将介绍
element-plus / uncoss / pinia / normalize 的 接入
, 以及自动化导入ts带来的类型问题
,由于eslint9
的升级,导致很多适配的插件,存在滞后性,本文也将用一些方案来解决这些适配问题
🫑 element-plus 接入
🍅 基本配置
官方链接element-plus.org/zh-CN/guide…
- 安装element-plus
pnpm add element-plus
- 按需导入element-plus
首先你需要安装
unplugin-vue-components
和unplugin-auto-import
这两款插件
pnpm add -D unplugin-vue-components unplugin-auto-import
- 把下列代码插入到你的
Vite
或Webpack
的配置文件中
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
已经生效
👿 服务型组件带来的问题
- 我们为element添加一个消息提示看下效果
import { ElMessage } from 'element-plus'
const infoTip = () => {
ElMessage('This is a message.')
}
<el-button type="info" @click="infoTip">info message</el-button>
样式丢失了? 为什么其他组件的样式没有丢失,唯独 <ELMessage> <ElNotification> 等这种弹框类型的组件,样式会丢失呢?
这是因为Element Plus 的服务型组件(如 Message
、Notification
)的实现机制与普通组件不同,因为它们是通过 JavaScript API 动态调用的,而不是通过模板标签直接使用的。这导致在按需加载时,服务型组件的样式需要额外处理。 通过document.body.appendChild
动态插入到 DOM 中
由于服务型组件,比如
Message
是通过 JavaScript 动态创建的,不像 <el-button>
等普通组件是静态挂载在 Vue 的模板中。由于是动态挂载的,按需加载的工具(如 babel-plugin-component
)不会自动引入它的样式。
- 解决方案: Element Plus 提供了基于 ES Module 的开箱即用的 Tree Shaking 功能。需要安装 unplugin-element-plus 来导入样式
pnpm i unplugin-element-plus
vite
// vite.config.ts
import { defineConfig } from 'vite'
import ElementPlus from 'unplugin-element-plus/vite'
export default defineConfig({
// ...
plugins: [ElementPlus({})],
})
🧪 改进优化
一般我们对于服务型组件,会放到实例上进行调用,做一个统一的封装
- 新建 plugins/element.ts
import type { App } from 'vue'
import { ElMessage, ElNotification, ElMessageBox } from 'element-plus'
export default (app: App) => {
// 都放到组件的实例上了
app.config.globalProperties.$message = ElMessage
app.config.globalProperties.$notify = ElNotification
app.config.globalProperties.$confirm = ElMessageBox.confirm
app.config.globalProperties.$alert = ElMessageBox.alert
app.config.globalProperties.$prompt = ElMessageBox.prompt
}
export type Size = 'default' | 'small' | 'large'
- 在main.ts 进行注册
import element from './plugins/element'
app.use(element)
- 在组件中进行使用
// 将服务型的组件,放到实例上调用
// import { ElMessage } from 'element-plus'
const { proxy } = getCurrentInstance()!
const infoTip = () => {
// ElMessage('This is a message.')
proxy?.$message('This is a message.')
}
此时会报错,
- 声明element的类型 在 tsconfig.app.json 中添加如下配置
// tsconfig.json
{
"compilerOptions": {
// ...
"types": ["element-plus/global"]
}
}
🍅 element-plus 图标使用
- 插件安装
pnpm add @element-plus/icons-vue
- 在min.ts 导入
// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
// 注册所有图标 / 也可以
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
🔗 自动导入组件库/方法 可阅读往期文章
🌹 vue 自动化导入,ts 类型报错问题
🤔 想自动导入其他库/插件,注释掉肯定报错,那我们需要做哪些配置呢?
- 在vite.config.ts 添加要自动导入的插件/库
// vite.config.ts
AutoImport({
// ... other optioins
// api
imports: ['vue', 'vue-router', 'pinia'],
eslintrc: { enabled: true } // 给eslint生产的配置 只需要一次,
}),
- tsconfig.app.json 添加ts文件配置
"types": ["element-plus/global", "./auto-imports.d.ts", "./components.d.ts"]
- 在eslint.config.js 中引入eslintrc-auto-import.json 做全局ts 配置
// eslint.config.js
// esModule commonjs
// 1.
// import autoImport from "./.eslintrc-auto-import.json" with { type: "json" }
// 2.
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const autoImport = require('./.eslintrc-auto-import.json')
// 3.fs.readFile
// 以上三种方式都可以,我们选择第二种方式加载 eslintrc-auto-import.json
export default [
// ...other options
// 2. 定义不同环境的全局变量
{
languageOptions: {
globals: {
...globals.browser,
...globals.node,
...autoImport.globals // 新增
}
}
},
]
ts 报错解决,
🍍 pinia 接入
- 插件安装
pnpm add pinia
- 全局注册
// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
🍅 pinia 基本使用
- 定义仓库
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const name = ref('Eduardo')
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
}
return { count, name, doubleCount, increment }
})
- 使用仓库
<script setup>
import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` and `doubleCount` are reactive refs
// This will also extract refs for properties added by plugins
// but skip any action or non reactive (non ref/reactive) property
const { name, doubleCount } = storeToRefs(store)
// the increment action can just be destructured
const { increment } = store
</script>
🍅 pinia 持久化处理
- 插件安装
pnpm add pinia-plugin-persistedstate
- 全局注册
// main.ts
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { createPinia } from 'pinia'
import element from './plugins/element'
// 注册持久化插件
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
const app = createApp(App)
pinia.use(piniaPluginPersistedstate)
app.use(pinia)
app.use(element)
app.mount('#app')
🍅 持久化基本使用
// counter-store.ts
import { defineStore } from 'pinia'
import { computed, ref, reactive } from 'vue'
export const useCounterStore = defineStore(
'counter',
() => {
const count = ref(0)
const minCount = ref(0)
const obj = reactive({
index: 0
})
// computed 出来的字段
const doubleCount = computed(() => count.value * 2)
function increment() {
count.value++
minCount.value++
obj.index++
}
return { count, minCount, obj, doubleCount, increment }
},
// 只需要新增这一行即可
{
persist: true
}
)
⌚️ 持久化扩展
- 简单配置
{
persist: true
}
- 指定字段持久化
默认情况,persist 会将所有显示声明ref/ reactive
都存储到localStorage 中,computed出来的字段,他是不会存储到内存中的
但是你也可以通过pick
手动指定哪些字段可以存储的内存,以及storage
指定存储位置
{
persist: {
pick: ['count', 'minCount'],
storage: localStorage // or sessionStorage
}
}
🫑 uncoss 接入 unocss.dev/guide/
- 插件安装
pnpm add -D unocss
- vite 中基本配置
// vite.config.ts
import UnoCSS from 'unocss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
UnoCSS(),
],
})
- main.ts 中 添加 virtual:uno.css
// main.ts
import 'virtual:uno.css'
- 新建
uno.config.ts
文件
// uno.config.ts
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS options
})
- 使用 可以参考官网
🍅 扩展
- 插件安装,可以智能提示
- 里面还有很多预设,比如 可以用结合 sass 使用指令@apply, 可以直接使用属性的方式,而不是写在class 里,可以自行探索
🍅 自定义规则
// uno.config.ts
// 自定义规则
shortcuts: {
'flex-center': ['flex', 'justify-center', 'items-center']
}
🐛 normalize 清除默认样式
- 插件安装
pnpm add normalize.css
- 在main.ts 中导入
// main.ts
import "normalize.css/normalize.css";
🍊 写在最后
如果您看到这里了,并且觉得这篇文章对您有所帮助,希望您能够点赞👍和收藏⭐支持一下作者🙇🙇🙇,感谢🍺🍺!如果文中有任何不准确之处,也欢迎您指正,共同进步。感谢您的阅读,期待您的点赞👍和收藏⭐!
本次项目仓库地址: github.com/github-lear…
后续会做成cli, 新项目直接cli 全套就有了
下一篇
- 路由表以及动态路由实现