monorepo+vue3+ts组件库(二)

397 阅读4分钟
  • 通过JS实现BEM规范(块、元素、修饰符):
    • 提高代码的可读性+维护性,尤其在大型项目或多人协作中。
    • 避免样式冲突。
    • 增强组件复用性,便于维护+扩展。
// block 代码块    element 元素    modifier 装饰    state 状态
// z-button
// z-button__element  执行某个功能或起某种作用
// z-button__element--disabled 块或元素的状态或变体
// is-checked is-enabled
// :class=[bem.b()]  工具函数来生成这些类
  • 参考组件库:NaiveUIElement-Plus
  • 问题:定义组件namesetup语法是无法定义组件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地址:xicons
  • theme-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与浏览器环境 image.png
    • 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设置中配置保存格式化代码, image.png image.png
    • 编辑器配置.editorconfig文件,配合EditorConfig for VS Code插件使用
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf

image.png

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'