木灵鱼儿
阅读:1670
vue 通过js触发element ui的图片预览组件
element ui的图片预览组件并没有单独提供出来,默认是在image组件里面一起使用,但是有的时候,我们需要点击某一个自定义按钮,然后弹出图片预览,但是,又不需要使用el-image组件,于是乎,有了这篇笔记。
首先思路并不是我的,我也是看了下同事,他网上找的教程,然后我看了下,在掘金找到一篇文章:《Vue中使用element-ui的内置组件实现图片预览全局调用功能》;深受启发,于是也记下自己的笔记。
首先思路是两个:
- element ui的图片预览本身是一个vue组件
- vue.extend构造器将vue组件通过js的方式构造出来,new出来的这个构造器,他的属性为组件的属性以及其他(其他就是我也不明白)
那么就很简单了,我们将图片预览组件引入,通过构造器构造出来,拿到构造后的实例,实例的属性就是组件的配置,我们再把组件的show方法挂载的全局vue的原型上,不就可以在任何地方通过this.xxx
方法触发了吗?
当然,也没有那么简单,还是有点曲折,我们一一解决。
引入图片预览组件
组件的路径大概是:element-ui/packages/image/src/image-viewer
我们查看这个组件,可以看到,他其实是没有v-if指令的,这就导致这个组件一使用,就在html上显示了。
查看一下element的image组件,可以看到,是在外面做了v-if
所以,我们也需要这么做,这样的话就不能直接引入再通过构造器构造了,我们需要一个中间层,用于v-if管理。
所以我们需要创建一个vue组件:Preview.vue
<template>
<transition name="viewer-fade">
<ElImageViewer v-if="show" :urlList="urlList"
:on-close="closeViewer" />
</transition>
</template>
<script>
import ElImageViewer from "element-ui/packages/image/src/image-viewer";
export default {
props: {
urlList: {
type: Array,
default: () => [],
},
},
data() {
return {
show: false,
};
},
methods: {
closeViewer() {
this.show = false;
},
},
components: {
ElImageViewer,
},
};
</script>
组件里面目前用了两个属性一个方法,show用于控制是否显示关闭,closeViewer方法是一个回调,当用户点击了关闭后会触发这个回调方法,我们就需要将show设置为false。
urlList就是图片的数组了,由于图片可以是多个,所以用的数组。
此时中间管理层我们已经做好了,下面开始构造他
vue.enxted构造组件
构造器我们需要使用到Vue实例,而且我们希望的是,这个组件可以像普通组件一样,import引入,然后vue.use()
激活,所以我们要手动先写一个组件的js文件,配合use方法使用。
use方法接收一个参数,这个参数可以是对象,也可以是函数,如果是对象的话,该对象就必须提供一个install的属性,这个属性是一个方法,接收一个参数,就是Vue实例。
因为我们需要import引入刚刚创建的中间管理层组件,所以只能使用对象的形式。
代码如下:
preview.js:
import PreviewItem from "./Preview.vue";
const Preview = {};
Preview.install = function (Vue) {
const PreviewConstructor = Vue.extend(PreviewItem);
const instance = new PreviewConstructor();
instance.$mount(document.createElement("div"));
document.body.appendChild(instance.$el);
Vue.prototype.$showImg = function (urlList=[]) {
instance.urlList = urlList
instance.show = true;
}
}
export default Preview;
大概原理:
引入管理中间件组件,创建一个对象Preview,给对象添加install方法,接收到vue实例对象。
通过vue实例对象的extend构造器,将管理中间件组件作为参数传入,此时会return出一个vue组件的构造函数,我们new出这个构造函数。
此时dom并没有生成,我们需要通过这个new出的构造函数的$mount方法,将它挂载到元素上,但是此时我们并不需要他真实挂载到网页的某个地方,所以我们创建一个div元素,将组件挂载到div中,这样他就不会出现在网页中去。
然后我们再通过instance组件的构造函数实例的$el属性,拿到dom,在将它传入网页的body中去。
此时我们的元素v-if为false,所以并不会显示。
但是,我们还没有办法触发让他显示,但是我们已知了两个条件:
- 有全局的Vue对象了
- instance实例已经可以通过他控制组件的属性
所以我们可以创建一个方法,然后挂载到Vue的原型上,方法接收一个数组,也就是图片数组,并且在方法触发时,控制instance的show属性为true。
然后我们导出这个Preview对象;
main.js 激活
在main.js文件中
import Preview from "./preview.js";
Vue.use(Preview);
这样就行了, 我们可以在项目的vue组件里面,使用:
this.$showImg(["xxx"])
来触发图片预览组件。
谈谈动画
element 原装组件触发的图片预览弹窗,第一次显示的时候会有动画的,关闭的时候就没有动画了,但是我按照图片组件的那种引入方式写,不知道为什么,就是不会有动画出现。
我想了下,可能是因为预览组件transition元素里面并没有使用v-if或者v-show导致的,但是原装里面没有使用,为啥会有动画????
所以很无奈,我只能在管理中间层组件那使用了一个transition元素包裹,这样效果就和官方的保持了一致,但是我也不知道为什么官方的可以有动画,所以,等待以后明白了再说吧,或者有大佬点醒下我。
关于预览组件点击遮罩层关闭的问题
其实官方组件已经考虑到这个问题了,但是并没有使用,可能是体验不好把!
打开图片预览组件,我们找到prop属性,里面有这个一个配置:
maskClosable: {
type: Boolean,
default: true,
},
这个属性字面意思是mask元素的close开关,默认是true,其实表示的是默认点击mask遮罩层的时候,是可以关闭预览弹窗的。
因为我们在去methods里面找handleMaskClick
方法,这个方法是绑定在mask元素上的:
<div class="el-image-viewer__mask" @click.self="handleMaskClick"></div>
方法内容为:
handleMaskClick() {
if (this.maskClosable) {
this.hide();
}
},
hide() {
this.deviceSupportUninstall();
this.onClose();
},
可以看到,handleMaskClick会判断maskClosable是否为true,如果为true,那么就会触发hide方法,hide则会在关闭一些事件监听后,触发onClose,这个是由prop接收的回调。
那么为什么会有人认为element ui的图片预览组件不支持点击遮罩层关闭呢?
我看了下框架的更新日志,这个点击mask关闭功能是在 2.15.0版本更新的,也就是说在那之前,是没有这个功能的,所以,这是个历史遗留问题,好在,现在都有解决方式了。
issues地址:https://github.com/ElemeFE/element/pull/20652
self修饰符表示事件必须是绑定的这个元素本身触发的才会触发函数,不会被冒泡啥的触发。
所以,我们如果想开关这个功能,就需要在中间层绑定这个属性,并prop接收一个对应的设置。
具体后面看完整代码
一些其他配置
图片预览组件还有一些其他配置:
- zIndex 层级
- onSwitch 当图片切换时的回调,参数为图片的index下标
- initialIndex 首次显示时显示的图片index下标
- appendToBody 是否允许传入body
差不多就是这些,所以,如果想完美一点的配置,我们就应该在管理中间层都要对这些参数进行绑定,并且在prop中加上接收对应属性的配置
完整版管理中间件
<template>
<transition name="viewer-fade">
<ElImageViewer v-if="show" :z-index="zIndex" :initial-index="imageIndex" :urlList="urlList"
:on-close="closeViewer" :on-switch="switchViewer" :appendToBody="appendToBody"
:maskClosable="maskClosable" />
</transition>
</template>
<script>
import ElImageViewer from "element-ui/packages/image/src/image-viewer";
export default {
props: {
urlList: {
type: Array,
default: () => [],
},
zIndex: {
type: Number,
default: 2000,
},
onSwitch: {
type: Function,
default: () => {},
},
onClose: {
type: Function,
default: () => {},
},
initialIndex: {
type: Number,
default: 0,
},
appendToBody: {
type: Boolean,
default: true,
},
maskClosable: {
type: Boolean,
default: true,
},
},
data() {
return {
show: false,
};
},
methods: {
closeViewer() {
this.show = false;
this.onClose();
},
switchViewer(index) {
this.onSwitch(index);
},
},
components: {
ElImageViewer,
},
};
</script>
构造器调整
preview.js:
import PreviewItem from "./Preview.vue";
const Preview = {};
Preview.install = function (Vue) {
const PreviewConstructor = Vue.extend(PreviewItem);
const instance = new PreviewConstructor();
instance.$mount(document.createElement("div"));
document.body.appendChild(instance.$el);
Vue.prototype.$showImg = function (urlList=[],initialIndex=0,onSwitch=()=>{}) {
//在这里加上一些配置
instance.urlList = urlList;
instance.initialIndex = initialIndex;
instance.onSwitch = onSwitch;
instance.show = true;
}
}
export default Preview;
具体的一些用法,可能会有一些自定义,所以这里是一个示例,没有经过测试,主要是同事写好了,我再去改的话有点吃饱了,就记个笔记在这。
如果你在使用中发现了问题,欢迎留言反馈,我会第一时间处理的,所以留言一定要留真实邮箱地址,才能接收到我的回复邮件。
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
vue-i18n 的使用方式
安装vue2版需要安装8.x版本的,9.x的是vue3版本使用上大同小异。vue2安装:yarn add vue-i18n@8vue3安装:yarn add vue-i18n封装官方虽然支持很不错的用法,但是自定义处理是难免的。vue3文件目录结构├─ src │ ├─ language │ │ ├─ lang │ │ │ ├─ en.json │ │ │ └─ zh.json │ │ ├─ core │ │ │ ├─ i18n.ts │ │ │ ├─ customization.ts │ │ │ └─ language.ts │ │ ├─ i...
vue router 一个重定向页面的思路
当项目需要和其他项目进行沟通的时候,往往常见的做法就是,我在a网站点击一个按钮,在链接中携带query参数啥的,然后去访问b网站页面。此时可能会有两种情况:跳转的链接就是b网站的具体链接地址。跳转的链接是b网站的一个跳板,跳板会对参数做一些操作,然后进行重定向。两种做法都各有优势:第一种省事简单,但是如果以后b网站链接层级发生变化,那么就会导致链接不可能,到时候还需要进行修改,很痛苦。第二种的话,我们需要写一个跳板页面,但是通过一些参数要求,甚至自身加上一些逻辑处理,那么他的功能性会更强一些。那么,在vue中,做一个重定向页面,怎么做?思路思路1利用路由守卫,当链接上存在某个参数的时候,...
vue 过滤器 驼峰与短横线相互转换的方法
自己去注册吧,提供的是es6导出的方法//短横线转驼峰 export const dashToHump = function (value) { const textArr = value.split("-"); return textArr.map((item, index) => { if (index === 0) return item.toLowerCase(); return item.slice(0, 1).toUpperCase() + item.slice(1); }) .join("")...
使用vue.draggable拖拽组件遇到的一些问题
资源github:vue.draggable中文文档:vue.draggable中文文档api参考文档:sortablejsvue.draggable是基于sortablejs的vue封装,所有有些api官方并不会有过多的解释,可以去sortablejs查看下拖拽无法触发页面滚动当拖拽的内容大于页面宽高时,页面滚动就是一个必然的需求,但是vue.draggable默认情况并不能触发滚动。官方设置里有一个属性:scroll,如果为true时就能触发滚动,但是默认属性就是true;所以这个配置可以说是无效的。解决方案:cannot set scrollSensitivity19年的时候就有提...

