viteePress搭建组件文档

 

目录

安装vitepress

目录结构

文档首页

Home Page 

Hero 部分 

Features 部分 

导航栏配置

logo

导航链接

socialLinks 

侧边栏

基本使用

多个侧边栏

使用组件

在 markdown 中导入组件 

在 theme 中注册全局组件

部署到Github Pages

前提

第一步

第二步 

第三步


 

viteePress搭建组件文档_第1张图片

每个组件库都有它们自己的文档。所以当我们开发完成我们自己的组件库必须也需要一个组件库文档。,所以下面就以element-plus作为示例来搭建一个文档吧。

vitepress中文官网:VitePress | 由Vite、Vue驱动的静态网站生成器Vite & Vue powered static site generator.icon-default.png?t=N7T8https://process1024.github.io/vitepress/

安装vitepress

安装vitepress

pnpm add vitepress -D

 在 package.json添加一些script

"scripts": {
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:serve": "vitepress serve docs"
  }

目录结构

viteePress搭建组件文档_第2张图片

  • .vitepress/config.js为配置文件

  • public是公共文件目录

  • index.md则是组件库文档的首页

  • guide放我们组件指南文档

  • assembly放组件文档

 Public 文件

有时你可能需要提供一些 Markdown 或主题组件中未直接引用的静态资源(例如,网站图标和 PWA 图标)。 项目根目录下的 public 目录(如果你正在运行 vitepress build docs,则为 docs 文件夹)将会保留,用以提供源代码中从未引用的静态资源(例如 robots.txt )和需要保留完全相同的文件名(不生成哈希)的资源。

放在 public 中的资源将会直接复制到 dist 的根目录。

注意,你应该使用根绝对路径引用放在 public 中的文件 - 例如,public/icon.png 在源代码中应始终引用为 /icon.png

文档首页

首先我们按照官网的样式给我们组件库整个首页,在index.md文件中写入

---
layout: home

hero:
  name: ElementPlus 二次封装
  text: 一个Vue3组件库
  tagline: 使用json形式渲染表格、表单
  image:
    src: /logo.png
    alt: 贾公子
  actions:
    - theme: brand
      text: 开始
      link: /guide/form
    - theme: alt
      text: 在 Gitee 上查看
      link: https://gitee.com/childe-jia

features:
  - icon: 
    title: 个人博客
    details: 日常工作、学习踩坑记录
    link: https://blog.csdn.net/qq_63358859
  - icon: 
    title: 表单
    details: 基于json渲染form表单
    link: https://gitee.com/childe-jia/form-render
  - icon: ️
    title: 表格
    details: 基于json渲染form表格
    link: https://gitee.com/childe-jia/table-vue3
---

Home Page 

VitePress 默认主题提供主页布局,您也可以在 本站主页 上看到使用的主页布局。 您可以通过在任何页面 通过 frontmatter 中指定 layout: home 使用它。 

但是,仅此选项不会有太大作用。 您可以通过设置额外的其他选项(例如hero 和 features)将几个不同的预模板“部分”添加到主页。

---
layout: home
---

Hero 部分 

Hero 部分位于主页的顶部。 以下是配置 Hero 部分的方法。

interface Hero {
  // `text' 的字符串所示。带有品牌颜色,通常会很短,例如项目名称。
  name?: string

  // hero 部分的文本。这将被定义成`h1`标签
  text: string

  // Tagline 会展示在 `text` 下面.
  tagline?: string

  // action 按钮显示在 hero 区域。
  actions?: HeroAction[]
}

interface HeroAction {
  // 按钮的的主题颜色,默认为 `brand`.
  theme?: 'brand' | 'alt'

  // 按钮的文案.
  text: string

  // 按钮链接.
  link: string
}

Features 部分 

interface Feature {
  // 在 feature 框里展示icon,目前只支持emoji
  icon?: string

  // feature 标题.
  title: string

  // feature 详情.
  details: string
}

然后pnpm run docs:dev启动我们的项目,我们就可以看到这样的画面

viteePress搭建组件文档_第3张图片

是不是感觉已经有点组件库文档的意思了。接下来对导航栏以及我们们文档的侧边栏进行一个配置 

导航栏配置

我们在config.js中配置我们的logo、导航栏以及社交链接。此时我们的导航栏便配置完成

base为部署配置必须跟仓库名一样

