慕仰4546411
2020-01-31 12:05:04浏览 829
1. 上一次的问题总结。
- overflow:hidden -> body.appendChild
- 关闭重复 -> 分开,document 只管外面,popover 只管里面
- 忘了取消监听 document -> 收拢 close
2. 可以把一个函数哟没有五行作为一个优化的标准,简称为五行定律
3. 接下来把样式改好点
.content-wrapper { // 如果写了scoped,popover里面那么就只作用于popover里面,移到外面就在外面了就可以
position: absolute;
border: 1px solid $border-color;
border-radius: $border-radius;
filter: drop-shadow(0 0 1px rgba(0,0,0,0.5));
/*通过drop-shadow解决小三角没有阴影的问题,但是兼容性不好 */
/*box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);*/
background: white;
transform: translateY(-100%);
margin-top: -10px;
padding: .5em 1em;
max-width: 20em;
word-break: break-all;
&::before , &::after{
content: '';
display: block;
width: 0;
height: 0;
position: absolute;
border: 10px solid transparent;
left: 10px;
}
&::after{
content: '';
display: block;
width: 0;
height: 0;
position: absolute;
border: 10px solid transparent;
left: 10px;
}
&::before {
border-top-color: black;
top: 100%;
}
&::after {
border-top-color: white;
top: calc(100% - 1px);
}
}
4. 增加功能:用户可以选择 popover 是上面下面左面右面
// 先要给contentWrapper加一个类,传递进入位置信息
<div ref="contentWrapper" class="content-wrapper" v-if="visible"
:class="{[`position-${position}`]:true}">
</div>
// 获得位置信息
props: {
position:{
type: String,
default: 'top',
validator(value){
return ['top','bottom','left','right'].indexOf(value) >= 0
}
}
},
}
// 在method里面写方法,主要控制大概位置
method: {
positionContent() {
const {contentWrapper, triggerWrapper} = this['$refs']
document.body.appendChild(contentWrapper)
let {width, height, top, left} = triggerWrapper.getBoundingClientRect()
if(this.position === 'top'){
contentWrapper.style.left = left + window.scrollX + "px"
contentWrapper.style.top = top + window.scrollY + "px"
}else if(this.position === 'bottom'){
contentWrapper.style.left = left + window.scrollX + "px"
contentWrapper.style.top = top + height + window.scrollY + "px"
}else if(this.position === 'left'){
contentWrapper.style.left = left + window.scrollX + "px"
let {height: height2} = contentWrapper.getBoundingClientRect()
contentWrapper.style.top = top + window.scrollY + (height - height2)/2 + "px"
}else if(this.position === 'right'){
contentWrapper.style.left = left + window.scrollX + width + "px"
let {height: height2} = contentWrapper.getBoundingClientRect()
contentWrapper.style.top = top + window.scrollY + (height - height2)/2 + "px"
}
},
}
// 然后对css进行处理,主要是箭头当想
<style lang="scss" scoped>
$border-color: #333;
$border-radius: 4px;
.popover {
display: inline-block;
vertical-align: top;
position: relative;
}
.content-wrapper { // 如果写了scoped,popover里面那么就只作用于popover里面,移到外面就在外面了就可以
position: absolute;
border: 1px solid $border-color;
border-radius: $border-radius;
filter: drop-shadow(0 0 1px rgba(0,0,0,0.5));
/*通过drop-shadow解决小三角没有阴影的问题,但是兼容性不好 */
/*box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);*/
background: white;
padding: .5em 1em;
max-width: 20em;
word-break: break-all;
&::before , &::after{
content: '';
display: block;
border: 10px solid transparent;
width: 0;
height: 0;
position: absolute;
}
&.position-top {
transform: translateY(-100%);
margin-top: -10px;
&::before, &::after{
left: 10px;
}
&::before {
border-top-color: black;
top: 100%;
}
&::after {
border-top-color: white;
top: calc(100% - 1px);
}
}
&.position-bottom {
margin-top: 10px;
&::before, &::after{
left: 10px;
}
&::before {
border-bottom-color: black;
bottom: 100%;
}
&::after {
border-bottom-color: white;
bottom: calc(100% - 1px);
}
}
&.position-left{
transform: translateX(-100%);
margin-left: -10px;
&::before, &::after{
transform: translateY(-50%);
top: 50%;
}
&::before {
border-left-color: black;
left: 100%;
}
&::after {
border-left-color: white;
left: calc(100% - 1px)
}
}
&.position-right{
margin-left: 10px;
&::before, &::after{
transform: translateY(-50%);
top: 50%;
}
&::before {
border-right-color: black;
right: 100%;
}
&::after {
border-right-color: white;
right: calc(100% - 1px)
}
}
}
</style>
5.发现目前代码比较冗余,进一步优化代码
- 多个 if else 逻辑相似,首先要把共有代码抽上去,利用表驱动编程的技巧。
positionContent() {
const {contentWrapper, triggerWrapper} = this['$refs']
document.body.appendChild(contentWrapper)
const {width, height, top, left} = triggerWrapper.getBoundingClientRect()
const {height: height2} = contentWrapper.getBoundingClientRect()
let positions = {
top: {
top: top + window.scrollY,
left: left + window.scrollX
},
bottom: {
top: top + height + window.scrollY,
left: left + window.scrollX
},
left: {
top: top + window.scrollY + (height - height2)/2,
left: left + window.scrollX
},
right: {
top: top + window.scrollY + (height - height2)/2,
left: left + window.scrollX + width
},
}
contentWrapper.style.left = positions[this.position].left + 'px'
contentWrapper.style.top = positions[this.position].top + 'px'
},
6.实现 hover 的效果
// 每个事件的处理逻辑不一样,所以要分开写if
mounted(){
if(this.trigger === 'click'){
this['$refs']['popover'].addEventListener('click',this.onClick)
} else {
this['$refs']['popover'].addEventListener('mouseenter',this.open)
this['$refs']['popover'].addEventListener('mouseleave',this.close)
}
},
// 负责任的轮子要写destory,防止内存泄露
destroyed(){
if(this.trigger === 'click'){
this['$refs']['popover'].removeEventListener('click',this.onClick)
} else {
this['$refs']['popover'].removeEventListener('mouseenter',this.open)
this['$refs']['popover'].removeEventListener('mouseleave',this.close)
}
},