这是我参与「第五届青训营 」伴学笔记创作活动的第 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,无法做到编码随心所欲。
-