亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

少女風vue組件庫的制作全過程

2019-11-19 11:34:08
字體:
來源:轉載
供稿:網友

預覽

組件庫官網

github地址

如果喜歡各位小哥哥小姐姐給個小星星鼓勵一下哈, 請勿在生產環境中使用,供學習&交流~~

完整項目目錄結構

git clone到本地安裝依賴后,執行npm run serve進行本地組件庫開發,npm run docs:dev進行組件庫官網開發。一般在src/demo.vue進行單個組件測試通過后,再引入到.vuepress/components中放入組件庫官網。

├─docs               // vuepress開發目錄
│  ├─.vuepress
│  │  ├─components   // 在markdown中可以使用的vue組件
│  │  ├─dist         // vuepress打包目錄
│  │  │  ├─assets
│  │  │  │  ├─css
│  │  │  │  ├─img
│  │  │  │  └─js
│  │  │  ├─components
│  │  │  │  ├─basic
│  │  │  │  ├─form
│  │  │  │  ├─navigation
│  │  │  │  ├─notice
│  │  │  │  └─other
│  │  │  └─guide
│  │  │
│  │  ├─config.js    // vurepess配置修改入口,包括左邊sidebar,右上方nav導航菜單,favicon等
│  │  ├─style.style  // 覆蓋vuerpress默認主題樣式
│  │  └─public       //公共資源入口,如favicon
│  ├─static
│  │  ├─img
│  │  └─js
│  └─views          // vuepress視圖文件,格式是markdown
│      ├─components
│      │  ├─basic
│      │  ├─form
│      │  ├─navigation
│      │  ├─notice
│      │  └─other
│      ├─design
│      │  └─color
│      └─guide
├─src              // 組件庫源碼目錄
│  ├─button
│  ├─cascader
│  ├─collapse
│  ├─container
│  ├─datepicker
│  ├─form
│  ├─icon
│  ├─layout
│  ├─notice
│  ├─plugins
│  ├─slide
│  ├─tab 
│  ├─step
│  ├─sticky
│  └─index.js    // 組件庫源碼組件入口文件,執行npm run build的目標文件
├─package.json   // 與npm發布相關,記錄版本號,包入口文件地址

學習組件庫制作會收獲

  • 學習組件封裝技能,良好的接口設計, 掌握組件設計套路
  • 夯實js/css基礎
  • 深入對vue的理解

制作流程

  1. 組件設計/開發
  2. 發布npm
  3. 制作官網展示

組件設計/開發

頻繁涉及到的vue api包括

  • $children : 獲取當前組件子組件。
  • $parent:  獲取當前組件父組件。
  • $options: 用于當前 Vue 實例的初始化選項, 可以用此選項獲得組件的name。
  • $refs: 一個對象,持有注冊過 ref 特性 的所有 DOM 元素和組件實例。
  • $el: Vue 實例使用的根 DOM 元素。
  • provide & inject :這對選項需要一起使用,允許一個祖先組件向其所有子孫后代注入一個依賴,注意不是響應式的。注入的對象可以是個vue實例的eventBus。
  • $on: 組件監聽自定義事件。
  • $emit: 組件觸發自定義事件。
  • .sync:語法糖,單向數據流中,父組件監聽到子組件修改props的意圖后父組件修改傳入的props,用了.sync不需要顯式在父組件監聽組件內部觸發的自定義事件去修改值, 父組件只要寫:x.sync="bindValue", 注意此時子組件觸發的事件必須是"update:x"此語法糖才生效。
  • updated 生命周期鉤子函數,由于數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用該鉤子, 在父子組件通信可能用到。
  • beforeDestoryed/ destory 生命周期鉤子函數,destory后組件的所有的事件監聽器會被移除。注意:如果是自己在組件內部對dom增加了事件監聽,組件銷毀的時候需要自己手動接觸自己另外添加上去的監聽程序。而且組件銷毀,dom元素還被保留在頁面,需要手動清除,可以調用原生js api, node.remove()清除dom節點。

原生js api包括:

  • target.addEventListener(type, listener[, useCapture])/removeEventListener 由于這是 DOM2 規范的基本內容,幾乎所有瀏覽器都支持這個,而且不需要特殊的跨瀏覽器兼容代碼。
  • Node.contains()返回的是一個布爾值,來表示傳入的節點是否為該節點的后代節點。多用于事件監聽判斷是否點擊了目標區域。
  • window.scrollY 獲取文檔垂直方向的滾動距離。
  • Element​.get​Bounding​Client​Rect() 返回元素的大小及其相對于視口的位置,返回一個對象,包括width/height/left/right/top/bottom。多用于計算定位。

