前端攻城?️對模態彈框確定很熟悉,無論是套用bootstrap的仍是本身寫的,它經常使用來完成與用戶的展現交互和處理一些數理邏輯。可是在用來展現小體量的信息時我認爲它是過於龐大的,咱們能夠採用更優雅的氣泡卡片來展現那些小體量的信息。
就像這樣的↓↓↓
先附上體驗地址css
<div class="v-popover-tag" @click.stop="pop($event)"> <slot></slot> </div> <div class="v-popover-wrap" :style="{left: x + 'px', top: y + 'px', visibility: show ? 'visible' : 'hidden'}" v-el:pop> <div class="v-popover-box"> <div class="v-popover-title">{{title}}</div> <div class="v-popover-content">{{content}}</div> <div :class="['v-popover-arrow', placement == 'top' ? 'v-popover-arrow-top' : 'v-popover-arrow-bottom']" :style="{left: arrowLeft + 'px'}"></div> </div> </div>
這裏對熟悉vue的同窗來說沒有什麼特殊的地方,主要有一個slot
標籤會有疑問,在編譯模版時遇到slot
標籤會回到html
文檔中用相應的內容代替,使用方式能夠參考官方文檔vue-slothtml
props: { title: { type: String, default: '標題' }, content: { type: String, default: '內容' }, placement: { type: String, default: 'top' } }, data() { return { show: false, arrowLeft: 0, x: 0, y: 0 } }
來自父組件的數據title
和content
是必選項(雖然我也給它們設置了默認值),placement
表明氣泡卡片的出現位置,默認會出如今觸發目標的上方,暫時支持top和bottom。其餘都是子組件的自身數據,用於控制氣泡卡片的顯示隱藏和位置。前端
pop(e) { if(this.show){ this.show = false return } var target = e.target this.arrowLeft = target.offsetWidth / 2 this.x = target.offsetLeft if(this.placement == 'top'){ this.y = target.offsetTop - this.$els['pop'].offsetHeight - 3 }else { this.y = target.offsetTop + target.offsetHeight + 3 } this.show = true }
這裏依靠事件的冒泡,slot
中的事件會冒泡到子組件中定義的父層div
標籤上,進而觸發事件執行後續的位置計算。vue
這方面難點主要是那兩個小三角形的,其餘的都比較簡單。git
.v-popover-arrow{ position: absolute; width: 0; height: 0; border: 5px solid transparent; margin-left: -5px; &:after{ content: " "; margin-left: -4px; border: 4px solid transparent; position: absolute; width: 0; height: 0; } } .v-popover-arrow-top{ border-bottom-width: 0; border-top-color: #d9d9d9; bottom: -5px; &:after{ border-top-color: #fff; bottom: -3px; } }
html: <div id="app"> <v-popover :title="popTitle" :content="popContent" :placement="popPlacement"> <button class="btn btn-primary">點擊彈出氣泡卡片</button> </v-popover> </div> js: var btn = new Vue({ el: '#app', data: { popTitle: '我是標題' popContent: '氣泡內容氣泡內容氣泡內容氣泡內容氣泡內容氣泡內容氣泡內容氣泡內容氣泡內容', popPlacement: 'top' }, components: { 'v-popover': components.popover } })
這裏我在組件標籤中插了一個button
標籤,上面提到的slot
最終就會被這個按鈕代替,同時它的點擊事件會通過冒泡被觸發。github
插播小廣告。。。不要打我,我和@二胖手正在維護相關組件庫web-style,待組件基本完善後,參考文檔也會跟上,歡迎關注,有什麼好的建議也歡迎討論。web