转载

vue组件系列-气泡卡片

从模态弹框讲起

前端攻城��️对模态弹框肯定很熟悉,不管是套用bootstrap的还是自己写的,它常用来完成与用户的展示交互和处理一些数理逻辑。但是在用来展示小体量的信息是我认为它是过于庞大的,我们可以采用更优雅的气泡卡片来展示那些小体量的信息。

就像这样的↓↓↓

vue组件系列-气泡卡片

先附上 体验地址

实现

vue模版

  <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-slot

数据

props: {   title: {     type: String,     default: '标题'   },   content: {     type: String,     default: '内容'   },   placement: {     type: String,     default: 'top'   } }, data() {   return {     show: false,     arrowLeft: 0,     x: 0,     y: 0   } }

来自父组件的数据 titlecontent 是必选项(虽然我也给它们设置了默认值), 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 标签上,进而触发事件执行后续的位置计算。

scss

这方面难点主要是那两个小三角形的,其他的都比较简单。

.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 最终就会被这个按钮代替,同时它的点击事件会经过冒泡被触发。

打个广告

插播小广告。。。不要打我,我和@二胖手正在维护相关组件库 web-style ,待组件基本完善后,参考文档也会跟上,欢迎关注,有什么好的建议也欢迎讨论。

原文  https://segmentfault.com/a/1190000005812503
正文到此结束
Loading...