技術點總結

組件設計的思想包括單數據流/ eventBus事件中心,核心是組件通信。

  • 單數據流: 數據的改變是單向的,即通過props的方式,只能讓父組件來修改數據,子組件不能主動修改props。這樣的例子如在collapse/tab/slide組件中,讓父組件來控制選中的值。單向數據流的思想讓數據修改更好設計,邏輯更加清晰。
  • vue插件開發:什么時候用插件開發?當組件不是顯式在代碼中被調用,不是直接寫在template中,而是通過調用Vue原型鏈上的方法被掛載到文檔中。
    比如modal模態框/toast彈窗。插件設計的基本思路是暴露一個install方法,這個方法中在vue原型鏈上增加一個自定義的方法X, X中引入組件a,通過Vue.extend(a)獲得組件構造器Constructor, 在通過new Constructor({propsData})獲得組件實例vm, 再掛載組件實例到文檔中。
import modal from '../notice/modal'export default { install (vue, options) { const Construtor = vue.extend(modal) let modalVm // 保證全局只有一個modal實例 let lastOption vue.prototype.$modal = (options) => { if (lastOption !== JSON.stringify(options)) { //! modalVm  modalVm = new Construtor({ propsData: options })  modalVm.$mount()  document.body.append(modalVm.$el)  }  lastOption = JSON.stringify(options)  modalVm.isVisible = true } }}
  • eventBus:什么時候用eventBus?當狀態的變化需要多個子組件被通知。如tab組件中,當選中的值發生變化,tab-head需要感知變化讓提示的短線做個動畫滑到選中的標簽下,tab-item需要感知變化讓文字變成選中樣式,tab-pane需要感知變化讓選中的面板出現。
  • 遞歸:在級聯組件的設計中用到。類似函數fn中用setTimout(fn,millseconds)調用自己實現setInterval的遞歸效果。組件只要內部提供name屬性,就可以遞歸地調用自身。允許組件模板遞歸地調用自身。通過提供 name 選項,便于調試,在控制臺可以看到可以獲得更有語義信息的組件標簽。
  • 媒體查詢 &flex布局:響應式布局的原理是媒體查詢和百分比布局,介于某個尺寸的時候某個類名生效;跟布局相關的大部分用到flex,非常好用。詳細看阮一峰老師教程
組件類型 組件 單數據流 vue插件開發 eventBus 原生js操作dom & 事件 遞歸 媒體查詢&flex布局
基礎 button按鈕 - - - - - -
基礎 icon圖標 - - - - - -
基礎 grid網格 - - - - - yes
基礎 layout布局 - - - - - yes
表單 input輸入框 - - - - - -
表單 cascader級聯選擇器 yes - - - yes -
表單 form表單 - - - - - -
表單 datepicker日期選擇器 - - - yes - -
導航 tab標簽頁 - - yes - - -
導航 step步驟調 - - - - - -
通知 toast提示 - yes - yes - -
通知 popover彈出框 - - - yes - -
通知 modal模態框 - yes - yes - -
其他 collapse折疊面板 yes - yes - - -
其他 slide輪播圖 yes - - - - -
其他 sticky粘滯 - - - - - -

組件設計三要素

  1. props:可以參考餓了么或者antd, 需要從用戶的角度考慮怎么使用方便和擴展性好,一般需要校驗類型和有效值,設置默認值。
  2. slot:插槽內容分發,使用作用域插槽讓slot也可以獲得組件內部方法,讓用戶自定義的內容頁能調用組件內部方法,比如popover彈出框中用戶想自己加個按鈕手動調用關閉。
  3. event: 組件事件。從用戶角度考慮,比如datepicker組件中用戶想在日期面板被打開或這關閉的時候進行操作。這種一般用在交互類UI組件。

舉個例子

復雜組件datepicker開發思路

1、在原有的popover組件上開發

點擊一個元素A(輸入框)后可以彈出元素B(日期面板)

2、生成日期面板

生成7*6=42個日期,6行是為了確保一個月都能在面板上完整顯示。這里計算最方便的做法是用時間戳,計算出這個月第一天時間戳和這一天周幾,就可以一次性計算出這42個日期。不用算上個月下個月分三段算,這樣的問題是還要考慮邊界情況,如剛好出現上一年下一年等,麻煩容易出bug。這42個日期我們在computed用visibleDays表示。

visibleDays () { let { year, month } = this.display let defaultObj = new Date(year, month, 28) var curMonthFirstDay = helper.getMonthFirstDay(defaultObj) var curMonthFirstDayDay = helper.getDay(curMonthFirstDay) === 0 ? 7 : helper.getDay(curMonthFirstDay) let x = curMonthFirstDayDay - 1 // 前面需要補多少位 var arr = [] for (let i = 0; i < 42; i++) {  arr.push(new Date(curMonthFirstDay.getTime() + (-x + i) * 3600 * 24 * 1000)) } return arr },

3、props接受value, 類型是date

日期面板上的日期渲染的時候加上一個計算的class, 分別加上'today','selected-date','available','prev-month','next-month',進行樣式上的區分

4、實現選中日期

告訴父組件修改數據意圖讓父組件修改傳入的props,對應使用我們組件的時候使用, 這里的基礎知識是組件上的v-model是個語法糖,v-model="x"會被解析成:value="a" @input="a=$event"。同時面板上輸入框顯示的數據也要跟著變化,所以這里用計算屬性,如在computed中用formattedValue表示。

 formattedValue: {  return this.value instanceof Date ? helper.getFormatDate(this.value) : '' }

5、實現點擊上一年/月,下一年/月

我們需要知道當前展示的是哪一年哪一個月,這個數據是組件內部維護的,所以在data申明一個display對象

display: {  year: (this.value && this.value.getFullYear()) || new Date().getFullYear(),  month: (this.value && this.value.getMonth()) || new Date().getMonth() }

點擊的時候即修改display對象的year/month,因為visibleDays也是計算屬性,依賴display對象,所以點擊上一年/月,下一年/月,渲染的日期也跟著變。

6、實現選擇年

年面板的制作,生成12個年,點擊第1(12)個年渲染出上(下)12個年。這里只需要給渲染出來的年的第一個和最后一個dom元素綁定事件,事件監聽程序傳入當前點擊的元素的值,即可計算出上或下一個12年。
同理點擊年的時候用$emit通知父組件修改value

7、實現選擇月

直接寫死12個月份,同理點擊月的時候用$emit通知父組件修改value

8、增加住面板上【今天】和【清空】的按鈕

點擊的時候用$emit通知父組件修改value,new Date()和''

9、細節處理

用戶選中完日期后要關閉面板

用戶選了年后點擊周圍空白區域日期面板關閉,第二次點擊進來應該默認展示日面板

10、用戶可以修改輸入框里面的值,需要判斷有效性

有效的話$emit通知父組件改值,無效的話當失去焦點的時候變回原來的值,這里需要用原生js去給input修改value。注意這里直接改formattedValue的話無效,雖然輸入框的值綁定了:value="formattedValue",但是因為formattedValue是計算屬性,依賴于this.value,在用戶輸入無效值的情況下this.value不會改變,因此界面不會被更新,所以需要手動改value的值。

setValueManually ($event) { if (!helper.isValidDate($event)) {  this.$refs.inputWrapper.$refs.input.value = this.isDate(this.value) ? helper.getFormatDate(this.value) : ''  return } this.$emit('input', new Date($event)) }

11、完善

給彈出日期面板和關閉日期面板增加組件自定義事件, 即調用$emit觸發'showDatepicker'和'closeDatepicker'事件。

發布npm

1、使用vue cli3 的庫模式打包代碼,修改package.json 中的"build": "vue-cli-service build --target lib --name sakura src/index.js",打包后輸出umd構建版本, 參考vue cli。

什么是umd? 統一模塊定義,可以兼容common.js(node端規范)/ AMD(瀏覽器端規范)/ ES6(node端不完全支持)等多種模塊化方案,確保代碼在各種環境下能被運行。

File      Size      Gzippeddist/sakura.umd.min.js 13.28 kb     8.42 kbdist/sakura.umd.js  20.95 kb     10.22 kbdist/sakura.common.js  20.57 kb     10.09 kbdist/sakura.css   0.33 kb     0.23 kb

2、在package.json指明模塊入口"main":"dist/sakura.umd.min.js"

 "name": "heian-sakura-ui", "version": "0.0.6", "private": false, "main":"dist/sakura.umd.min.js", "description": "an UI framework based on Vue.js",

3、在npm 上注冊一個用戶

4、在命令行輸入,注意每次發布都要修改package.json中的 "version": "0.0.x","private"必須設置成false才能發布

npm adduser // 提示輸入注冊的用戶名npm publish

官網制作

使用vue press

1、在原有項目中使用

# 安裝依賴npm install -D vuepress# 創建一個 docs 目錄mkdir docs

在package.json中進行腳本配置

{"scripts": { "docs:dev": "vuepress dev docs", "docs:build": "vuepress build docs"}}

然后運行npm run docs:dev即可訪問

2、簡單配置

在docs/.vuepress下新建文件config.js

module.exports = { base:'/sakura-ui/', title: 'Sakura UI', description: 'Inspiration from heian sakura', head: [  ['link', { rel: 'icon', href: '/favicon.ico' }] ], themeConfig: {  nav: [  { text: 'Home', link: '/' },  { text: 'Github', link: 'https://github.com/Firenzia/sakura-ui/' },  ],  sidebar: [   {    title: '開發指南',    collapsable: true,    children: [    'views/guide/install.md',    'views/guide/get-started.md'    ]   },   {    title: '設計',    collapsable: true,    children: [    'views/design/color/',    ]   },   {    title: '組件',    collapsable: true,    children: [    'views/components/basic/',    'views/components/form/',    'views/components/navigation/',    'views/components/notice/',    'views/components/other/'    ]   },  ]  } }

3、使用vue組件

官網中提到,所有在 .vuepress/components 中找到的 *.vue 文件將會自動地被注冊為全局的異步組件,可以在markdown中引用, vue文件中的代碼高亮我用的是vue-highlightjs 查看這里

4、編寫文檔

由于所有的頁面在生成靜態 HTML 時都需要通過 Node.js 服務端渲染,對于SSR 不怎么友好的組件(比如包含了自定義指令),你可以將它們包裹在內置的 ClientOnly 組件中,而且注意因為是ssr,組件內部beforeCreate, created生命周期鉤子函數訪問不到瀏覽器 / DOM 的 API,只能在beforeMount和mounted中調用。

---title: 'Basic 基礎'sidebarDepth: 2---## Icon 圖標<ClientOnly> <sakura-icon/><font size=5>Attributes</font>| 參數| 說明 | 類型 | 可選值 | 默認值 || :------ | ------ | ------ | ------ | ------ || name | 圖標名稱 | string |- | - || color | 圖標顏色, 支持常見顏色和十六進制顏色 | string |- | - |</ClientOnly>

5、覆蓋默認主題樣式

在.vuepress下新增style.styl進行覆蓋。

6、部署到github

官網上介紹的很清楚,點這里。

在項目根目錄下新增deploy.sh,windows下直接命令行運行./deploy.sh即可發布到github pages上。

結語

如果你能看到這里,非常感謝,第一次寫文章,希望大家多多提出意見。組件庫還有很多細節需要完善,比如里面css的類名命名我沒做的很規范,大部分組件都是自己測試沒有測到復雜或特殊場景,還有很多功能還沒支持。通過這段時間制作組件庫,自己的技術有了一定提升,官網的展示融入了自己的一點想法和設計,希望大家喜歡~~ 謝謝!

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
xxx一区二区| 91精品国产综合久久久久久久久| 国产精品久久久久影院日本| 国产剧情日韩欧美| 91视频免费在线| 国产精品综合久久久| 日韩精品中文字幕有码专区| 日韩电影在线观看免费| 粉嫩老牛aⅴ一区二区三区| 国产在线日韩在线| 最近中文字幕mv在线一区二区三区四区| 中文字幕av一区| 影音先锋日韩有码| 中国日韩欧美久久久久久久久| 国产精品久久视频| 茄子视频成人在线| 日韩欧美精品网站| 97超级碰在线看视频免费在线看| 在线亚洲欧美视频| 色七七影院综合| 麻豆精品精华液| 尤物九九久久国产精品的分类| 精品国偷自产在线| 久久久久亚洲精品国产| 亚洲一区二区中文| 91网站免费观看| 日韩免费黄色av| 欧美一级片久久久久久久| 欧美日韩中文在线| 国产亚洲成av人片在线观看桃| 日日摸夜夜添一区| 黑人巨大精品欧美一区二区免费| 久久久久久高潮国产精品视| www.欧美精品一二三区| 91视频免费网站| 午夜精品视频网站| 日韩电影免费观看中文字幕| 午夜精品久久久99热福利| 九九九久久久久久| 日韩电影中文字幕av| 伊人伊成久久人综合网小说| 国产欧美一区二区| 欧美老女人在线视频| 国产精品日韩在线播放| 国产精品久久久久久中文字| 国产精品偷伦视频免费观看国产| 欧美激情乱人伦| 97久久精品人搡人人玩| 欧美精品18videos性欧| 亚洲第一视频在线观看| 国产成人在线精品| 欧美成人精品一区二区| 98视频在线噜噜噜国产| 俺去亚洲欧洲欧美日韩| 国产成人精品免费久久久久| 欧美性猛交xxxx富婆弯腰| 日韩精品中文在线观看| 国产在线观看精品| 另类视频在线观看| 国产精品久久久久久久美男| 97超级碰在线看视频免费在线看| 亚洲精品白浆高清久久久久久| 青青草原一区二区| 国产+人+亚洲| 久久综合伊人77777| 成人午夜在线视频一区| 成人黄色免费网站在线观看| 欧美激情一区二区三级高清视频| 日产精品99久久久久久| 亚洲尤物视频网| 欧美亚洲视频在线观看| 国产一区欧美二区三区| 亚洲成av人乱码色午夜| 91免费综合在线| 美女啪啪无遮挡免费久久网站| 国产精品自在线| 欧美中文字幕在线观看| 日韩大胆人体377p| 青青草国产精品一区二区| 国产精国产精品| 日韩亚洲欧美中文高清在线| 国产精品视频在线播放| 亚洲第一福利网站| www高清在线视频日韩欧美| 久久精品国产v日韩v亚洲| 91国产视频在线播放| 日本久久久久亚洲中字幕| 亚洲xxxx妇黄裸体| 精品久久久中文| 久久精品亚洲热| 91成人天堂久久成人| 北条麻妃一区二区在线观看| 欧美精品成人91久久久久久久| 红桃av永久久久| 黑人精品xxx一区| 亚洲天堂av在线免费观看| 色悠悠久久88| 成人a在线视频| 日韩精品视频在线观看网址| 一区二区三区国产在线观看| 永久免费毛片在线播放不卡| 亚洲欧美激情另类校园| 精品久久久久久亚洲国产300| 欧美日韩成人在线观看| 欧美黄色片免费观看| 91tv亚洲精品香蕉国产一区7ujn| 国模精品一区二区三区色天香| 97色在线观看| 国产香蕉精品视频一区二区三区| 这里只有精品在线播放| 亚洲精品视频久久| 91精品视频大全| 亚洲午夜精品久久久久久久久久久久| 国产精品视频免费在线观看| 91国在线精品国内播放| 91在线观看欧美日韩| 亚洲黄色www网站| 中文字幕亚洲无线码在线一区| 狠狠躁18三区二区一区| 91精品视频播放| 欧美日韩亚洲国产一区| 青草热久免费精品视频| 欧美性生交大片免网| 久久成人免费视频| 国产成+人+综合+亚洲欧洲| 韩国v欧美v日本v亚洲| 欧美日产国产成人免费图片| 岛国av一区二区| 91精品久久久久久久久| 欧美黑人xxxⅹ高潮交| 亚洲成人黄色在线| 亚洲最大的av网站| 日韩欧美亚洲一二三区| 亚洲精品自拍视频| 欧美另类xxx| 日日噜噜噜夜夜爽亚洲精品| 麻豆精品精华液| 日韩中文综合网| 欧美福利视频在线观看| 亚洲电影免费观看高清完整版| 色爱精品视频一区| 精品日韩中文字幕| 国产精品99久久久久久白浆小说| 欧美夫妻性生活视频| 亚洲一区二区久久| 欧美xxxx综合视频| 久久久免费电影| 亚洲午夜精品久久久久久久久久久久| 欧美精品一区二区免费| 欧美午夜精品久久久久久久| 色综合久久中文字幕综合网小说| 欧美性猛交xxxx乱大交蜜桃| 在线观看日韩av| 日韩av不卡在线| 日本精品性网站在线观看| 亚洲a级在线观看| 国产精品久久久久久亚洲调教| 欧美激情成人在线视频| 一道本无吗dⅴd在线播放一区| 91麻豆桃色免费看| 日本一区二区三区四区视频| 大伊人狠狠躁夜夜躁av一区| 91精品综合视频| 91香蕉亚洲精品|