初始化項目
使用vue-cli3初始化項目蹦浦,初始化目錄如下:
將src修改為packages,用于放置組件源文件。新建example目錄用于放組件案例吵护,獲得最新目錄:
配置vue.config.js
修改目錄后需要修改打包文件中對應(yīng)的文件名,在vue-cli3中需要新增vue.config.js
來擴展打包配置表鳍,參考文檔: https://cli.vuejs.org/zh/config/
配置如下:
module.exports = {
outputDir: 'dist', // 輸出目錄(打包后的文件夾)
publicPath: './',
pages: {
index: {
entry: 'example/main.js', // 入口文件(開發(fā)和生產(chǎn)中案例的入口文件)
template: 'public/index.html',
filename: 'index.html'
}
}
}
按照以上配置執(zhí)行
npm run build
后會直接生成dist目錄馅而,且將example中的案例打包,不是組件文件的打包
配置package.json
修改package.json
文件:
在script
中新增lib
命令"lib": "vue-cli-service build --target lib --name base-main --dest lib packages/index.js"
--target: app | lib | wc | wc-async (默認值:app)
--name: 打包后的組件名稱
--dest: 指定輸出目錄 (默認值:dist)
packages/index.js: 入口js文件
參考文檔:https://cli.vuejs.org/zh/guide/cli-service.html#vue-cli-service-build
運行npm run lib
譬圣,生成lib文件夾和組件文件base-main.umd.min.js
上傳組件文件到npm
- 配置 package.json 文件中發(fā)布到 npm 的字段
name: 包名瓮恭,該名字是唯一的±迨欤可在 npm 官網(wǎng)搜索名字屯蹦,如果存在則需換個名字。
version: 版本號绳姨,每次發(fā)布至 npm 需要修改版本號登澜,不能和歷史版本號相同。
description: 描述就缆。
main: 入口文件帖渠,該字段需指向我們最終編譯后的組件包文件(上面的lib文件夾中的lib/base-main.umd.min.js)。
keyword:關(guān)鍵字竭宰,以空格分離希望用戶最終搜索的詞空郊。
author:作者
private:是否私有份招,需要修改為 false 才能發(fā)布到 npm
license: 開源協(xié)議(可以填自己的github地址) - 添加 .npmignore 文件,設(shè)置忽略發(fā)布文件
發(fā)布到 npm 中狞甚,只有編譯后的 lib 目錄锁摔、package.json、README.md才是需要被發(fā)布的哼审。所以我們需要設(shè)置忽略目錄和文件谐腰。和 .gitignore 的語法一樣,具體需要提交什么文件涩盾,看各自的實際情況十气。 - 登錄npm
npm login
如果配置了淘寶鏡像,先設(shè)置回npm鏡像:
npm config set registry http://registry.npmjs.org/
發(fā)布到npm
npm publish-
更新npm版本包
使用npm version <update_type>
春霍,對npm版本進行更新砸西,版本號的三位分別是大號·中號·小號·預(yù)發(fā)布號
。
update_type可以為以下值:- prerelease:有預(yù)發(fā)布號的址儒,版本號+1芹枷;無預(yù)發(fā)布號的,小號+1且預(yù)發(fā)布號初始為0
運行:npm version prerelease
package.json 中的版本號1.0.0變?yōu)?1.0.1-0
再運行
package.json 中的版本號1.0.1-0變?yōu)?1.0.1-1
- prepatch:小號+1莲趣;預(yù)發(fā)布號初始為0
運行:npm version prepatch
1. package.json 中的版本號1.0.0變?yōu)?1.0.1-0
2. package.json 中的版本號1.0.1-1變?yōu)?1.0.2-0
- preminor:中號+1鸳慈;小號和預(yù)發(fā)布號初始為0
運行:npm version preminor
1. package.json 中的版本號1.0.2-0變?yōu)?1.1.0-0
2. package.json 中的版本號1.0.1-1變?yōu)?1.1.0-0
- premajor:大號+1;中號喧伞,小號和預(yù)發(fā)布號初始為0
運行:npm version premajor
1. package.json 中的版本號1.1.0-0變?yōu)?2.0.0-0
- patch:有預(yù)發(fā)布號的去掉預(yù)發(fā)布號走芋,其他不變;無預(yù)發(fā)布號的小號+1
運行:npm version patch
1. package.json 中的版本號1.1.0-0變?yōu)?1.1.0
2. package.json 中的版本號1.1.0變?yōu)?1.1.1
- minor:有預(yù)發(fā)布號的絮识,小號為0時去掉預(yù)發(fā)布號绿聘,其他不變嗽上,小號不為0時中號+1且其他置為0去掉預(yù)發(fā)布號次舌;無預(yù)發(fā)布號的中號+1,小號置為0
運行:npm version minor
1. package.json 中的版本號1.1.0變?yōu)?1.2.0
2. package.json 中的版本號1.1.0-0變?yōu)?1.1.0
3. package.json 中的版本號1.1.1-0變?yōu)?1.2.0
- major: 無預(yù)發(fā)布號的兽愤,大號+1其他置為0彼念;有預(yù)發(fā)布號的,中號和小號為0時去除預(yù)發(fā)布號浅萧,其他不變逐沙。如果中號和小號中有一個不為0的話,大號+1洼畅,其他重置為0吩案,去除預(yù)發(fā)布號
運行:npm version major
1. package.json 中的版本號1.1.0變?yōu)?2.0.0
2. package.json 中的版本號1.0.0-0變?yōu)?1.0.0
3. package.json 中的版本號1.1.1-0變?yōu)?2.0.0
UI文檔的編寫
這一塊參考的element-ui
做法,需要新增外部包:
highlight.js // 用于代碼的高亮
transliteration // 用于中文拼音轉(zhuǎn)換
markdown-it
markdown-it-anchor
markdown-it-container
vue-markdown-loader
新增demo-block.vue文件
用于展示案例效果和代碼帝簇,參考element-ui
的demo-block.vue文件做了修改徘郭,去除了其他語言靠益,如下:
<template>
<div
class="demo-block"
:class="[blockClass, { 'hover': hovering }]"
@mouseenter="hovering = true"
@mouseleave="hovering = false">
<div class="source">
<slot name="source"></slot>
</div>
<div class="meta" ref="meta">
<div class="description" v-if="$slots.default">
<slot></slot>
</div>
<div class="highlight">
<slot name="highlight"></slot>
</div>
</div>
<div
class="demo-block-control"
ref="control"
:class="{ 'is-fixed': fixedControl }"
@click="isExpanded = !isExpanded">
<transition name="arrow-slide">
<i :class="[iconClass, { 'hovering': hovering }]"></i>
</transition>
<transition name="text-slide">
<span v-show="hovering">{{ controlText }}</span>
</transition>
</div>
</div>
</template>
<style lang="scss">
.demo-block {
border: solid 1px #ebebeb;
border-radius: 3px;
transition: .2s;
&.hover {
box-shadow: 0 0 8px 0 rgba(232, 237, 250, .6), 0 2px 4px 0 rgba(232, 237, 250, .5);
}
code {
font-family: Menlo, Monaco, Consolas, Courier, monospace;
}
.demo-button {
float: right;
}
.source {
padding: 24px;
}
.meta {
background-color: #fafafa;
border-top: solid 1px #eaeefb;
overflow: hidden;
height: 0;
transition: height .2s;
}
.description {
padding: 20px;
box-sizing: border-box;
border: solid 1px #ebebeb;
border-radius: 3px;
font-size: 14px;
line-height: 22px;
color: #666;
word-break: break-word;
margin: 10px;
background-color: #fff;
p {
margin: 0;
line-height: 26px;
}
code {
color: #5e6d82;
background-color: #e6effb;
margin: 0 4px;
display: inline-block;
padding: 1px 5px;
font-size: 12px;
border-radius: 3px;
height: 18px;
line-height: 18px;
}
}
.highlight {
pre {
margin: 0;
}
code.hljs {
margin: 0;
border: none;
max-height: none;
border-radius: 0;
&::before {
content: none;
}
}
}
.demo-block-control {
border-top: solid 1px #eaeefb;
height: 44px;
box-sizing: border-box;
background-color: #fff;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
text-align: center;
margin-top: -1px;
color: #d3dce6;
cursor: pointer;
position: relative;
&.is-fixed {
position: fixed;
bottom: 0;
width: 868px;
}
i {
font-size: 16px;
line-height: 44px;
transition: .3s;
&.hovering {
transform: translateX(-40px);
}
}
> span {
position: absolute;
transform: translateX(-30px);
font-size: 14px;
line-height: 44px;
transition: .3s;
display: inline-block;
}
&:hover {
color: #409EFF;
background-color: #f9fafc;
}
& .text-slide-enter,
& .text-slide-leave-active {
opacity: 0;
transform: translateX(10px);
}
.control-button {
line-height: 26px;
position: absolute;
top: 0;
right: 0;
font-size: 14px;
padding-left: 5px;
padding-right: 25px;
}
}
}
</style>
<script type="text/babel">
export default {
data() {
return {
hovering: false,
isExpanded: false,
fixedControl: false,
scrollParent: null,
langConfig: {
"hide-text": "隱藏代碼",
"show-text": "顯示代碼"
}
};
},
props: {
jsfiddle: Object,
default() {
return {};
}
},
methods: {
scrollHandler() {
const { top, bottom, left, width } = this.$refs.meta.getBoundingClientRect();
this.fixedControl = bottom > document.documentElement.clientHeight &&
top + 44 <= document.documentElement.clientHeight;
this.$refs.control.style.left = this.fixedControl ? `${ left }px` : '0';
this.$refs.control.style.width = this.fixedControl ? `${ width }px` : 'auto';
},
removeScrollHandler() {
this.scrollParent && this.scrollParent.removeEventListener('scroll', this.scrollHandler);
}
},
computed: {
lang() {
return this.$route.path.split('/')[1];
},
blockClass() {
return `demo-${ this.lang } demo-${ this.$router.currentRoute.path.split('/').pop() }`;
},
iconClass() {
return this.isExpanded ? 'el-icon-caret-top' : 'el-icon-caret-bottom';
},
controlText() {
return this.isExpanded ? this.langConfig['hide-text'] : this.langConfig['show-text'];
},
codeArea() {
return this.$el.getElementsByClassName('meta')[0];
},
codeAreaHeight() {
if (this.$el.getElementsByClassName('description').length > 0) {
return this.$el.getElementsByClassName('description')[0].clientHeight +
this.$el.getElementsByClassName('highlight')[0].clientHeight + 20;
}
return this.$el.getElementsByClassName('highlight')[0].clientHeight;
}
},
watch: {
isExpanded(val) {
this.codeArea.style.height = val ? `${ this.codeAreaHeight + 1 }px` : '0';
if (!val) {
this.fixedControl = false;
this.$refs.control.style.left = '0';
this.removeScrollHandler();
return;
}
setTimeout(() => {
this.scrollParent = document.querySelector('#ex-r-area');
this.scrollParent && this.scrollParent.addEventListener('scroll', this.scrollHandler);
this.scrollHandler();
}, 200);
}
},
mounted() {
this.$nextTick(() => {
let highlight = this.$el.getElementsByClassName('highlight')[0];
if (this.$el.getElementsByClassName('description').length === 0) {
highlight.style.width = '100%';
highlight.borderRight = 'none';
}
});
},
beforeDestroy() {
this.removeScrollHandler();
}
};
</script>
配置vue.config.js
修改vue.config.js文件,新增chainWebpack屬性残揉,用于文檔文件的轉(zhuǎn)換胧后。如下:
chainWebpack: config => {
// 設(shè)置文件夾別名
config.resolve.alias
.set('@', resolve('example'))
.set('~', resolve('packages'))
config.module
.rule('js')
.include
.add(__dirname + 'packages')
.end()
.use('babel')
.loader('babel-loader')
.tap(options => {
// 修改它的選項...
return options
})
config.module
.rule('md')
.test(/\.md/)
.use('vue-loader')
.loader('vue-loader')
.end()
.use('vue-markdown-loader')
.loader('vue-markdown-loader/lib/markdown-compiler')
.options({
raw: true,
preventExtract: true, //這個加載器將自動從html令牌內(nèi)容中提取腳本和樣式標簽
// 定義處理規(guī)則
preprocess: (MarkdownIt, source) => {
// 對于markdown中的table,
MarkdownIt.renderer.rules.table_open = function() {
return '<table class="doctable">';
};
// 對于代碼塊去除v - pre, 添加高亮樣式;
const defaultRender = md.renderer.rules.fence;
MarkdownIt.renderer.rules.fence = (
tokens,
idx,
options,
env,
self
) => {
const token = tokens[idx];
// 判斷該 fence 是否在 :::demo 內(nèi)
const prevToken = tokens[idx - 1];
const isInDemoContainer =
prevToken &&
prevToken.nesting === 1 &&
prevToken.info.trim().match(/^demo\s*(.*)$/);
if (token.info === "html" && isInDemoContainer) {
return `<template slot="highlight"><pre v-pre><code class="html">${md.utils.escapeHtml(
token.content
)}</code></pre></template>`;
}
return defaultRender(tokens, idx, options, env, self);
};
return source;
},
use: [
// 標題錨點
[
require("markdown-it-anchor"),
{
level: 2, // 添加超鏈接錨點的最小標題級別, 如: #標題 不會添加錨點
slugify: slugify, // 自定義slugify, 我們使用的是將中文轉(zhuǎn)為漢語拼音,最終生成為標題id屬性
permalink: true, // 開啟標題錨點功能
permalinkBefore: true // 在標題前創(chuàng)建錨點
}
],
// :::demo ****
//
// :::
//匹配:::后面的內(nèi)容 nesting == 1,說明:::demo 后面有內(nèi)容
//m為數(shù)組,m[1]表示 ****
[
require("markdown-it-container"),
"demo",
{
validate: function(params) {
return params.trim().match(/^demo\s*(.*)$/);
},
render: function(tokens, idx) {
const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/);
if (tokens[idx].nesting === 1) {
//
const description = m && m.length > 1 ? m[1] : ""; // 獲取正則捕獲組中的描述內(nèi)容,即::: demo xxx中的xxx
const content =
tokens[idx + 1].type === "fence"
? tokens[idx + 1].content
: "";
return `<demo-block>
<div slot="source">${content}</div>
${description ? `<div>${md.render(description)}</div>` : ""}
`;
}
return "</demo-block>";
}
}
],
[require("markdown-it-container"), "tip"],
[require("markdown-it-container"), "warning"]
]
});
}
設(shè)置文檔文件
在example中新增doc文件夾用于存放md文件,在md文件中使用markdown語法書寫文檔抱环。其中以:::demo
開始對組件進行使用的講解壳快,在demo后面可以填寫組件的中相關(guān)的屬性和方法的使用,在```html 代碼塊 ```
的代碼塊中填寫組件案例的使用代碼镇草,和函數(shù)方法眶痰。案例:
:::demo 使用`type`、`plain`梯啤、`round`和`circle`屬性來定義 Button 的樣式凛驮。
```html
<div class="mb-20">
<el-button>默認按鈕</el-button>
<el-button type="primary">主要按鈕</el-button>
<el-button type="success">成功按鈕</el-button>
<el-button type="info">信息按鈕</el-button>
<el-button type="warning">警告按鈕</el-button>
<el-button type="danger">危險按鈕</el-button>
</div>
<script lang="babel">
export default{
}
</script>
``` // html的結(jié)尾符
:::
修改example中的路由文件,設(shè)置對應(yīng)案例的對應(yīng)的路由条辟,如下:
new Router({
routes: [
{
path: '/ElButton',
name: 'ElButton',
text: 'button按鈕',
component: () => import(`@/doc/ElButton.md`)
}
]
})
預(yù)覽地址:https://erpang123.github.io/C-UI/CUI/index.html
參考的相關(guān)文章:https://blog.csdn.net/qq_31126175/article/details/100527322
https://segmentfault.com/a/1190000021140844