组件库的架构 | 青训营笔记

308 阅读7分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天

组件库:项目架构

一、搭建一个vite项目

1、使用yarn创建vite项目

yarn create vite

2、安装jsx

yarn add @vitejs/plugin-vue-jsx -D

3、此时在vite.config.ts文件下导入内容如下

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue(), vueJsx({})],
})

二、配置代码规范eslint+prettier

1、安装eslint

npx eslint --init
  • 回答1: To check syntax and find problems

  • 回答2: JavaScript modules (import/export)

  • 回答3: Vue.js

  • 回答4: "Does your project use TypeScript?" Yes

  • 回答5: Browser

  • 回答6: JavaScript

// 此时package.json多出来几行代码
// 把"type":module删掉
	"script": {
    ...
    "lint": "eslint . --ext .js,.ts,.tsx,.vue --fix"
    // 手动增加
  }	

  "devDependencies": {
    "@typescript-eslint/eslint-plugin": "^5.48.2",
      // ts-eslint插件
    "@typescript-eslint/parser": "^5.48.2",
      // ts-eslint
    "@vitejs/plugin-vue": "^4.0.0",
    "@vitejs/plugin-vue-jsx": "^3.0.0",
    "eslint": "^8.32.0",
      // js-eslint
    "eslint-plugin-vue": "^9.9.0",
      // vue-eslint
    "typescript": "^4.9.3",
    "vite": "^4.0.0",
    "vue-tsc": "^1.0.11"
  }
  • 运行监测是否生效

yarn lint
  • 配置一下.eslintrc.js文件(把.cjs改成.js)

module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    "plugin:@typescript-eslint/recommended",
    "plugin:vue/vue3-recommended",
  ],
  parserOptions: {
    ecmaVersion: "latest",
    parser: "@typescript-eslint/parser",
    sourceType: "module",
    jsx: true,
    tsx: true,
  },
  plugins: ["vue", "@typescript-eslint"],
  rules: {},
};

2、整合prettier

  • 安装prettier

yarn add -D prettier eslint-plugin-prettier eslint-config-prettier
  • 在.eslintrc.js引入prettier

extends: [
...
'plugin:prettier/recommended'
],
  • 创建.prettierrc.js

module.exports = {
  // printWidth: 80,
  // tabWidth: 2,
  // useTabs: false,
  semi: false, // 未尾分号, default:  true
  singleQuote: true, // 单引号 default: false
  trailingComma: "none", // 未尾分号 default: es5    all | none | es5
  arrowParens: "avoid", // default: always
  proseWrap: "never",
  endOfLine: "auto", // default lf
};
  • 此时代码规范由prettier接管,可以再运行一次yarn lint看看有没有报错

3、安装lint-staged并生成husky默认配置文件(在此之前必须将项目上传到github)

npx mrm@2 lint-staged

三、基于VitePress的文档系统

1、安装VitePress

yarn add -D vitepress

2、创建文档目录

mkdir docs && echo '# hello vitepress' > docs/index.md
  • 此时项目生成了一个docs文件夹

3、在package.json中配置

"scripts": {
	...
  "docs:dev": "vitepress dev docs",
    // 预览命令
  "docs:build": "vitepress build docs",
    // 创建命令
  "docs:serve": "vitepress serve docs",
    // 本地跑预览(生产版本)
},
  • 跑一下

yarn docs:dev

4、配置文档

  • 组件内容: 在docs/components下创建Button、Input、Tree、Space等等组件

  • 侧边栏sidebar

    • 在docs文件夹下创建.vitepress文件夹,在.vitepress文件夹下创建config.ts进行导航配置
    const sidebar = {
      '/': [
        { text: '快速开始', link: '/', items: [] },
        {
          text: '通用',
          items: [{ text: 'Button 按钮', link: '/components/button/' }]
        },
        { text: '导航', items: [] },
        { text: '反馈', items: [] },
        {
          text: '数据录入',
          items: [{ text: 'Input 输入框', link: '/components/input/' }]
        },
        { text: '数据展示', items: [
          { text: 'Tree 树', link: '/components/tree/' }
        ] },
        { text: '布局',
          items:[
            { text:'Space 间距',link:'/components/space/'}
          ]
        }
      ]
    }
    
    const config = {
      themeConfig: {
        sidebar,
      }
    }
    
    export default config
    
  • 在.vitepress下创建index.md

# hello vitepress
  • 主题theme:创建docs->.vitepress->theme->index.ts

import Theme from 'vitepress/theme'
import HelloWorld from '../../../src/components/HelloWorld.vue'

export default {
	...Theme,
	enhanceApp({app}) {
		// 注册组件
		app.component('HelloWorld', HelloWorld)
	}
}
  • 在button->index.md中引入即可在页面显示组件内容

# Button - 按钮
<HellowWorld></HelloWord>
  • 配置jsx: 创建docs->vite config.ts

import {defineConfig} from 'vite'
import vueJsx from '@vitejs/plugin-vue-jsx'

export default defineConfig({
  plugins: [vueJsx()]
})
  • 显示代码的配置

    • 安装插件
    yarn add -D vitepress-theme-demoblock
    
    • 配置.vitepress->config.ts
    const config = {
      themeConfig: {
        sidebar,
      },
      markdown: {
        config(md) {
          // 是用markdown-it插件
          const { demoBlockPlugin } = require('vitepress-theme-demo-demoblock')
          md.use(demoBlockPlugin)
        }
      }
    }
    
    • 在theme->index.ts中注册两个组件
    import 'vitepress-theme-demoblock/dist/theme/index.mjs'
    import DemoBlock from 'vitepress-theme-demoblock/dist/client/components/DemoBlock.vue'
    import Demo from 'vitepress-theme-demoblock/dist/client/components/Demo.vue'
    
    export default {
      enhanceApp({ app }) {
        app.component('DemoBlock', DemoBlock)
        app.component('Demo', Demo)
      }
    }
    
    • 随后即可使用特殊语法编写组件
    # Button - 按钮
    
    :::demo 这是HelloWorld的组件
    ```vue
    <template>
      <HelloWorld></HelloWorld>
    </template>
    ```
    :::
    