export default {
  themeConfig: {
    base: "/jiayc4215/",
    siteTitle: false,
    logo: "/logo.png",
    nav: [
      { text: "指南", link: "/guide/form" },
      { text: "组件", link: "/assembly/form/basic" },
    ],
    socialLinks: [{ icon: "github", link: "https://gitee.com/childe-jia" }],
  
  },
};

可以通过配置logo来展示网站的logo,logo应该直接放在 public 中,并定义为绝对路径。

export default {
  themeConfig: {
    logo: '/my-logo.svg'
  }
}

添加logo后将会与网站标题一起显示。如果只想要展示logo而隐藏标题,请将 siteTitle 设置为 false

export default {
  themeConfig: {
    logo: '/my-logo.svg',
    siteTitle: false
  }
}

导航链接

你可以通过定义 themeConfig.nav 选项来添加链接到导航。

export default {
  themeConfig: {
    nav: [
      { text: 'Guide', link: '/guide' },
      { text: 'Configs', link: '/configs' },
      { text: 'Changelog', link: 'https://github.com/...' }
    ]
  }
}

text 是 nav 中显示的实际文本,link 是单击文本时将导航到的链接。链接的路径设置为不带 .md 前缀的实际文件,并始终以 / 开头。

socialLinks 

您可以定义此选项以在导航中展示带有图标的社交帐户链接。

export default {
  themeConfig: {
    socialLinks: [
      { icon: 'github', link: 'https://github.com/vuejs/vitepress' },
      { icon: 'twitter', link: '...' },
      // 你也可以自定义svg的icon:
      {
        icon: {
          svg: 'Dribbble'
        },
        link: '...'
      }
    ]
  }
}

侧边栏

首先我们对指南的侧边栏做一个配置

viteePress搭建组件文档_第4张图片

   sidebar: {
      "/guide/": [
        {
          text: "快速开始",
          items: [
            {
              text: "表单Form",
              link: "/guide/form",
            },
            {
              text: "表格table",
              link: "/guide/table",
            },
          ],
        },
      ],
      "/assembly/": [
        {
          text: "表单Form",
          items: [
            { text: "base", link: "/assembly/form/basic" },
            { text: "checkbox-group", link: "/assembly/form/checkbox-group" },
            { text: "content", link: "/assembly/form/content" },
            { text: "date-picker", link: "/assembly/form/date-picker" },
            { text: "deprecated", link: "/assembly/form/deprecated" },
            { text: "disabled", link: "/assembly/form/disabled" },
            { text: "el", link: "/assembly/form/el" },
            {
              text: "get-component-by-id",
              link: "/assembly/form/get-component-by-id",
            },
            { text: "get-form-value", link: "/assembly/form/get-form-value" },
            { text: "hidden", link: "/assembly/form/hidden" },
            { text: "next-tick", link: "/assembly/form/next-tick" },
            { text: "on", link: "/assembly/form/on" },
            { text: "radio-group", link: "/assembly/form/radio-group" },
            { text: "readonly", link: "/assembly/form/readonly" },
            { text: "remote", link: "/assembly/form/remote" },
            { text: "rules-plus", link: "/assembly/form/rules-plus" },
            { text: "rules", link: "/assembly/form/rules" },
            { text: "set-options", link: "/assembly/form/set-options" },
            { text: "slot-label", link: "/assembly/form/slot-label" },
            { text: "slot", link: "/assembly/form/slot" },
            { text: "update-form", link: "/assembly/form/update-form" },
            { text: "v-model", link: "/assembly/form/v-model" },
            { text: "value-format", link: "/assembly/form/value-format" },
          ],
        },

        {
          text: "表格table",
          items: [{ text: "表格", link: "/assembly/table/table" }],
        },
        {
          text: "进阶",
          items: [
            { text: "form自定义组件", link: "/assembly/advanced/customForm" },
            {
              text: "form自定义组件设置自定义校验规则",
              link: "/assembly/advanced/customFormRoules",
            },
          ],
        },
      ],
    },

例子

docs\guide\form.md文件

## 技术交流群 711368818



## 遗留问题 :待解决

select 为 multiple 多选时 必须初始化空数组(在 elementplus v-model 初始化 updateValue 时 为空数组会触发校验)

## Introduction

### WHAT

form-renderer 基于元素 element-plus,但不限于元素 element-plus 组件。在完全继承 element-plus 元素的 form 属性的基础上,进行了扩展。一些非表单组件或自定义组件,因此,用户可以使用一段 json 来呈现完整的表单。

### WHY

在我们的日常开发中,有很多有表单的页面,通常表单结构相似,逻辑重复。el 表单呈现器没有复杂的逻辑。它只转换 JSON 来呈现表单项,节省了编写业务逻辑的时间和精力,并减少了重复代码。

