.ui文件 c语言,参考ElementUI的文档实现方案,实现自己组件库的说明文档

实现使用markdown编写的个人组件库说明文档

前一篇文章实现了按需加载封装个人的组件库功能,有了组件库,当然还要有配套说明文档,这样使者用起来才更方便。打包完成的dist目录是最终可放到服务器中,直接访问到文档的哟。

项目github地址:https://github.com/yuanalina/installAsRequired

在项目中配置打包examples

上篇文章中,执行打包命令会将项目打包至lib下,打包完成的目录结构是适合直接发布为npm包,使用时使用import等引入的。其中并没有html文件入口,所以要有说明文档,直接在浏览器中可访问,还需要重新配置打包。

打包examples相关目录结构及webpack配置

一、package.json增加打包命令"build_example": "node build/build.js examples"

bVbgJxf?w=1854&h=352

二、在src同级增加examples目录,存放文档相关文件

examples目录中:1、assets目录存放静态资源依赖,2、components存放vue组件,3、docs目录存放.md文件,说明文档,4、main.js会作为打包的入口,在这里引入项目的组件、第三方依赖:element-ui、路由配置等,5、route.js路由配置,6、index.html作为打包的html模版,7、App.vue

bVbgJAZ?w=608&h=816

三、webpack相关配置

在build目录中增加webpack.prod.examples.conf.js文件,配置打包example。这个文件是vue-cli生成项目中的webpack.prod.conf.js稍作修改,改动部分:

1、增加output出口配置,由于之前在config中将这个值设置成了../lib,这里把值设置为../dist,将examples打包后输出到dist

bVbgJr7?w=1658&h=350

2、设置打包入口为examples下的main.js

bVbgJso?w=1210&h=330

3、设置html模版为./examples/index.html

bVbgJtP?w=1218&h=386

另外在build/build.js中,需要判断example参数,更改一下output出口路径,如图:

bVbgJw1?w=1490&h=348

技术实现

编写说明文档,最直观的还是使用markdown编写,看了elementUI的实现方案,决定按elementUI的技术方案去实现。特别说明:本文中有部分实现是copy了elementUI的代码实现的。后面会特别指出

相关依赖安装

npm i highlight -D //安装语法高亮

npm i markdown-it markdown-it-anchor markdown-it-container -D // 安装markdown相关依赖

npm i vue-markdown-loader -D //安装vue-markdown-loader,解析.md文件为.vue文件

webpack相关配置

安装了vue-markdown-loader解析.md文件,在webpack.base.conf.js文件中,需要进行相关的loader配置,这里的配置相关,都是copy的element-ui中的代码。改动部分如下:

一、首先增加strip-tags文件到/build目录中,strip-tags内容如下:

/*!

* strip-tags

*

* Copyright (c) 2015 Jon Schlinkert, contributors.

* Licensed under the MIT license.

*/

'use strict';

var cheerio = require('cheerio');

exports.strip = function(str, tags) {

var $ = cheerio.load(str, {decodeEntities: false});

if (!tags || tags.length === 0) {

return str;

}

tags = !Array.isArray(tags) ? [tags] : tags;

var len = tags.length;

while (len--) {

$(tags[len]).remove();

}

return $.html();

};

exports.fetch = function(str, tag) {

var $ = cheerio.load(str, {decodeEntities: false});

if (!tag) return str;

return $(tag).html();

};

二、webpack.base.conf.js的改动

1、增加引入strip-tags和markdown-it

const striptags = require('./strip-tags')

const md = require('markdown-it')()

2、增加工具函数

const wrap = function(render) {

return function() {

return render.apply(this, arguments)

.replace('

.replace('', '')

}

}

function convert(str) {

str = str.replace(/()(\w{4});/gi, function($0) {

return String.fromCharCode(parseInt(encodeURIComponent($0).replace(/(%26%23x)(\w{4})(%3B)/g, '$2'), 16))

})

return str

}

3、增加.md相关loader配置,将.md文件解析为.vue文件,同时,解析处理::: demo :::代码块等,解析处理::: demo :::代码块为demo-block vue组件,并传入对应参数.

{

test: /\.md$/,

loader: 'vue-markdown-loader',

options: {

use: [

[require('markdown-it-container'), 'demo', {

validate: function(params) {

return params.trim().match(/^demo\s*(.*)$/)

},

render: function(tokens, idx) {

var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)

if (tokens[idx].nesting === 1) {

var description = (m && m.length > 1) ? m[1] : ''

var content = tokens[idx + 1].content

var html = convert(striptags.strip(content, ['script', 'style'])).replace(/(]*)=""(?=.*>)/g, '$1')

var script = striptags.fetch(content, 'script')

var style = striptags.fetch(content, 'style')

var jsfiddle = { html: html, script: script, style: style }

var descriptionHTML = description

? md.render(description)

: ''

jsfiddle = md.utils.escapeHtml(JSON.stringify(jsfiddle))

return `

${html}

${descriptionHTML}

`

}

return '

\n'

}

}],

[require('markdown-it-container'), 'tip'],

[require('markdown-it-container'), 'warning']

],

preprocess: function(MarkdownIt, source) {

MarkdownIt.renderer.rules.table_open = function() {

return '

};

MarkdownIt.renderer.rules.fence = wrap(MarkdownIt.renderer.rules.fence)

return source;

}

}

}

