造個自己的Vue的UI組件庫類似Element


前言

隨着前端的三大框架的出現,組件化的思想越來越流行,出現許多組件庫.它能夠幫助開發者節省時間提高效率,
如React的Ant-design,Vue的iView,Element等,它們的功能已經很完善了.
我寫這遍文章的目的:記錄自己搭建UI庫的過程(對Vue的理解加深了好多)演示地址
首先講一下思路:
平常寫組件時,寫一個組件要用時直接導入就行了,如你寫了一個time.vue,用的時候

import time from '路徑'

現在要寫一個組件庫,是不是把所有組件一個文件夾里(如button.vue,icon.vue,input.vue...),通過Vue.components注冊所有組件,再通過Vue.use()安裝一下就實現了,這就是所以的vue插件的思路,沒有那么神秘

1.環境准備

前面說要把所有的組件放在一個文件夾里,最簡單就是用腳手架搭一個項目目錄結構,
同時還需要添加示例文檔----方便調試和展示:
按鈕的示例效果
圖片描述

現在要考慮比較重要的兩點:目錄結構示例文檔
1.目錄結構
直接用vue-cli建立項目結構, 在基礎上修改一下就行了(以滿足我們示例的展示)
目錄結構

.
├── build  -------------------------webpack相關配置文件
│   ├── build.js
│   ├── check-versions.js
│   ├── logo.png
│   ├── strip-tags.js
│   ├── utils.js
│   ├── vue-loader.conf.js
│   ├── webpack.base.conf.js -------配置markdown設置時會用到它
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config  ------------------------vue的基本配置
│   ├── dev.env.js
│   ├── index.js
│   └── prod.env.js
├── examples -----------------------放置例子
│   ├── App.vue --------------------根文件
│   ├── assets ---------------------靜態資源
│   │   ├── css --------------------css
│   │   ├── img --------------------圖片
│   │   └── logo.png ---------------vue的logo
│   ├── components -----------------公共組件
│   │   ├── demo-block.vue ---------盒子組件
│   │   ├── footer.vue -------------footer組件
│   │   ├── header.vue -------------header組件
│   │   └── side-nav.vue -----------側邊欄組件
│   ├── docs -----------------------例子模塊的文檔
│   │   ├── breadcrumb.md ----------面包屑組件文檔
│   │   ├── button.md --------------按鈕組件文檔
│   │   ├── card.md ----------------卡片組件文檔
│   │   ├── guide.md ---------------簡介文檔
│   │   ├── icon.md ----------------圖標文檔
│   │   ├── install.md -------------安裝文檔
│   │   ├── layout.md --------------布局文檔
│   │   ├── logs.md ----------------更新日志文檔
│   │   ├── message.md -------------消息文檔
│   │   ├── start.md ---------------快速開始1文檔 │ │ ├── tag.md -----------------標簽文檔 │ │ └── twotable.md ------------二維表格文檔 │ ├── icon.json ------------------圖標數據 │ ├── main.js --------------------入口文件 │ ├── nav.config.json ------------側邊欄數據 │ └── router ---------------------路由 │ └── index.js ---------------路由配置 ├── packages -----------------------組件庫源代碼 │ ├── README.md ------------------README │ ├── breadcrumb -----------------面包屑源碼 │ │ ├── index.js │ │ └── src │ ├── breadcrumb-item ------------面包屑源碼 │ │ └── index.js │ ├── button ---------------------按鈕源碼 │ │ ├── index.js │ │ └── src │ ├── card -----------------------卡片源碼 │ │ ├── index.js │ │ └── src │ ├── col ------------------------列布局源碼 │ │ ├── index.js │ │ └── src │ ├── message --------------------消息源碼 │ │ ├── index.js │ │ └── src │ ├── two-dimensional-table -----二維表格源碼 │ │ ├── index.js │ │ └── src │ ├── row -----------------------行源碼 │ │ ├── index.js │ │ └── src │ ├── tag -----------------------標簽源碼 │ │ ├── index.js │ │ └── src │ ├── theme-default --------------樣式表 │ │ └── lib │ ├── package.json │ └── index.js -------------------組件庫入口 ├── index.html ---------------------主頁 ├── package.json ├── static └── README.md

以上是已經修改過的目錄結構,將腳手架生成的src目錄改為examples用來放示例文檔,所以相應的你要修改build目錄下的webpack.base.conf.js ,讓它指向examples,webpack才能正確進行打包
圖片描述
示例文檔,編寫文檔使用markdown最適合了,要讓vue能夠實現markdown文檔可以用vue-markdown-loader,配置相關文件在webpack.base.conf.js 的rules里添加
圖片描述
就可以開始寫文檔,測試一下

{
  path: '/hello', name: 'hello', component: r => require.ensure([], () => r(require('../docs/hello.md'))) }

npm run dev 跑項目打開http://localhost:8080/#/hello, 可以顯示,初步成功(基本實現)
接下來就要實現示例文檔的效果: 既能演示又有代碼展示(如下圖)
圖片描述

如上圖的示例文檔是button.md, 要讓它在button.md一個文件里想顯示代碼的地方顯示代碼,想顯示按鈕的地方顯示按鈕,所以就要在顯示按鈕的地方打上一個標識符,

讓編譯過程中能夠識別,安裝.vue的方式編譯展示還是要用到markdown的配置,它其實封裝了markdown-it,支持options選項,只要加上定義的標識符(我用的是'demo'),options 選項的配置(也在webpack.base.conf.js 里)

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) const code_inline = MarkdownIt.renderer.rules.code_inline MarkdownIt.renderer.rules.code_inline = function (...args) { args[0][args[1]].attrJoin('class', 'code_inline') return code_inline(...args) } 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'; } }] ] }

其實這就是把要當解析器遇到帶demo的標識符時就會添加我們准備好的demo-block組件,按照以上規則解析成AST(抽象語法樹),再把它編譯成html
所以寫示例文檔時,可以這樣寫
圖片描述

2.如何編寫組件源碼

其實沒有想象中那么難,就像平常寫組件那樣,只不過要按照一定結構編寫(具體的可以去看我的github),一般的UI組件庫都支持全局引入和單個組件引入,
全局引入:

const install = function(Vue) { if(install.installed) return components.map(component => Vue.component(component.name, component)) }

遍歷你寫的組件,通過Vue.component注冊到Vue上,構成一個install函數,暴露install,當你的別的項目要用時只要安裝一下包,用Vue.use()使用(像別的插件一樣)
單個文件引入:

export default { install, JButton, JCol, JRow, JTag, JBreadcrumb, JBreadcrumbItem, JCard, towTable }

類似的只要暴露出組件就OK了

別人要能夠通過npm安裝包用我們的包,我們是不是要在包里寫所以組件和樣式,別人只要npm安裝包和引入一個全部組件的樣式兩步驟就可以使用了

3. npm發布你的UI框架

  1. 你要擁有一個npm賬號(沒有的直接去官網注冊一個)
  2. 打開終端登錄npm
npm login

3.發布包
我們只有發布packages這個文件夾就行,寫好packages文件夾下個的package.json

{
  "name": "jk-ui", "version": "1.0.9", "description": "UI base on Vue", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", "url": "git+ssh://git@github.com/liuyangjike/JKUI.git" }, "keywords": [ "UI" ], "author": "Jike", "license": "ISC", "bugs": { "url": "https://github.com/liuyangjike/JKUI/issues" }, "homepage": "https://github.com/liuyangjike/JKUI#readme" }

使用npm publish發布就OK了,別人就可以用npm install jk-ui --save愉快的玩耍了
具體的可以去看源碼,在github上,覺得可以的話幫忙star一下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM