項目搭建
項目搭建參考 從零開始搭建 Vue 組件庫 VV-UI
記錄模仿 VV-UI 組件庫造輪子中遇到的問題,以及解決方案
新建項目
對於腳手架環境的問題,目前已經有非常成熟的 vue 官方的腳手架,我們拿來用就好了
npm install vue-cli -g
vue init webpack origin-ui
cd origin-ui
npm install
npm run dev
項目可以正常啓動,在此基礎上進行改造
更改目錄
|-- examples // 原 src 目錄,改成 examples 用作示例展示
|-- assets // api文檔logo 樣式文件
|-- docs // api文檔
|-- router // api文檔路由
|-- packages // 新增 packages 用於編寫存放組件
|-- button // 組件
|-- theme-default // 組件樣式 gulp 運行目錄
|-- lib // 編譯後css
|-- src // 編譯前css
|-- gulpfile.js // gulp 寫打包css的task
|-- salad.config.json // BEM的配置文件
|-- index.js // 導出組件
原 src 目錄,改成 examples 用作示例展示,需要對應修改 webpack 配置
把原先的編譯指向 src 的目錄改成 examples
{
test: /\.(js|vue)$/,
loader: 'eslint-loader',
include: [resolve('examples'), resolve('test'), resolve('packages')],// 修改
}
entry: {
app: './examples/main.js' // 程序入口修改
},
resolve: {
alias: {
vue$: 'vue/dist/vue.esm.js',
'@': resolve('examples') // 根據實際情況修改
}
},
如何編寫文檔
使用vue-markdown-loader在 vue 下可以去寫 markdown 文檔
安裝
# For Vue2
npm i vue-markdown-loader -D
npm i vue-loader vue-template-compiler -D
使用
webpack.config.js file:
module.exports = {
module: {
rules: [
{
test: /\.md$/,
loader: 'vue-markdown-loader'
}
]
}
}
在 example/docs 目錄下新建 test.md
同時創建一個新的路由,指向我們的 md 文件:
{
path: '/test',
name: 'test',
component: r => require.ensure([], () => r(requi('../docs/test.md')))
}
打開瀏覽器訪問http://localhost:8080/#/test
實現 demo/代碼演示
- 需求 1 就是攔截 import,並且解析 markdowm 語法
- 需求 2 在析 markdown 中也可以寫 Vue 的組件
全部配置可參考Vue 加載 Markdown 格式組件有詳細註釋
markdown-it,支持 options 選項。這樣我們就可以爲我們的 markdown 定義獨特的標識符,這裏我用 demo 標識需要顯示代碼塊的地方,所以我需要配置 options 選項 :
const vueMarkdown = {
preprocess: (MarkdownIt, source) => {
MarkdownIt.renderer.rules.table_open = function() {
return '<table class="table">'
}
MarkdownIt.renderer.rules.fence = utils.wrapCustomClass(
MarkdownIt.renderer.rules.fence
)
return source
},
use: [
[
MarkdownItContainer,
'demo',
{
// 用於校驗包含demo的代碼塊
validate: params => params.trim().match(/^demo\s*(.*)$/),
render: function(tokens, idx) {
var m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)
if (tokens[idx].nesting === 1) {
var desc = tokens[idx + 2].content
// 編譯成html
const html = utils.convertHtml(
striptags(tokens[idx + 1].content, 'script')
)
// 移除描述,防止被添加到代碼塊
tokens[idx + 2].children = []
return `<demo-block>
<div slot="desc">${html}</div>
<div slot="highlight">`
}
return '</div></demo-block>\n'
}
}
]
]
}
這裏簡單的描述一下這段代碼是幹什麼的:首先把內容裏面 vue 片段編譯成 html,用於顯示,另一方面用 highlight 來高亮代碼塊。demo-block 本身是我們定義好的組件:
<template>
<div class="docs-demo-wrapper">
<div :style="{maxHeight: isExpand ? '700px' : '0'}" class="demo-container">
<div span="14">
<div class="docs-demo docs-demo--expand">
<div class="highlight-wrapper">
<slot name="highlight"></slot>
</div>
</div>
</div>
</div>
<span class="docs-trans docs-demo__triangle" @click="toggle"
>{{isExpand ? '隱藏代碼' : '顯示代碼'}}</span
>
</div>
</template>
基本用法:
::: demo
<o-button>默認按鈕</o-button>
:::
如何編寫組件
環境準備完畢,緊接着要開始編寫組件,考慮的是組件庫,所以我們竟可能讓我們的組件支持全局引入和按需引入,如果全局引入,那麼所有的組件需要要註冊到 Vue component 上,並導出:
const install = function(Vue) {
if (install.installed) return
components.map(component => Vue.component(component.name, component))
}
export default {
install
}
着要實現按需加載,我們只需要單個導出組件即可:
import Button from './button/index.js'
import Row from './row/index'
import Col from './col/index'
const components = [Button, Row, Col]
const install = function(Vue) {
if (install.installed) return
components.map(component => Vue.component(component.name, component))
}
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export { install, Button, Row, Col }
既然是單頁面應用,必然要去解決樣式衝突問題,如果組件內使用 soped,那麼樣式就無法從組件內抽離出來,達不到可定製化主題顏色的目的。我們需要一套可以分離處理的樣式,可以自行編譯,可以相互不污染。這時候 css 的 BEM 規範就顯得尤爲重要。如果你還不知道什麼是 BEM 參考: http://www.w3cplus.com/css/cs...。
說到這裏,目前對 BEM 規範支持較好的插件就是 postcss 了,他允許我們配置 BEM 之間的連接符和縮寫:
{
"browsers": ["ie > 8", "last 2 versions"],
"features": {
"bem": {
"shortcuts": {
"component": "b",
"modifier": "m",
"descendent": "e"
},
"separators": {
"descendent": "__",
"modifier": "--"
}
}
}
}
這樣我們就可以把樣式單獨的抽離出來,通過 gulp 進行打包編譯:
gulp.task('compile', function() {
return gulp
.src('./src/*.css')
.pipe(postcss([salad]))
.pipe(cssmin())
.pipe(gulp.dest('./lib'))
})
關於 gulp 的使用
npm install --global gulp
npm install --save-dev gulp
進入 packages/theme-default 中,運行 gulp
gulp