element ui组件,el-image组件
主要介绍了elementui下图片组件的使用,通过示例代码进行了非常详细的介绍,对大家的学习或工作有一定的参考价值。有需要的朋友下面和边肖一起学习。
目录
elementui的组件-image组件elementui的功能-image组件elementui的功能-image实现fit风格实现图片的延迟加载可配置功能模块实现图片预览失败和图片加载(image-view.vue文件)对element ui管理事件的一些解释和总结
elementui-image组件的组成
元素的图像模块主要由两个文件组成:main.vue和image-viewer.vue,最外面的main.vue是图像组件的主文件,image-viewer.vue文件主要用于点击图片后预览大图。
elementui-image组件的功能
首先明确图像组件中完成了哪些功能。功能列表如下:
(1)图像组件可以设置fit的属性,通过fit设置图像的显示形式。
(2)图片的懒加载是基于滚动条事件的。
(3)通过设置preview可以启动图片的大范围预览,需要传入previewSrcList的参数。
(4)可以配置图片加载失败的显示,可以通过插槽实现。
(5)可以配置图像加载过程的显示,可以通过插槽实现。
(6)大图预览中图片的功能:缩放、旋转、调整比例、切换图片、基于鼠标滚轮的缩放、基于键盘输入的缩放、切换、隐藏预览功能、基于鼠标按下事件的拖放功能。
elementui-image的功能实现
fit的样式实现
拟合样式主要包括五种形式,即:填充、无、包含、缩小、覆盖。
部分版本较低的浏览器不支持Object-fit property,所以需要自己处理以上五种显示形式,下面会组织编写。
Object-fit属性用于指定如何调整img或video的大小以适合其容器。这个属性告诉内容以多种方式填充容器;比如“保持长宽比”或者“拉伸,尽可能多占空间”。具体图片显示效果如下:
根据MDN-CSS的解释,上述五种形式的对应解释如下
包含:
当填充元素的内容框时,被替换的内容将被缩放以保持其纵横比。整个对象在填充盒子时保持其纵横比,所以如果纵横比与盒子的纵横比不匹配,对象将被添加==黑边==。
封面:
替换的内容填充元素的整个内容框,同时保持其纵横比。如果对象的纵横比与内容框不匹配,对象将被裁剪以适合内容框。
填充:
被替换的内容只是填充元素的内容框。整个对象将完全填满这个框。如果对象的纵横比与内容框不匹配,对象将被拉伸以适合内容框。
无:
被替换的内容将保持其原始大小。
缩小比例:
的内容大小与none或contain的内容大小相同,具体取决于哪一个的对象大小更小。
然后,在image组件中,为了实现fit的动态配置,image组件是父组件导入的fit的属性值。如果没有导入,将选择默认填充来处理图片。
同时,由于一些较低版本的浏览器平台不支持object-fit,image组件对其进行处理,通过一个计算的数据imageStyle来控制image的样式。同时,对于不支持的浏览器平台,也为兼容性定制了类似object-fit的样式。
具体兼容代码如下:
//使用此代码确定当前浏览器是否受支持。如果不支持,将返回false。如果支持,则返回true。
const isSupportObjectFit=()=document . document element . style . object fit!==未定义;
//定义枚举类,用来对应几种形式的拟合
const ObjectFit={
无:无,
包含:“包含”,
封面:“封面”,
填充:填充,
缩小比例:“缩小比例”
};
/**
* 兼容代码,它的实际实现也很简单,实际就是处理图片的长宽比,来控制图片的显示格式
*/
getImageStyle(fit) {
const { imageWidth,imageHeight }=this
常数{
客户端宽度:containerWidth
客户端高度:容器高度
}=这个10.95美元埃尔
如果(!imageWidth !imageHeight !containerWidth !集装箱高度)返回{ };
const imageAspectRatio=图像宽度/图像高度;
常数容器光谱比=容器宽度/容器高度;
if (fit===ObjectFit .SCALE_DOWN) {
const较小=图像宽度容器宽度图像高度容器高度;
fit=isSmaller?对象匹配无:对象匹配。包含;
}
开关(适合){
案例对象匹配。无:
return { width: auto ,height: auto };
案例对象匹配。包含:
return(imageAspectRatio containeraspectreratio)?{宽度: auto } : {高度: auto };
案例对象匹配。封面:
return(imageAspectRatio containeraspectreratio)?{高度: auto } : {宽度: auto };
默认值:
return { };
}
}
/**
* 图片的长宽获取实际是在安装好的种获取到的,通过新建一个图像类,然后监控方法的库是否成功,如果成功了,就可以读取图片的长宽。
*/
loadImage() {
如果(这个$isServer)返回;
//重置状态
this.loading=true
this.error=false
const img=new Image();
img.onload=e=this.handleLoad(e,img);
img。出错时=此。处理错误。绑定(这个);
//绑定超文本标记语言属性
//这样它的行为才能一致
Object.keys(this .$attrs)。forEach((key)={
常数值=这个.$ attrs[key];
img.setAttribute(键,值);
});
img。src=这个。src
}
装卸(例如,img) {
这个。图像宽度=img。宽度;
这个。图像高度=img。身高;
this.loading=false
this.error=false
}
//计算的属性图像样式
imageStyle() {
const { fit }=this
如果(!这个$isServer fit) {
返回isSupportObjectFit()
?{ 对象适合:适合}
:这个。getimagestyle(fit);
}
return { };
}
通过上述的代码,就可以设置图片的合适的属性了,如果说浏览器不支持,也可通过自定义宽度与高度来实现类合适的的样式。虽然说实现起来的步骤比较多,但是这样可以为大部分浏览器平台提供很好的适配和兼容,是一种很好的处理方式。
图片懒加载的实现方式
图片懒加载的实现实际上用了节流器来完成,通过设置延迟器,避免在第一时间加载图片,等待一个指定的时间后加载图片,达到图片懒加载的实现。具体的防抖和节流的实现,这里就先不赘述了,等到之后出一片博文之后,来在这里添加一条链接。
同时这里的图片懒加载也是基于卷起的事件监听进行实现,然后加入喉咙之后,设置等待时间为200毫秒,来实现显示的延迟加载。
具体实现代码如下:
addLazyLoadListener() {
//判断是否是服务端渲染,如果是服务端渲染就无法使用懒加载,因为服务端渲染是把所有标签全部渲染完成后输出的
如果(这个$isServer)返回;
const { scrollContainer }=this
let _ scrollContainer=null
if(isHtmlElement(滚动容器)){
_ scroll container=滚动容器;
} else if(是字符串(滚动容器)){
_ scroll container=文档。查询选择器(滚动容器);
}否则{
_ scroll container=get scroll container(this .$ El);
}
if (_scrollContainer) {
这个. scroll container=_ scroll container;
//这里来设置节流,等待时间为200毫秒,这样就不会实时出发卷起滚动事件。
这个. lazyLoadHandler=throttle(200,这个。handlelazyload);
在(_scrollContainer, scroll ,这个. lazyLoadHandler);
这个。handlelazyload();
}
}
实现还是比较简单的,但是这里很多东西感觉值得学习,无论是节流还是滚动事件的设置。作为现在的新手,值得学习。还可以学习节流的场景,以及节流与事件结合的技巧。
图片加载失败和加载中的可配置的实现
这里失败的镜像加载和加载中的可配置实现实际上是基于slot实现的,也就是vue中的slot,这里用的是命名slot。插槽的使用相对简单。下面是vue官网对slot的介绍:vue slot。
图片预览的功能模块实现(image-view.vue文件)
先放一张图,通过这张图中的内容介绍预览功能。
预览模块的功能实现比较好玩,主要分以上几个方面。现在我们来谈谈这几个方面:
布局:
页面的布局其实就是mask的实现,但是image-view的mask实现存在一些问题,就是在页面中插入组件时,如果整个页面是一个很长的页面,那么当图像被滚轮缩放时,主页面也会受到影响。整个页面布局是flex布局的形式。同时,justify-content被设置为中心,align-item也被设置为中心,以便图像可以显示在中心。其他图标是绝对的。图标组仍然基于绝对,并且设置了灵活布局。同时,为了确保每个图标都分布在图标组中,justify-content被设置为space-around。
Flex布局很牛逼,省了不少时间。它只需要调解基线。
缩放比例
图像缩放的功能是基于css中的transform属性,提供了比例调整,所以缩放图像非常方便。同时,当图像使用transform时,会默认提升到顶层,完美解决了蒙版遮盖的问题,一举两得。图像组件中基本缩放的控制基于两个缩放按钮,因此也非常方便。
辐状的
图像旋转的功能是基于css中的transform属性,它提供了旋转的调整,所以旋转图像很方便。
在旋转和缩放的实现中,会设置一个判断来确定是否是普通按钮操作。如果是普通操作,会增加一个转场来设置切换时间,这样交互会更友好。但是在滚轮的缩放中,需要取消转场属性,因为滚轮滑动非常快,交互非常频繁。为了满足节流的要求,需要将滚轮每次滚动的步长设置得比普通按钮长,并取消过渡,防止直接卡死。
等比例调整
比例调节功能的实现也很简单。只有直接取消原来设置的最大宽度和最大高度才能实现。
常量模式={
包含:{
名称:“包含”,
图标:“el图标-全屏”
},
原件:{
姓名:原件,
图标:“El-icon-c-缩放至原始值”
}
};
toggleMode() {
if (this.loading)返回;
const Mode names=object . keys(Mode);
const Mode values=object . values(Mode);
const index=mode values . index of(this . mode);
const nextIndex=(index 1)% modenames . length;
this . Mode=Mode[Mode names[nextIndex]];
this . reset();
}
您可以通过按钮事件切换类。
画面切换
通过键盘输入的左右箭头键或页面中提供的按钮切换图片。这里的画面切换就是通过修改currentImage,改变指向srclist的下标来进行切换。同时,加载的一个步骤是在srclist中初始采集点图像的位置初始化下表。
//currentImage和viewerZIndex是一个计算属性,不需要修改这两个属性,一旦改变就可以触发。
计算值:{
currentImg() {
返回this . URL list[this . index];
},
viewerZIndex() {
const nextZIndex=popup manager . nextZIndex();
返回this.zIndex nextZIndex?this . zindex:next zindex;
}
}
//具体实现
方法:{
prev() {
如果(this.isFirst!this.infinite)返回;
const len=this . URL list . length;
this . index=(this . index-1 len)% len;
},
下一个(){
如果(this.isLast!this.infinite)返回;
const len=this . URL list . length;
this . index=(this . index 1)% len;
}
}
基于鼠标滚轮的缩放
基于鼠标滚轮的缩放是在当前页面添加一个鼠标滚轮滑动事件。同时通过window.requestAnimationFrame优化鼠标滚轮滑动的效率,使事件的触发与浏览器刷新频率相同,性能得到优化。
鼠标滚轮的事件在不同的浏览器中有不同的事件名称,图像组件中的处理是判断isFirefox,具体代码如下
导出常量isFirefox=function() {
回归!Vue.prototype.$isServer!window . navigator . user agent . match(/Firefox/I);
};
const mousewheelEventName=isFirefox()?DOM mouse scroll“:”mouse wheel”;
不过这里我个人感觉不是特别严谨。感觉mdn上给出的判断比较合理。下面是贴出的代码。
//获取鼠标滚轮事件
const mouseWheel=()=
document.createElement(div )中的 onwheel
?Wheel //各厂商的较高版本浏览器支持 Wheel
:document.onmousewheel!==未定义
?鼠标滚轮“//Webkit和IE必须支持“鼠标滚轮”
: DOM mouse scroll ;firefox的较低版本
在自己基于自己的博客开发的图片组件中,我只是用了上述的写法,做了一个测试,效果还不错。
这里学到的主要是鼠标滚轮事件的优化,也就是上面提到的方法结合window.requestAnimationFrame,真的感觉很棒,让滚轮事件的每一次触发都结合当前屏幕的实时刷新率,使其效果达到最佳。
具体代码实现如下:
this . mousewheelhandler=raft throttle((e)={
/**
*注:wheelDelta和detail都是用来判断滚轮是向上滑动还是向下滑动的,但不同浏览器的判断条件不同,所以都需要称为判断。
*注意:使用window.requestAnimationFrame时,不能使用transition。
*/
const delta=e.wheelDelta?e . wheel delta:-e . detail;
if (delta 0) {
this . transform . enable transition=false;
this . zoom in(false);
}否则{
this . transform . enable transition=false;
this . zoom out(false);
}
});
//on方法是由elementui封装的coriolis addEventListener方法。
关于(这个。$isServer)(document,mouseWheel(),this . mousewheelhandler);
导出函数raft throttle(fn){
//这里锁定的是一个锁,只限制当前页面的一个requestAnimationFrame事件。
let locked=false
返回函数(.args) {
如果(锁定)返回;
locked=true
window . requestanimationframe(_={
fn.apply(this,args);
locked=false
});
};
}
基于键盘输入的缩放
基于键盘的缩放是监视键盘输入,并处理上下左右四个方向键,esc键和空格。直接粘贴代码就可以了。很简单。
这个。_keyDownHandler=e={
//防止事件向上传播,只在当前标记中使用
e .停止传播();
const key code=e . key code;
开关(键码){
//ESC
案例27:
this . hide();
打破;
//空格
案例32:
this . toggle mode();
打破;
//左箭头
案例37:
this . prev();
打破;
//向上箭头
案例38:
this . handle actions( zoom in );
打破;
//右箭头
案例39:
this . next();
打破;
//向下箭头
案例40:
this . handle actions( zoom out );
打破;
}
};
隐藏预览功能
隐藏的形式主要有三种,一种是按esc键,一种是点击蒙版而不是图片的位置,最后一种是点击按钮。它们的实现完全相同。在这里,我不明白为什么方法要作为prop传递然后执行,为什么不能作为emit处理。实现还是很简单的,就不贴了。
基于鼠标按下事件的拖放功能
mousedown事件的拖放功能主要依赖于vue支持的mousedown事件。同时,mousemove事件被绑定到mousedown事件以获得移动的X和Y轴的位置,该位置被提供给transform上的offsetX和offsetY属性以设置imageStyle的margin-left和margin-top属性。其实挺简单的。
具体代码实现如下:
handleMouseDown(e) {
if (this.loading e.button!==0)返回;
const { offsetX,offsetY }=this.transform
const startX=e.pageX
const startY=e.pageY
这个。_ drag handler=raft throttle(ev={
this . transform . offsetX=offsetX ev . pagex-startX;
this . transform . offsetY=offsetY ev . pagey-startY;
});
关于(文档,鼠标移动,这个。_ drag handler);
在(文档中, mouseup ,ev={
关(文档,鼠标移动,这个。_ drag handler);
});
//当事件处理完成后,该事件将被取消,不会再发生。
e . prevent default();
}
关于elementui管理事件的一些解读
elementui的事件管理是通过一个科林蒂安的方法来进行的,也就是src/utils/dom.js下的on和off方法,这两个方法写的很巧妙,通过判断是否是服务器渲染的代码就可以返回不同的事件绑定代码。具体实现如下:
export const on=function(is server){
如果(!is server document . addevent listener){
返回函数(元素、事件、句柄){
if(元素事件){
element.addEventListener(事件,句柄,false)
}
}
}否则{
返回函数(元素、事件、句柄){
if(元素事件){
element . attach event(` on $ { event } `,handle)
}
}
}
}
export const off=function(is server){
如果(!is server document . addevent listener){
返回函数(元素、事件、句柄){
if(元素事件){
element.removeEventListener(事件,句柄,false)
}
}
}否则{
返回函数(元素、事件、句柄){
if(元素事件){
element . detachevent(` on $ { event } `,handle)
}
}
}
}
虽然这对于绑定事件来说会变得非常简单,但是还有一个关键的问题就是我无法知道我的当前事件是否已经被消除,所以我很想知道是否有一个好的事件管理机制来处理这些创建的事件,然后在使用这些事件的时候不需要去处置这些事件,这是我后面需要探索的。
总结
element-ui的图片组件的源代码读取是我在它的每一步操作中仔细分析的第一个组件。虽然看过两个比较复杂的模块的源代码,table和tree的实现,但是这次没有仔细分析每一步和页面布局设计。在这次阅读中,我学会了如何优化频繁交互的处理方式,以及防抖和节流的使用。
关于elementui下图片组件的使用,本文到此为止。有关元素图像组件的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。