5、更多vitepress相关内容参考官方文档

四、配置样式体系

1、引入Tailwind CSS,可以利用它的样式体系,写的时候比较简单,结合Sass

2、安装依赖

npm i -D sass tailwindcss postcss autoprefixer
// 初始化tailwind
npx tailwindcss init -p

3、安装完之后有两个配置文件生成

  • tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./index.html",
    "./src/**/*.{vue,js,ts,jsx,tsx}"
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
  • src->index.scss

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";
  • src->main.ts

import './index.scss'

4、TailwindCSS优点

1 自定义

它带有一个默认配置,你可以使用项目中的 “tailwind.config.js” 来覆盖默认配置。从颜色到间距大小和字体的所有内容都可以使用配置文件轻松定制。不再修改框架文件,尝试找出要覆盖哪些类才能得到您想要的结果。

2 不需要关心命名

在编写自定义 CSS 时,我最讨厌的事情之一就是命名类。哪些类应该是特定的?哪些类应该更通用?你如何组织它们并确保它们以正确的顺序级联?Tailwind 通过提供 99% 时间可用的实用程序类解决了所有这些问题。唯一需要命名的时候是提取组件的时候。

3 不需要切换上下文

由于框架提供了几乎所有你需要的开箱即用的东西,所以在构建设计时很少会留下 HTML (或其他模板语言)。不再需要数百次从 HTML 切换到 CSS 这让设计看起来恰到好处。

4 更简单的创建组件

尽管 Tailwind 主要是一个实用的 CSS 框架,但是它使得从这些实用的组合中创建定制组件变得非常简单。在几乎每个项目中,我都使用 “@apply” 指令提取按钮和其他表单元素的组件类。还可以在 CSS 文件中使用 ' theme () ' 函数从配置文件中获取值,比如颜色和间距大小,而不是硬编码它们。

5 开发速度

因为您不需要命名一些东西,也不需要频繁地切换上下文,而且您也不需要为定制而与框架作斗争,所以使用 Tailwind 来创建原型和实现定制设计是非常快的。比大多数其他 CSS 框架快得多,也比编写自定义 CSS 快得多。Tailwind 提供了构建站点所需的几乎所有工具,因此很少需要编写任何自定义 CSS。如果您更喜欢像 .btn 和 .panel ,你可以很容易地去创建它们,以便在整个项目中使用。

6 支持响应式

Tailwind(生成 CSS) 的所有公用程序都是使用响应版本生成的,能够让您的站点在移动、平板和桌面屏幕上看起来有不同的效果。除此之外,它还提供了 @screen 和 @responsive 指令来帮助(您)生成自定义响应式类。

7 缓存益处

使用传统的 CSS 框架或自定义 CSS ,在更改设计时,很可能需要更改 CSS 文件。然而,当使用 Tailwind 工具时,由于您在标记中反复使用相同的类而不是更改 CSS 文件,所以您甚至不必破坏 CSS 缓存来对设计进行小的更改。这意味着用户不必经常重新下载 CSS 文 件。

8 可靠性

当你使用传统的 CSS 时,如果不小心更改一个页面的设计可能会影响到另一个页面。使用 Tailwind,您所做的任何更改都将在模板中进行,因此只影响正在处理的页面。这样可以更容易地更改单个页面,而不用担心可能造成的副作用。

五、配置jsx、tsx

1、声明组件的方式和语法

import { defineComponent, withModifiers } from 'vue'

export default defineComponent({
  // 自定义指令
  directives: {
    focus: {
      mounted(el) {
        el.focus()
      }
    }
  }
  // 向外派发
  emits: ['click'],
	setup(props, { slots, emit }) {
    const count = ref(0)
    const list = ref<string[]>(['a', 'b', 'c'])
    const inc = () => {
      count.value++
      emit('click')
    }
		return () => {
      const span = condition ? <span>A</span> : <span>B</span>
			return <div onClick={withModifiers(inc, ['self'])}>
      	text: {count.value}
        // v-if的代替写法
      	<div>{ span }</div>
    		// v-for用map进行映射
    		<ul>
          {list.value.map((str) => <li key={str}>{str}</li>)}
        </ul>
  			// 自定义指令使用
  			<input type="text" v-focus />
      </div>
		}
	}
})

2、插槽的使用

// 使用组件
<Test @click>
	<template #default>aaa</template>
  <template #title>bbb</template>
</Test>
// 组件
// setup(props, {slots})
<div>{slots.default ? slots.default() : 'default content'}</div>
<div>{slots.title ? slots.title() : 'title slot content'}</div>

3、jsx和template的对比

  • jsx特点(JavaScript的语法扩展):

    • 数据绑定使用单括号语法
    • 更偏重逻辑的处理。
    • 更细粒度的控制交互细节,比如:使用一个首字母大写的变量,HTML标签可动态生成。
    • 拥有js完全编程能力,一切可以变量化,这样理解吧。
  • 模板语法(HTML的扩展):

    • 数据绑定使用Mustache语法
    • 主要用于快速构建页面,不方便写入较复杂的逻辑处理。
    • 使用上更局限于vue本身的指令api,无法做到编码随心所欲。