一、需求:当body的有了zoom值之后,element ui相关的popper弹框(下拉框、日期选择框、分页组件)位置都会出现偏移问题
二、问题来源
popper弹框都会需要根据屏幕x,y的坐标来设置位置,但是有了zoom值之后,x,y坐标就会获取错误,这是element ui官方的一个bug,当前element ui已经停止维护了,所以我们就得更改源码。
三、如何解决
1.使用饿了么官方解决方式(不推荐,因为只能解决这两个组件偏移问题,而且当在弹框打开下拉框又会重新这个问题)
select组件添加:popper-append-to-body="false"
<el-select :popper-append-to-body="false" v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
date-picker组件添加:append-to-body="false"
<el-date-picker
:append-to-body="false"
v-model="value1"
type="date"
placeholder="选择日期">
</el-date-picker>
2.通过修改源码的方式(推荐,一劳永逸)
在'element-ui/lib/utils/popper.js文件中
的617行634行和635行中进行修改
var styles = {
position: data.offsets.popper.position,
direction: data.placement
}
else {
//获取当前zoom
var zoom = window.getComputedStyle(document.body).zoom
styles.left = left
styles.top = top
//当有zoom值时,重新修改样式
if (zoom !== '1') {
//其中top-start和top是popper打开的方向,可以通过打印styles.direction来判断这个组件的打开方向
if (styles.direction === 'top-start') {
styles.left = left / zoom
//40或者30是我自己定的,这个方法不能100%还原之前的效果,可以自定义值
styles.top = top / zoom + 40
} else if (styles.direction === 'top') {
styles.left = left / zoom
styles.top = top / zoom + 30
} else {
styles.left = left / zoom
styles.top = top / zoom
}
}
}
修改源码的方式虽好,但是重新下依赖就会丢失修改的代码(如果你想防御性编程的话,就不用看后面的了)
将我们修改后的源码抽离出来为一个js文件,再全局使用,即使重新下载依赖也生效
1.创建element-ui-bug-fixed.js
文件
import Popper from 'element-ui/lib/utils/popper'
Popper.prototype.modifiers.applyStyle = function (data) {
// console.log(data.placement);
// apply the final offsets to the popper
// NOTE: 1 DOM access here
var styles = {
position: data.offsets.popper.position,
direction: data.placement
}
// round top and left to avoid blurry text
var left = Math.round(data.offsets.popper.left)
var top = Math.round(data.offsets.popper.top)
// if gpuAcceleration is set to true and transform is supported, we use `translate3d` to apply the position to the popper
// we automatically use the supported prefixed version if needed
var prefixedProperty
if (
this._options.gpuAcceleration &&
(prefixedProperty = getSupportedPropertyName('transform'))
) {
styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'
styles.top = 0
styles.left = 0
}
// othwerise, we use the standard `left` and `top` properties
else {
//获取当前zoom
var zoom = window.getComputedStyle(document.body).zoom
styles.left = left
styles.top = top
//当有zoom值时,重新修改样式
if (zoom !== '1') {
//其中top-start和top是popper打开的方向,可以通过打印styles.direction来判断这个组件的打开方向
if (styles.direction === 'top-start') {
styles.left = left / zoom
//40或者30是我自己定的,这个方法不能100%还原之前的效果,可以自定义值
styles.top = top / zoom + 40
} else if (styles.direction === 'top') {
styles.left = left / zoom
styles.top = top / zoom + 30
} else {
styles.left = left / zoom
styles.top = top / zoom
}
}
}
// any property present in `data.styles` will be applied to the popper,
// in this way we can make the 3rd party modifiers add custom styles to it
// Be aware, modifiers could override the properties defined in the previous
// lines of this modifier!
Object.assign(styles, data.styles)
setStyle(this._popper, styles)
// set an attribute which will be useful to style the tooltip (use it to properly position its arrow)
// NOTE: 1 DOM access here
this._popper.setAttribute('x-placement', data.placement)
// if the arrow modifier is required and the arrow style has been computed, apply the arrow style
if (
this.isModifierRequired(this.modifiers.applyStyle, this.modifiers.arrow) &&
data.offsets.arrow
) {
setStyle(data.arrowElement, data.offsets.arrow)
}
return data
}
function setStyle (element, styles) {
function is_numeric (n) {
return n !== '' && !isNaN(parseFloat(n)) && isFinite(n)
}
Object.keys(styles).forEach(function (prop) {
var unit = ''
// add unit if the value is numeric and is one of the following
if (
['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !==
-1 &&
is_numeric(styles[prop])
) {
unit = 'px'
}
element.style[prop] = styles[prop] + unit
})
}
2.在main.js
文件中添加这个文件(注意路径)
//解决饿了么缩放bug
import '@/utils/element-ui-bug-fixed' // 引入自定义的 Popper 修改脚本
上才艺!!!