关于 element table多选里面实现单选的偷懒做法
在elment的table多选中增加单选逻辑,这个也不能说产品的问题,单选和多选应该算是比较基础的应用,但是,element并没有对单选做支持。于是我有了一个偷懒思路!前提由于table的一键全选按钮无法进行细致化操作,无法控制点击时选中的数量,只能在选中后的回调里面处理,所以,我的做法是单选时隐藏这个按钮。 selectable方法可以返回布尔值来表示当前格子是否允许勾选或者取消,其实就是禁用的意思。<el-table-column type="selection" :selectable="onSelectable"></el...

关于element el-input 输入的值需要转number的问题
前言经常是一个input表单需要输入数字和小数,那么如果仅仅是要求数据格式,我们可以通过表单校验的方式对输入的值进行限制,具体的做法,我之前就写过文章:《element input表单验证数字类型方法大全》里面有关于数字类型校验的方式,基本涵盖了日常需求。但是,仅仅就只能这样吗???no,如果后端要求你输入的数字,提交给他的时候也必须是数字类型呢?要知道,即便我们做了表单校验,校验它输入的必须是数字格式,但是input本身就是一个string类型的值,即便你设置type="number"也无法改变它值的类型。有人说用.number;其实这个问题之前就聊过了,这个修饰符...
关于element table合并格子的思路
效果图需要将第一个col值相同的格子row进行合并。实现element的表格提供了一个span-method方法,该方法会为每个格子运行一次。比如,有一个3行的表格,每行4个格子,那么span-method就会运行:3*4=12;共计12次。有时候我们并不需要每个格子都运行一次,在上面的需求上,我们只需要每行运行一次就行了,所以我们可以通过span-method的参数中,解构出columnIndex每行每个格子的下标。<script> export default { methods: { spanMethod({columnIndex}) { if(...

.native修饰符 做了什么
估计也就只有我这个憨憨一直以为native会自动将事件传给组件的input那些元素,比如按键事件啊,点击事件啊。然后,我就一直很好奇,他是怎么做到准确绑定的?然而事实上,他就是一次事件的绑定而已。<base-input v-on:focus="onFocus"></base-input>base-input<template> <div class="input-item"> <input type="text"> </div> </t...
实现一个点击自动滚动到指定元素,并让input元素聚焦
效果图思路分析tab切换在vue中,tab的切换只需要改动tab组件的active属性即可,所以,我们只需要对点击的元素,点击后能提供一个它奴属于哪个tab选中项即可。具体就看自己的代码怎么设计,比如html元素可以使用data属性。聚焦聚焦就很简单了,input元素有focus方法,运行就会聚焦。滑动定位利用scrollIntoView方法,可以达到定位的效果,配置属性,就会有动画。element.scrollIntoView({behavior:"smooth"})MDN:Element.scrollIntoView()点击这个元素,从data属性上获取要滚动的元...

分享一个vscode的配置 vue开发用的
安装的插件Atom One Dark Theme 主题Auto Rename Tag 头尾标签自动修改,改一个改一双Beautify 格式化Bracket Pair Colorizer 对象括号选择有颜色表示范围Highlight Matching Tag 选择标签自动高亮对应的结尾标签Material Icon Theme 图标Path Intellisense 路径提示,只能相对路径Version Lens 版本提示,安装完可以在打开package.json文件,在右上角有一个v按钮,点击可以查看最新版本,更新狂魔必备Vetur 用了vue还有不装这个的?Color Hig...