文档编写部分

配置相关的就告一段落了,接下来进入examples中的文档编写部分

一、main.js入口文件编写

在入口文件中,引入相关依赖,项目样式入口、路由、组件以及element-ui

import Vue from 'vue'

import App from './App.vue'

import VueRouter from 'vue-router'

// 引入组件

import JY from '../src'

Vue.use(JY)

// 引入element-ui

import ElementUI from 'element-ui'

import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI)

// 引入demo-block

import DemoBlock from './components/demoBlock'

Vue.component('demo-block', DemoBlock)

// 引入项目样式入口

import './assets/less/index.less'

// 引入路由

import routes from './route'

Vue.use(VueRouter)

const router = new VueRouter({

routes

})

/* eslint-disable no-new */

new Vue({

render(createElement) {

return createElement(App)

},

router

}).$mount('#app')

二、设置路由配置route.js

路由配置时,将路由路径对应的组件设置为引入的.md文件

import Install from './docs/install.md'

import QuikeStart from './docs/quikeStart.md'

import Input from './docs/input.md'

const routes = [

{

path: '/',

component: Install,

name: 'default'

},

{

path: '/guide/install',

name: 'Install',

component: Install

},

{

path: '/guide/quikeStart',

name: 'quikeStart',

component: QuikeStart

},

{

path: '/input',

name: 'input',

component: Input

}

]

export default routes

三、App.vue、以及相关布局组件

1、App.vue

/* 引入代码高亮样式 */

@import 'highlight.js/styles/color-brewer.css';

import HeaderModel from './components/header'

import MenuModel from './components/menu'

export default {

components: {

HeaderModel,

MenuModel

},

data() {

return {

}

},

methods: {

}

}

2、header.vue

通用组件库

export default {

data () {

return {

}

}

}

3、menu.vue

export default {

data () {

return {

defaultActive: '/guide/install'

}

},

created () {

const path = this.$route.fullPath

this.defaultActive = path == '/' ? '/guide/install' : path

},

methods: {

}

}

四、重要组件demoBlock.vue

demoBlock组件是解析.md中的::: demo ::: 代码块需要用到的组件,这里的demoBlock.vue文件是copy的element-ui的代码后稍作修改

class="demo-block"

:class="[blockClass, { 'hover': hovering }]"

@mouseenter="hovering = true"

@mouseleave="hovering = false">

class="demo-block-control"

ref="control"

@click="isExpanded = !isExpanded">

{{ controlText }}

.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;

}

}

}

export default {

data() {

return {

hovering: false,

isExpanded: false,

fixedControl: false,

scrollParent: null,

langConfig: {

"hide-text": "隐藏代码",

"show-text": "显示代码",

"button-text": "在线运行",

"tooltip-text": "前往 jsfiddle.net 运行此示例"

}

};

},

props: {

jsfiddle: Object,

default() {

return {};

}

},

methods: {

scrollHandler() {

const { top, bottom, left } = this.$refs.meta.getBoundingClientRect();

this.fixedControl = bottom > document.documentElement.clientHeight &&

top + 44 <= document.documentElement.clientHeight;

},

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('.page-component__scroll > .el-scrollbar__wrap');

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();

}

};

五、docs中的.md文档文件

.md文件编写时有几个需要注意的地方:

具有交互功能的说明文档,需要有标签,在标签元素中定义需要导出的vue实例。

在:::demo ::: 代码块中定义的模版会作为导出的vue实例的模版,但是在代码块中的中的内容仅作为展示。

bVbgJDp?w=1388&h=1444

.md文件粘贴进来会展示有误,这里只进行了截图,有需要的伙伴可以进入github查看

六、样式调整

样式相关的调整代码这里就不单独列出来说明了,需要的伙伴可以进入github查看

开发中的调试

设置webpack.dev.conf.js文件的入口为./examples/main.js,这样即可以边开发组件边调试,同时也可以调试到说明文档。

entry: {

app: './examples/main.js'

},

本文结束啦~希望对你有所帮助。。学无止境,与诸君共勉~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值