- 通过JS实现BEM规范(块、元素、修饰符):
- 提高代码的可读性+维护性,尤其在大型项目或多人协作中。
- 避免样式冲突。
- 增强组件复用性,便于维护+扩展。
// block 代码块 element 元素 modifier 装饰 state 状态
// z-button
// z-button__element 执行某个功能或起某种作用
// z-button__element--disabled 块或元素的状态或变体
// is-checked is-enabled
// :class=[bem.b()] 工具函数来生成这些类
- 参考组件库:NaiveUI、Element-Plus
- 问题:定义组件
name,setup语法是无法定义组件name的,需要插件。
// 方式一
<script lang="ts">
export default {
name: 'ZIcon'
}</script>
<script setup lang="ts"></script>
// 方式二:unplugin-vue-define-options 插件
- 根目录下安装unplugin-vue-define-options插件作用:
play目录下安装@vicons/ionicons5依赖包对应Vue3,参考icon图标GitHub地址:xiconstheme-chalk目录下编写scss样式文件theme-chalk\src\mixins\config.scss样式规范配置
$namespace: 'z';
$element-separator: '__';
$modifier-separator:'--';
$state-prefix:'is-';
theme-chalk\src\mixins\mixins.scss混合方法
@use 'config' as *;
@forward 'config';
// .z-button{}
@mixin b($block) {
$B: $namespace+'-'+$block;
.#{$B}{
@content;
}
}
// .z-button.is-desiabled
@mixin when($state) {
@at-root {
&.#{$state-prefix + $state} {
@content;
}
}
}
// &--primary => .z-button--primary
@mixin m($modifier) {
@at-root {
#{&+$modifier-separator+$modifier} {
@content;
}
}
}
// &__header => .z-button__header
@mixin e($element) {
@at-root {
#{&+$element-separator+$element} {
@content;
}
}
}
- scss样式编写有
import语法,可能导致多次引入;使用@use只会引入一次,不会重复引入,默认的私有变量不会被引入;@forward将xxx导出。 - 代码规范:
- 根目录下执行,
Eslint初始化校验代码是否符合规范,命令npx eslint --init遇到问题一路Y就行,需要支持nodejs与浏览器环境 Prettier代码格式化,强制代码风格:执行pnpm i eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser @vue/eslint-config-typescript typescript-eslint eslint-plugin-vue命令.eslintrc.js文件配置:
- 根目录下执行,
module.exports = {
env: {
browser: true,
es2021: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended", // vue3解析 https://eslint.vuejs.org/
"plugin:@typescript-eslint/recommended",
"@vue/typescript/recommended",
],
parserOptions: {
ecmaVersion: "latest",
parser: "@typescript-eslint/parser",
sourceType: "module",
},
plugins: ["vue", "@typescript-eslint"],
rules: {
"vue/html-self-closing": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/multi-word-component-names": "off",
"vue/prefer-import-from-vue": "off",
"vue/attribute-hyphenation": "off",
},
globals: {
defineOptions: "readonly",
},
};
.eslintignore、.prettierignore、.prettierrc.js文件配置:具体内容参考- 安装
Prettier - Code formatter插件,在VSCode设置中配置保存格式化代码,- 编辑器配置
.editorconfig文件,配合EditorConfig for VS Code插件使用
- 编辑器配置
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
vitepress配置
- 默认支持vue组件,
Vitepress编写组件文档:进入docs目录,初始化项目pnpm init,执行pnpm add vitepress -D,组件库文档入口文件index.md
---
layout: home
hero:
name: z-ui 组件库
text: 基于 Vue 3 的组件库.
tagline: 掌握 vue3 组件编写
actions:
- theme: brand
text: 快速开始
link: /guide/quieStart
features:
- icon: 🛠️
title: 组件库构建流程
details: Vue3 组件库构建...
- icon: ⚙️
title: 组件库单元测试
details: Vue3 组件库测试...
---
- docs目录,配置文档运行命令:
package.json文件,script属性添加"dev": "vitepress dev ." - 根目录配置
package.json文件,script属性添加"doc:dev": "pnpm -C docs dev" - 添加
docs/.vitepress/config.js - 将icon组件注册为全局:
docs/.vitepress/theme/index.js,组件量大时,需在packages/components/下做统一导出配置。 - 在
docs目录下创建vite.config.ts,配置vite插件实现组件生效,与play目录配置相同,但无需配置vue。
Tree组件搭建
- vue文件与tsx文件的不同:在vue项目中,会默认对vue文件进行优化,但tsx文件不会。复杂的逻辑,先写vue,后期抽离出来写成tsx文件。
vite支持 jsx 语法插件配置
- 在根目录下,执行
pnpm add @vitejs/plugin-vue-jsx -D -w
组件间的跨级通讯
Provide/Inject
form组件
- 整体组件的封装步骤,由内向外,例如 form 内嵌 form-item,那么先写 form-item 组件,form-item 组件可能内嵌 row col input 等组件,要实现 form-item 内组件间跨级通讯要用到 Provide/Inject,实现 rules规则校验。完成 form-item 组件封装后,在将其包含在 form 组件中。form 组件要实现 data数据+rules规则(会与 form-item 组件的规则合并校验)。
- form-item中 typescript类型校验需要 在根目录中 安装依赖
pnpm add async-validator -w。
upload组件
- 本地服务测试,server.js脚本,安装
pnpm add express multer cors -w,再执行nodemon server/server.js启动本地服务。 - action属性配置:
action="http://localhost:4000/upload" URL.createObjectURL方法接受一个Blob(二进制文件数据块)或File对象,返回一个本地 URL。这个 URL 可以用作文件资源的引用,通常在<img>,<video>,<audio>标签的src属性中使用,实现即时预览效果
// 假设有一个 <input type="file"> 元素
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0]; // 获取用户选择的文件
const fileURL = URL.createObjectURL(file); // 创建一个临时 URL
// 创建一个 <img> 元素来展示文件
const img = document.createElement('img');
img.src = fileURL;
document.body.appendChild(img); // 添加到页面以进行预览
});
Vue3中defineProps使用
可以直接使用isShow,不需要 props.isShow,在setup语法糖中使用defineProps会自动解构并暴露在模板中
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
isShow: Boolean,
});
</script>
<template>
<!-- 直接使用 isShow -->
<div v-if="isShow">内容显示</div>
</template>
虚拟列表组件
- 本地模拟大量数据,根目录下执行
pnpm add mockjs -w,需要ts类型支持pnpm add @types/mockjs -w。 import { Random } from 'mockjs'