## Features

- 用 json 呈现表单
- 支持与自定义组件集成
- 支持 updateForm 方法批量更新表单数据
- 支持 setOptions 方法,动态更改选择选项
- 内容支持 inputFormat、outputFormat、trim 以处理组件的输入和输出值
- 支持 v-model

## Links

- [$attrs 和 $listeners (vue2&&vue3)](https://blog.csdn.net/qq_63358859/article/details/133699476?spm=1001.2014.3001.5501)
- [vue2 与 vue3 函数式组件](https://blog.csdn.net/qq_63358859/article/details/133635120?spm=1001.2014.3001.5501)
- [vue 2 与 vue3 获取模版引用 (ref)的区别](https://blog.csdn.net/qq_63358859/article/details/133532229?spm=1001.2014.3001.5501)
- [vue2 与 vue3 v-model 的区别](https://blog.csdn.net/qq_63358859/article/details/133484380?spm=1001.2014.3001.5501)
- [vue2 版本](https://blog.csdn.net/qq_63358859/article/details/130442636?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522169684271816800180612618%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=169684271816800180612618&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-7-130442636-null-null.nonecase&utm_term=render&spm=1018.2226.3001.4450)
- [中文文档](https://gitee.com/childe-jia/form-render/wikis/%E6%96%87%E6%A1%A3/%E4%BB%8B%E7%BB%8D)
- [element-plus table 的封装](https://gitee.com/childe-jia/table-vue3)

## Quick Start

```ts
pnpm i el-form-renderer-vue3
```

```ts
import elFormRenderer from "el-form-renderer-vue3";
app.use(elFormRenderer);
```

```ts




```

## Props

```ts
export default {
  // ...
  props: {
    /**
     * support all el-form's props
     * @see: https://element.eleme.io/#/zh-CN/component/form#form-attributes
     */

    /**
     * 表单项的配置数组,每个表单项代表一个原子表单项
     * the form config's array, each item represents a form-item
     */
    content: {
      type: Array, // type:Content[], check Content's definition below
      required: true
    },

    /**
     * disable all form-items
     */
    disabled: {
      type: Boolean,
      default: false
    }
  }
}

/**
 * 表单项的typescript定义
 * 支持所有el-form-item's props。表单项组件本身的props定义在el上
 * definition of form-item written in typescript.
 * support all el-form-item's props. The component's props need to be set at prop el
 */
interface Content {
  // 每一个原子都存在 id,用于存储该原子的值,不能重复
  // key of form-item value in form value. Must be unique
  id: string

  /**
   * 可以是element提供的所有表单组件类型,如传入'input',则渲染出'el-input'
   * 当type="group"时,可以创造复杂对象类型的表单数据,配合items使用。此时getFormValue()返回的是对象类型的数据,对象的每个属性对应items里的每一项
   * support all element's form component, e.g., type 'input' will render as 'el-input'.
   * you can create nested form value with type 'group' and use items to define that form value's shape. The type of this form value will be 'object'
   */
  type: string

  /**
   * 当type="group"时使用
   * items内依然遵循同一层级的id不重复的原则
   * using with type 'group'
   * the `id` in each item of items must be unique
   */
  items: Content[]

  /**
   * 默认值
   * FIXME: 别用关键字做 key
   */
  default?: any

  /**
   * 当 type === 'input' 时展示文本值
   * 当 type === 'select' 时展示对应 label
   * 对于其他组件等同于 disabled = true
   */
  readonly = false

  /**
   * @deprecated
   */
  enableWhen?: object | string

  /**
   * 传入一个方法,并返回 boolean,返回 true 时则隐藏该表单项
   * formValue 为当前 form 的值,item 为当前表单项的定义
   * hide the form-item when return true
   * formValue is same as what getFormValue returns, and item is the config of this form-item
   */
  hidden?: (formValue: Object, item: Content) => boolean

  /**
   * 具有选择功能的原子表单可用此定义可选项
   * use with type: select, radio-group, radio-button, checkbox-group, checkbox-button
   */
  options?: {label: string; value?: any}[]

  /**
   * 配置remote.url,即可远程配置组件的某个prop!
   * remote接受以下属性:
   * url: 远程接口的地址
   * prop: 要注入的 prop 的名称,默认为 options
   * request: 可选,请求方法
   * dataPath: 可选,data在响应体中的路径
   * onResponse: 可选,处理请求回来的数据
   * onError: 可选,处理请求出错的情况
   * 另外,针对 select、radio-group、checkbox-group,远程数据能自动映射成 el-option 选项!以下属性仅在此情况使用
   * label: 可选,可直接配置远程数据中用作 label 的key
   * value: 可选,可直接配置远程数据中用作 value 的key
   * @see https://zhuanlan.zhihu.com/p/97827063
   *
   * use remote to set one prop! remote accept following props:
   * url: remote api address
   * prop: prop name that data inject
   * request: optional, customize how to get your options
   * dataPath: optional, data's path in response
   * onResponse: optional, deal with your response
   * onError: optional, deal with request error
   * and, we treat select、radio-group、checkbox-group specially and the resp will be map as an el-option's group! following props only suitable for this case
   * label: optional, label key in resp
   * value: optional, value key in resp
   */
  remote?: {
    url: string
    request = () => this.$axios.get(url).then(resp => resp.data)
    prop = 'options'
    dataPath = ''
    onResponse = resp => {
      if (dataPath) resp = _get(resp, dataPath)
      switch (this.data.type) {
        case 'select':
        case 'checkbox-group':
        case 'radio-group':
          return resp.map(item => ({
            label: item[label],
            value: item[value]
          }))
        default:
          return resp
      }
    }
    onError = error => console.error(error.message)
    label = 'label'
    value = 'value'
  }

  attrs?: object // html attributes
  /**
   * 用于定义具体原子表单(如el-input)的属性,比如定义el-input的placeholder
   * use to define props of the actual component of this form-item, such as placeholder of el-input
   */
  el?: object

  /**
   * 使用自定义组件
   * component适用于渲染局部注册组件和自定义组件,而type适用于带el-前缀的全局组件
   * custom component
   * use it when element's form components are not enough
   */
  component?: Vue

  /**
   * 是否覆盖自定义组件内置的校验规则
   * `true` 为覆盖, 默认为 `false`
   * whether to override the validation rules written in custom components
   * `true` to override, default `false`
   */
  overrideRules: boolean

  label?: string //set el-form-item's label
  trim = true // trim value at change event

  // 用于处理输入值,输入的值包括:1. default;2. v-model;3. updateForm。参数为整个表单的值对象或 updateForm 传入的对象
  // 如果 inputFormat 返回 undefined,则不会更新此表单项
  // obj is param you passed to updateForm. You can use this function to hijack this process and customize the form value
  inputFormat?: (obj: any) => any

  // 用于处理输出值,参数为对应组件返回值
  // 如果处理后的值是对象类型,会覆盖(Object.assign)到整个表单的值上
  // used to hijack the getFormValue's process and customize the return value
  outputFormat?: (val: any) => any

  // set el-form-item's rules
  rules?: object

  // @deprecated
  atChange?: (id: string, value: any) => void

  /**
   * 监听表单项发出的事件
   * listen to any events emitted by component of form item
   * @param {any[]} args - what that event emits
   * @param {function} updateForm - same as methods.updateForm
   */
  on?: {
    [eventName: string]: (args: any[], updateForm: function) => void
  }
}

/**
 * a tour of typescript
 */
interface obj {
  a: string // type string
  b?: string // type string, optional
  c = true // type boolean, optional, default true
  d: string[] // type array, each item must be string
  e: any // could be any valid js type
  f: (a: number) => void // type function, which receives a param 'a' as number and return nothing
  h: Vue // instance of Vue
  i: {[a: string]: number} // type object, whose key is type string, and value is type number
}
```

## Methods

support all [el-form's methods](https://element.eleme.io/#/zh-CN/component/form#form-methods)

## Slots

| Slot     | Description                                 |
| -------- | ------------------------------------------- |
| default  | insert at bottom                            |
| id:hello | insert before form-item whose id is 'hello' |

## Inspiration

thanks to [el-form-renderer](https://github.com/femessage/el-form-renderer/)

基本使用

侧边栏菜单的最简单形式是传入一个链接数组。 第一级项目定义了侧边栏部分。 它应该包含text,即该部分的标题,以及 items ,即实际的导航链接。

export default {
  themeConfig: {
    sidebar: [
      {
        text: 'Section Title A',
        items: [
          { text: 'Item A', link: '/item-a' },
          { text: 'Item B', link: '/item-b' },
          ...
        ]
      },
      {
        text: 'Section Title B',
        items: [
          { text: 'Item C', link: '/item-c' },
          { text: 'Item D', link: '/item-d' },
          ...
        ]
      }
    ]
  }
}

每个 link 都应该指定以 / 开头的实际文件的路径。 如果在链接末尾添加斜杠,它将显示相应目录的index.md

export default {
  themeConfig: {
    sidebar: [
      {
        text: 'Guide',
        items: [
          // This shows `/guide/index.md` page.
          { text: 'Introduction', link: '/guide/' }
        ]
      }
    ]
  }
}

多个侧边栏

您可能会根据页面路径显示不同的侧边栏。 例如,如本网站所示,您可能希望在文档中创建单独的内容部分,例如“指南”页面和“配置”页面。

为此,首先将你的页面放到所在的目录中:

.
├─ guide/
│  ├─ index.md
│  ├─ one.md
│  └─ two.md
└─ config/
   ├─ index.md
   ├─ three.md
   └─ four.md

然后,更新配置以定义每个部分的侧边栏,不同的是,这次配置的是一个对象而不是数组。

export default {
  themeConfig: {
    sidebar: {
      // 当用户在 `指南` 目录页面下将会展示这个侧边栏
      '/guide/': [
        {
          text: 'Guide',
          items: [
            // This shows `/guide/index.md` page.
            { text: 'Index', link: '/guide/' }, // /guide/index.md
            { text: 'One', link: '/guide/one' }, // /guide/one.md
            { text: 'Two', link: '/guide/two' } // /guide/two.md
          ]
        }
      ],

      // 当用户在 `配置` 目录页面下将会展示这个侧边栏
      '/config/': [
        {
          text: 'Config',
          items: [
            // This shows `/config/index.md` page.
            { text: 'Index', link: '/config/' }, // /config/index.md
            { text: 'Three', link: '/config/three' }, // /config/three.md
            { text: 'Four', link: '/config/four' } // /config/four.md
          ]
        }
      ]
    }
  }
}

使用组件

vitepress中markdown文件中是可以直接使用vue组件的,我们先在theme/index全局引入element-plus

// .vitepress/theme/index.js

import DefaultTheme from "vitepress/theme";
import "element-plus/dist/index.css";
import elementplus from "element-plus";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
export default {
  ...DefaultTheme,
  enhanceApp: async ({ app, router, siteData }) => {
    // app is the Vue 3 app instance from `createApp()`. router is VitePress'
    // custom router. `siteData`` is a `ref`` of current site-level metadata.

    for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
      app.component(key, component);
    }
    app.use(elementplus);
  },
};

这里我们拿Button做一个演示,在button/index.md中我们可以直接这样使用Button组件

 
默认按钮


默认按钮

主要按钮

成功按钮

信息按钮

此时我们页面即可展示我们的Button按钮

viteePress搭建组件文档_第5张图片

在 markdown 中导入组件 

如果你的组件仅在少数地方使用,推荐的使用方法是在使用它的文件中导入组件。



# Docs

This is a .md using a custom component



## More docs

...

在 theme 中注册全局组件

如果要在文档中的多个页面中使用组件,则可以在主题中全局注册它们(或作为默认 VitePress 主题扩展的一部分)。查看 主题指南 了解更多信息。

在 .vitepress/theme/index.js 中,enhanceApp 函数接收 Vue app 实例,因此您可以在常规的 Vue 应用程序中 注册组件 。

import DefaultTheme from 'vitepress/theme'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('VueClickAwayExample', VueClickAwayExample)
  }
}

然后就可以在 markdown 文件里使用组件

# Vue Click Away


部署到Github Pages

网上搜了很多教程,包括官网的教程,但是还是费了一番功夫,
如果你使用自动化部署脚本部署不成功的话,可以参考我的这个笨方法
这是部署后的效果

前提

我假设你本地运行OK, 已经准备好要部署了

第一步

你的 vuepress 项目是否已经在github上的仓库下
如果是,请跳到第二步
如果不是,想在GitHub新建一个仓库,如图所示:

viteePress搭建组件文档_第6张图片

## 小坑
仓库名字要和config.js 里 的 base 属性值一样 

比如你的仓库名字叫jiayc4215
base就是/jiayc4215/

第二步 

执行  "docs:build": "vitepress build docs",

把打包好的文件拿出来创建一个新的文件夹初始化仓库


git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/jiayc4215/form-render.github.io.git
git push -u origin main

第三步

点击 Settings--》pages---》切换分支为main /root--》点击save

成功之后上边会有链接查看网页 

viteePress搭建组件文档_第7张图片

你可能感兴趣的:(vue.js,前端,javascript)