精华内容
下载资源
问答
  • 失焦
    2022-01-06 11:11:42

    div的失焦事件


    div本身不具有失焦事件,在vue中添加:tabIndex=“1” @blur="fn()"即可

    更多相关内容
  • 主要介绍了javascript实现搜索框点击文字消失失焦时文本出现的效果,示例代码如下,大家可以看看
  • 主要介绍了详解小程序input框失焦事件在提交事件前的处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 图像退化模型在频率域的表示如下 其中 S 表示退化 ( 模糊 ) 图像频谱 H表示角点扩散功能 (PSF) 的频谱响应 U 表示原真实图像的频谱 N表示叠加的频谱噪声 圆形的 PSF因为只有一个半径参数 R是一个非常好的失焦畸变...
  • 失焦事件: 代码如下: $(“#id”).blur(function(){ }); 但是文本改变事件却不能这样写: 代码如下: $(“#id”).change(function(){ }); 文本改变事件可以这样写,propertychange是属性改变时触发事件 代码如下: $...
  • 首先用css的伪类:focus可以改变。...input type=”text” /></dd> <dt>Password: <dt> <dd><input type=”password” /></dd> <dt>Textarea: <dt> <dd><textarea></textarea>...
  • Android EditText(失焦+焦点)+登录界面
  • 失焦图像还原,盲目反卷积迭代处理图像,参考交流
  • 今天做项目中,一个input元素中同时添加了 失焦方法 和 失焦校验。今天发现偶发的会仅触发其中一个。和大佬同事讨论许久,发现可能是 二者其一 被另外一个冲掉了。如果触发了失焦校验,那么失焦方法就会失效。(偶发...

    问题描述:

    今天做项目中,一个input元素中同时添加了 失焦方法 和 失焦校验。今天发现偶发的会仅触发其中一个。和大佬同事讨论许久,发现可能是 二者其一 被另外一个冲掉了。

    如果触发了失焦校验,那么失焦方法就会失效。(偶发性)

     <input
        name="itsAInput"
        nz-input
        [(ngModel)]="aValue"
        (blur)="onPatientIdBlur()"
        Validator
        [ngModelOptions]="{ updateOn: 'blur' }"
      />

    原因分析:

    由于JavaScript为单线程,同一时间只能执行处理一个事件。


    解决方案:

    解决方案1:setTimeOut 让另外一个失焦进入第二次的事件循环

        onPatientIdBlur() {
                // 校验失焦 和 输入框失焦 单线程会冲突 使用settimeout事件循环 
                setTimeout(() => {                
                    console.log("fuck");
                }, 1);
            
        }


    解决方案2:将click事件改为mousedown,让其优先于blur事件执行

    mousedown事件:当鼠标指针移动到元素上方,并按下鼠标按键时,会发生mousedown事件。

    mouseup事件:当在元素上放松鼠标按钮时,会发生mouseup事件。

    注意:
    (1)mousedown与click 事件不同,mousedown事件仅需要按键被按下,而不需要松开即可发生。

    (2)mouseup与click事件不同,mouseup事件仅需要放松按钮。当鼠标指针位于元素上方时,放松鼠标按钮就会触发该事件。
     

    资料:

    Js EventLoop

    并发模型与事件循环 - JavaScript | MDNJavaScript 有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其它语言中的模型截然不同,比如 C 和 Java。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop

    2022/7/8 

    获取debounce也可以达到setTimeout效果 

     

    展开全文
  • clock_fused.zip_失焦

    2022-07-15 04:01:40
    将两幅不同位置失焦的图片融合成一幅无失焦的图
  • 图像失焦模糊分析。当成像物体不在相机的焦平面上时,会拍摄得到一张失焦模糊图像,隐藏了物体的部分细节。 图像模糊可以理解为清晰图像和模糊核进行二维卷积,模糊核通常有高斯型和圆盘型两种形态。根据其在图像...
  • 一、景深和失焦模糊 1.1 失焦模糊的原理 说起失焦的模糊,我们就要回忆一下我的另外一篇文章31. 镜头、曝光,以及对焦(上),https://zhuanlan.zhihu.com/p/97542357)中的内容。 我们看到,当物体位于镜头的对焦...

    点击上方“3D视觉工坊”,选择“星标”

    干货第一时间送达

    到目前为止,我已经介绍了两种用于将模糊的图像变清晰的技术,它们分别是:

    • 去卷积:怎么把模糊的图像变清晰?,我介绍了用它来解决镜头光学系统本身导致的模糊

    • 盲去卷积 - 更加实用的图像去模糊方法,https://zhuanlan.zhihu.com/p/105500403,我介绍了用它来解决相机抖动导致的运动模糊

    我注意到了文章下面一些朋友的评论,比如

    @sfezzzz 的观点就很有代表性

    是的,我们今天就来看看另外一种图像模糊——即失焦导致的图像模糊——应该怎么样处理。

    我今天将要介绍的技术,不仅能够从单张图像中同时获取到全焦图像(全焦图像的定义请参考33. 摄影-怎样对焦才能让不同距离的物体都拍摄清晰?,https://zhuanlan.zhihu.com/p/99637413),还能顺便获取到场景的景深图。

    通过单张图像同时获取景深图和全焦图像

    我想你已经被这个动图吸引了吧,那么让我们先从失焦模糊的原理讲起吧。

    一、景深和失焦模糊

    1.1 失焦模糊的原理

    说起失焦的模糊,我们就要回忆一下我的另外一篇文章31. 镜头、曝光,以及对焦(上),https://zhuanlan.zhihu.com/p/97542357)中的内容。

    我们看到,当物体位于镜头的对焦面上时,物体上的一点发出的光可以通过镜头在像平面上呈现成一个像点:

    但对于不在对焦面上的点,则会形成由很多个像点构成的弥散圆:

    弥散圆的大小依赖于当前的对焦距离、光圈值、焦距、传感器的像素尺寸等一系列因素。

    从这里你就可以看出,失焦带来的模糊和之前介绍的运动模糊以及镜头本身的不完美导致的模糊是完全不同的。之前介绍的模糊对画面中的每个点都是均匀的,即每个像素对应的PSF都一致。而现在这种由于失焦带来的模糊则是对画面中每个点都不一致的,这是它们的第一个不同。

    另外一个不同之处则在于PSF的形状,我们之前讲过衍射极限PSF的形状是这样的:

    而相机的抖动PSF则是不规则的,大概长这样:

    那么失焦的PSF呢?失焦的PSF其实和镜头的光圈形状高度相关,这里有个动图可以说明:

    因此,失焦的PSF相对更加容易测量一些。

    1.2 失焦模糊时PSF的测量

    当镜头的像距、焦距固定好后,对焦平面也固定了。此时我们可以比较容易的测量出物体偏离对焦平面后的PSF。我们还是可以采用35. 去卷积:怎么把模糊的图像变清晰?中的思想,只不过现在要求的是卷积核c,这就要求我们提前获取到失焦的图像x和清晰的图像b

    下面是实施此方法的步骤思想:

    1. 固定好相机的像距和焦距,这样我们就锁定了对焦平面

    2. 将平面的物体,例如一个印有特定曲线的标定板放置在对焦平面上并拍照,我们将的到清晰的像 x

    3. 接着,移动标定板并拍照,我们将得到模糊的像 b

    反向使用用去卷积的思想,就可以得到卷积核c。当然实际操作时,通常还需要加入一定的正则化,来限制卷积核中的噪声。

    总之,采用类似的思想,我们是比较容易通过提前测量的方式获取到在特定对焦距离情况下的卷积核簇的形状和尺寸的。

    此时,聪明的你一定想到如何获取全焦图像了,我猜你是这样想的:

    1. 先提前标定好各个失焦距离的PSF

    2. 对输入的模糊图像每一个点,用这些不同的PSF分别做去卷积操作,根据输出的图像的清晰程度,判断哪个是这个点对应的正确尺寸的PSF

    3. 对所有的局部区域选择正确的PSF进行去卷积,想得到的所有图像块合成起来,就可以得到全焦图像。

    4. 局部区域对应的PSF的尺寸则形成了场景的景深图

    我一开始也和你想的一样,然而以色列理工大学的Anat Levin教授在多年前就指出,这种简单的想法有两个巨大的障碍:

    1. 即便知道了接近正确的卷积核的尺寸和形状,对应失焦类型的卷积核,也很难通过传统的去卷积方法得到清晰的图像。比如采用经典的Richardson-Lucy方法处理失焦图像很多时候会产生强烈的振铃效应:

    2. 用不同尺度的卷积核去卷积后,很多时候很难分清楚哪个更清晰, 特别是比正确尺寸略小的卷积核的去卷积结果很难和正确尺寸的结果相区分, 这导致我们很难为每个区域都选择出正确的卷积核。

    这会导致什么后果呢?看看下面这张输入图像

    我们采用上面所讲的方法提前标定得到了不同失焦距离的PSF,然后进行局部去卷积,最终得到的全焦图像张这个样子。你可以观察到后面的啤酒瓶都变清晰了,但是前面的食品袋、易拉罐则出现了明显的振铃现象。

    那么,如何解决上面这两个问题呢?我们现在才进入今天文章的核心

    二、把失焦模糊的图像变清晰

    今天给大家介绍的是以色列理工大学的Anat Levin教授的经典论文

    Levin et al., “Image and depth from a conventional camera with a coded aperture,” SIGGRAPH 2007.

    在这篇论文中,作者针对性的用两种技术来解决了上面提到的两大问题。我们一一介绍。

    2.1 利用自然图像的统计特征来进行更好的去卷积

    在35. 去卷积:怎么把模糊的图像变清晰?和36. 盲去卷积 - 更加实用的图像去模糊方法,https://zhuanlan.zhihu.com/p/105500403中,我讲过去卷积其实是一个病态问题,有多种组合都可以产生同样的结果。比如下面两种不同的图像和同样的卷积核卷积后都可以得到一致的模糊图像。但其实只有第一种图像才是我们所需要的。

    作者认为,我们可以利用自然图像和非自然的图像的差异作为先验知识,从这些多种组合里面挑选出最佳的结果。

    自然图像的特殊之处就是其梯度是稀疏的,我在36. 盲去卷积 - 更加实用的图像去模糊方法,https://zhuanlan.zhihu.com/p/105500403里面讲过,自然图像的梯度符合重尾分布。但在当前我们这篇文章里面,Levin认为只需要用到梯度的稀疏性即可,下图是示意图

    于是Levin的去卷积思想可以用下图表示

    事实上,我在35. 去卷积:怎么把模糊的图像变清晰?讲过维纳滤波也可以等效于空域中的下面的表示:

    这里维纳滤波的正则项是梯度的平方,也是希望惩罚过大的梯度。其实平方梯度和作为惩罚项,相当于一种高斯先验,即假设图像中有很多小的梯度均匀的分布在画面中的各个地方——仔细想想,这其实符合白噪声的分布。所以维纳滤波才会有比较强的去噪作用,因为正则项惩罚了噪声。

    但Levin的正则项则是希望去卷积后画面中的梯度更加稀疏,于是采用了下面这样的形式:

    让我们来比较一下几种去卷积方法的效果


    可以看到利用稀疏梯度的先验信息确实可以得到更好的结果。

    2.2 利用编码光圈来提升不同尺度的卷积核之间的区分度

    如果说,上面对去卷积的正则项作出的改进还是我们之前所讲的非盲去卷积知识的自然延续的话,那么作者解决第二个问题——即增强不同尺度卷积核去卷积结果的可区分度——的方法就真的是让人大开眼界了。

    作者用硬纸板制作了一个小小的掩模,放置在镜头后面。

    那么这个Mask有什么效果呢?很显然,根据我们第一节所讲的,它会改变点光源的成像,因此每个尺度的PSF也就不一样了。

    这个时候,我们再用不同尺度的卷积核去去卷积,可以很明显看到编码光圈的去卷积结果使得我们更容易区分出正确的尺度和错误的尺度了,因为对于编码光圈,不管是偏大的卷积核还是偏小的卷积核,在去卷积后都会出现振铃效应,而正确尺寸的卷积核则不会。

    2.3 完整的过程

    有了前面所讲的两点作为基础,作者就进一步解释了如何来获取全焦图像。

    1. 提前标定好不同尺度的编码光圈卷积核 

    2. 对每个像素i,选择一个局部窗口  ,对应的图像为 

    3. 对这个局部窗口,用不同尺度的卷积核进行去卷积,得到局部图像 

    4. 第k个卷积核对应的卷积误差为 

    5. 我们要挑选的是误差最小的卷积核,于是选出的卷积核编号为 

    6. 所以对像素i,其对应的清晰图像为  , 而对应的相对深度可以认为是 

    7. 由于弱纹理,无纹理区域的初始估计不够好,作者还对深度图做进一步优化(不是本文重点,这里我就略过了)

    这个过程可以用下图来总结

    对每个像素块重复上述过程,将所有像素块的去卷积结果拼接起来,就可以得到一幅全焦图像了,而所有像素对应的  则构成了深度图。

    三、效果展示

    下面是作者在演示PPT中的效果展示,我们来欣赏一下。

    3.1 获取全焦图像

    3.2 获取相对景深图

    3.3 先拍照后对焦

    还可以像光场相机(参看34. 光场--捕获场景中所有的光线,https://zhuanlan.zhihu.com/p/100610848))一样实现先拍照后对焦效果

    3.4 多视角摄影

    有了深度图,作者甚至利用视差原理展示了多视角摄影的效果,见下图:

    四、进一步的原理分析

    看到这里,一阵激动之后,你可能突然觉得有哪里不对啊。凭什么说编码光圈就比传统光圈在各个尺度去卷积时区分度更好啊?

    我们再回顾一下两个光圈的样子:

    可以看到,传统光圈的卷积核通光量更多,产生的画面更模糊,也就是说很多信号频谱都被过滤了。而编码光圈的通光量更少,产生的画面稍微没有那么模糊,所成图像有更多的信号频谱。

    如果把滤波器看做是一维的,我们可以用下图来展示两种光圈在频域上的区别,这里展示了两个不同尺度的两种滤波器,分布对应着编码光圈和传统光圈。可以看到编码光圈的频谱有更多的能量为0的点,另外整体的能量分布更广。

    先来看看不同尺度的编码光圈对图像信号的影响:

    当选择了不正确尺度的卷积核进行去卷积时,由于模糊图像的0点和卷积核频谱上0点的位置不一致,因此去卷积的结果会有明显的振铃效应。因此,不管是从肉眼上观察,还是通过振铃效应导致的过大的卷积误差,我们都很容易判断哪个是正确尺度的卷积核。

    再看看传统的光圈,传统光圈的频谱没有那么多0点,因此即便是错误尺度的卷积核,在去卷积时也没有明显的振铃效应。不同尺度结果之间的区分也不明显。

    以上就是关键核心思想,作者通过构造特殊的通光形态使得光圈频谱具有较多的0点,从而使得用不同尺度卷积核去卷积的结果更容易区分。作者还比较了不同形态的编码光圈的可判别性,并与传统光圈做了对比。从下图可以看到,传统光圈的可判别性确实不够强,而作者最终选择的形态则具有很强的可判别性。

    五、总结

    今天给大家介绍了一种可以通过处理失焦模糊的照片同时获取到场景的景深图和全焦图像的技术。这里面的两个关键点是

    1. 当卷积核是失焦卷积核时,利用稀疏的梯度先验信息进行去卷积,可以得到更清晰的图像。

    2. 只需要在传统的相机上加一点点小小的改变就能够实现的编码光圈技术,使得不同尺度之间的去卷积结果的区分更加容易。作者专门提到这里面增加的成本仅仅1美元左右。

    从今天的文章你可以看到,计算摄影学不仅仅是软件的事情,有的时候也会涉及到一些必要的硬件。我之后还会再更多的文章里面展示这一点。

    希望这一篇文章给你带来了新的想法,别忘了给我点赞哦!

    最后的最后,再考考屏幕面前的你一个小问题,大家可以踊跃发言,留言区见!

    我前面讲过点光源通过光圈后所成的像跟光圈的形状是一致的,那么下面这个传统光圈,它的PSF为何不是中间这张图的样子,而是右边这个样子呢?中间的黑色像素是怎么来的?如果你不清楚的话,可以参考下我之前的文章:去卷积:怎么把模糊的图像变清晰?

    六、参考资料

    1. CMU 2017 Fall Computational Photography Course 15-463, Lecture 18 http://graphics.cs.cmu.edu/courses/15-463/2017_fall/lectures/lecture18.pptx)

    2. Levin et al., “Image and depth from a conventional camera with a coded aperture,” SIGGRAPH 2007., Paper and Slides from https://groups.csail.mit.edu/graphics/CodedAperture/

    本文仅做学术分享,如有侵权,请联系删文。

    推荐阅读:

    重磅!3DCVer-学术论文写作投稿 交流群已成立

    扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。

    同时也可申请加入我们的细分方向交流群,目前主要有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。

    ▲长按加微信群或投稿

    ▲长按关注公众号

    3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近1000+星球成员为创造更好的AI世界共同进步,知识星球入口:

    学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

     圈里有高质量教程资料、可答疑解惑、助你高效解决问题

    展开全文
  • Input输入框的失焦

    千次阅读 2020-12-02 10:02:16
    其中遇到一个棘手的问题,在输入框失去焦点时,下拉选项框需要隐藏, ... 解决思路: =>...=> 在下拉选项区域内做操作时,... 输入框的失焦是在鼠标onmousedown事件执行时浏览器的默认行为 => 给下拉选项区域加上

    最近遇到一个需求:需要点击输入框后,出现下拉选项,且下拉选项的内容以树结构展示,如图
    在这里插入图片描述
    其中遇到一个棘手的问题,在输入框失去焦点时,下拉选项框需要隐藏,
    这意味着当我准备点击树节点时,整个下拉选项框就被隐藏了,
    所以虽然视觉效果上我点击了节点,但实际上我一直未曾真正点击到。

    解决思路
    => 在点击节点时,需要保证输入框不会失去焦点
    => 在下拉选项区域内做操作时,输入框不会失去焦点
    => 输入框的失焦是在鼠标onmousedown事件执行时浏览器的默认行为
    => 给下拉选项区域加上onmousedown事件,并阻止默认行为,代码如下

    this.$refs.treeGroup.onmousedown = function (e) {
      if (e && e.preventDefault) {
        // 现代浏览器阻止默认事件
        e.preventDefault()
      } else {
        // IE阻止默认事件
        window.event.returnValue = false
      }
      return false
    }
    

    完整代码,仅供学习参考

    <!-- 基于 vue.js 2.0 + element-ui 2.14.x -->
    <template>
      <div class="select-tree">
        <v-input
          class="search"
          v-model="filterText"
          :placeholder="placeholder"
          :width="width"
          :suffix-icon="showTree ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"
          @focus="onFocus"
          @blur="onBlur"
          @clear="clear"
        />
        <div class="tree-group" v-show="showTree" ref="treeGroup">
          <div class="tree-group__box" v-show="treeData.length !== 0">
            <button-tree
              ref="buttonTree"
              class="button-tree"
              :key="key"
              :data="treeData"
              :defaultProps="treeProps"
              :filterText="filterText"
              :highlightCurrent="highlightCurrent"
              :filterNodeMethod="filterNodeMethod"
              :expand-on-click-node="false"
              @nodeClick="nodeClick"
            />
          </div>
          <div v-show="treeData.length === 0" class="tree-group__box is-empty">暂无数据</div>
        </div>
      </div>
    </template>
    
    <script>
    import { ButtonTree } from 'components/bussiness'
    
    export default {
      name: 'selectTree',
      components: {
        ButtonTree
      },
      props: {
        // 选中项的值,支持`.sync`
        value: {
          type: String,
          require: true
        },
        placeholder: {
          type: String,
          default: '请输入'
        },
        width: {
          type: Number,
          default: 182
        },
        treeData: {
          type: Array,
          default: () => {
            return []
          }
        },
        treeProps: {
          type: Object,
          default: () => {
            return {}
          }
        },
        expandOnClickNode: {
          type: Boolean,
          default: true
        },
        highlightCurrent: {
          type: Boolean,
          default: true
        },
        filterNodeMethod: {
          type: Function
        }
      },
      data () {
        return {
          showTree: false,
          filterText: '',
          result: '',
          model: this.value,
          key: 0
        }
      },
      watch: {
        model (newValue) {
          console.log(newValue, 'newValue')
          // 返回当前所选值的value数组
          this.$emit('update:value', newValue)
        },
        showTree (val) {
          if (val) { return }
          // 树弹框隐藏时触发
          if (this.model === '') {
            this.filterText = ''
          } else {
            this.recursGetData(this.model, this.treeData)
            this.filterText = this.result[this.treeProps.label]
            this.result = null
          }
        }
      },
    
      mounted () {
        this.$refs.treeGroup.onmousedown = function (e) {
          if (e && e.preventDefault) {
            // 现代浏览器阻止默认事件
            e.preventDefault()
          } else {
            // IE阻止默认事件
            window.event.returnValue = false
          }
          return false
        }
      },
      methods: {
        // input 输入框获取焦点
        onFocus () {
          this.filterText = ''
          setTimeout(() => {
            this.showTree = true
          }, 100)
          this.$emit('focus', event)
        },
        // input 输入框失去焦点
        onBlur () {
          this.showTree = false
          this.$emit('blur', event)
        },
        clear () {
          // this.form.orgId = ''
          this.model = ''
          this.key += 1
          this.$emit('clear')
        },
        nodeClick (data, node, nodeVue) {
          this.filterText = data[this.treeProps.label]
          // this.form.orgId = data[this.treeProps.id]
          this.model = data[this.treeProps.id]
          this.$emit('nodeClick', data, node, nodeVue)
        },
    
        /* 计算 */
        // 通过值递归获取数据
        recursGetData (id, arr) {
          console.log(id, arr, this.treeProps, 'id, arr')
          arr.map((d, i) => {
            if (id === d[this.treeProps.id]) {
              this.result = d
            } else {
              if (d[this.treeProps.children].length !== 0) {
                this.recursGetData(id, d[this.treeProps.children])
              }
            }
          })
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .select-tree {
      position: relative;
      .search {
        // ::v-deep .el-input__inner {
        //   border-radius:18px;
        //   background: rgba(144,166,186, 0.1);
        //   box-shadow: inset 4px 1px 8px 0px rgba(95,122,155,0.1);
        //   border: none;
        // }
        ::v-deep .el-input__suffix {
          line-height: 32px;
        }
      }
      .tree-group {
        &::before {
          content: '';
          border: 1px solid;
          border-color: #E4E7ED transparent transparent #E4E7ED;
          background-color: #fff;
          width: 6px;
          height: 6px;
          position: absolute;
          top: 2px;
          left: 36px;
          z-index: 4;
          transform: rotateZ(45deg)
        }
        position: absolute;
        left: 0;
        top: 110%;
        z-index: 2;
        .tree-group__box {
          &.is-empty {
            height: auto;
            color: #909399;
            text-align: center;
            padding: 4px 0;
            font-size: 14px;
          }
          /** 不可使用定位,会破坏button-tree组件结构 */
          width: 182px;
          height: 204px;
          border: 1px solid #E4E7ED;
          border-radius: 4px;
          background-color: #FFF;
          box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
          box-sizing: border-box;
          margin: 5px 0;
          padding: 5px 0 0;
        }
      }
    }
    </style>
    
    // button-tree 组件
    
    <template>
      <div class="tree-button-wrapper" id="treeButtonBox">
        <div class="tree-button-box" id="treeButton">
          <el-tree
            ref="elTree"
            :node-key="nodeKey"
            :default-checked-keys="defaultCheckedKeys"
            :data="data"
            :props="defaultProps"
            :filter-node-method="filterNodeMethod"
            :empty-text="emptyText"
            :lazy="lazy"
            :load="loadData"
            :default-expanded-keys="defaultExpandedKeys"
            :default-expand-all="expandAll"
            :expand-on-click-node="expandOnClickNode"
            :accordion="accordion"
            :highlight-current="highlightCurrent"
            :show-checkbox="showCheckbox"
            :check-on-click-node="checkOnClickNode"
            :draggable="draggable"
            :allow-drag="allowDrag"
            :allow-drop="allowDrop"
            :indent="indent"
            @node-click="nodeClick"
            @node-contextmenu="nodeContextMenu"
            @check-change="checkChange"
            @check="check"
            @current-change="currentChange"
            @node-expand="nodeExpand"
            @node-collapse="nodeCollapse"
            @node-drag-start="nodeDragStart"
            @node-drag-enter="nodeDragEnter"
            @node-drag-leave="nodeDragLeave"
            @node-drag-over="nodeDragOver"
            @node-drag-end="nodeDragEnd"
            @node-drop="nodeDrop">
            <template slot-scope="{ node, data }">
              <div class="custom-tree-node">
                <span class="icon" v-if="data.icon" :style="handleBG(data, node)"></span>
                <div class="node-content" ref="nodeContent" @contextmenu.stop.prevent="contentContextMenu(data, node, $event)">
                  <!--传入html-->
                  <div style="display: inline-block;" v-if="data && data.html" v-html="data.value"></div>
                  <!--传入自定义组件-->
                  <component v-else-if="data && data.component" :is="data.componentName" :row="scope.row"></component>
                  <!--传入普通文本-->
                  <div style="display: inline-block;" v-else v-text="data[defaultProps.label]"></div>
                </div>
                <!-- 按钮列表 -->
                <div class="node-button" v-if="showBtnAll(data)">
                  <div class="node-button-icon" @click.stop.prevent="buttonIconClick(data)"><i class="el-icon-more"></i></div>
                  <ul class="node-button-list" v-show="showList(data)">
                    <li
                      v-show="showBtn(data, item)"
                      v-for="item in btnFilterOps"
                      :key="item.value"
                      @click.stop.prevent="buttonClick(data, item)"
                    >
                      {{item.text}}
                    </li>
                    <!-- <li @click.stop="buttonClick(data, 'add')">添加部门</li> -->
                    <!-- <li>添加成员</li>
                    <li>编辑</li>
                    <li>删除</li>
                    <li>移动</li> -->
                  </ul>
                </div>
              </div>
            </template>
          </el-tree>
        </div>
      </div>
    </template>
    <script>
    import { Tree } from 'element-ui'
    import _ from 'lodash'
    // @group 基础组件
    // @title Tree 树形组件
    export default {
      name: 'button-tree',
      components: {
        'el-tree': Tree
      },
      props: {
        // 是否开启防抖
        isDebounce: {
          type: Boolean,
          default: true
        },
        // 用于显示弹框按钮的列表数据
        btnOps: {
          type: Array,
          default: () => {
            // [{ text: '添加部门', value: 'add' }] text 按钮名称 value 按钮编号
            return []
          }
        },
        // 用于树节点过滤
        filterText: {
          type: String,
          default: ''
        },
        // 每个树节点用来作为唯一标识的属性,整棵树应该是唯一的,建议业务方传入这个属性
        nodeKey: {
          type: String,
          default: 'id'
        },
        // 默认勾选的节点的 key 的数组
        defaultCheckedKeys: {
          type: Array
        },
        // 与data配套使用,详情请参考element-ui的tree组件的props介绍:http://element-cn.eleme.io/#/zh-CN/component/tree
        defaultProps: {
          type: Object,
          default: () => {
            return {
              // 必传,唯一性id
              id: 'id',
              // 必传,label 指定节点标签为节点对象的某个属性值 string, function(data, node)
              label: 'label',
              // 必传,children 指定子树为节点对象的某个属性值 string
              children: 'children',
              // disabled 指定节点选择框是否禁用为节点对象的某个属性值 boolean, function(data, node)
              disabled: 'disabled',
              // isLeaf 指定节点是否为叶子节点,仅在指定了 lazy 属性的情况下生效 boolean, function(data, node)
              isLeaf: 'isLeaf',
              // btn 指定节点存在哪些功能按钮,Array<>
              btn: 'btn'
            }
          }
        },
        // 展示数据
        data: {
          type: Array,
          default: () => {
            return []
          }
        },
        // 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏
        filterNodeMethod: {
          type: Function
        },
        // 内容为空的时候展示的文本
        emptyText: {
          type: String,
          default: '暂无数据'
        },
        // 是否懒加载子节点,需与 load 方法结合使用
        lazy: {
          type: Boolean,
          default: false
        },
        // 默认展开的节点的 key 的数组
        defaultExpandedKeys: {
          type: Array
        },
        // 是否默认展开所有节点
        expandAll: {
          type: Boolean,
          default: false
        },
        // 是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
        expandOnClickNode: {
          type: Boolean,
          default: true
        },
        // 是否每次只打开一个同级树节点展开
        accordion: {
          type: Boolean,
          default: false
        },
        // 是否高亮当前选中节点,默认值是 false。
        highlightCurrent: {
          type: Boolean,
          default: false
        },
        // 节点是否可被选择
        showCheckbox: {
          type: Boolean,
          default: false
        },
        // 是否在点击节点的时候选中节点,默认值为 false,即只有在点击复选框时才会选中节点。
        checkOnClickNode: {
          type: Boolean,
          default: false
        },
        // 是否开启拖拽节点功能
        draggable: {
          type: Boolean,
          default: false
        },
        // 判断节点能否被拖拽
        allowDrag: {
          type: Function
        },
        // 拖拽时判定目标节点能否被放置。type 参数有三种情况:'prev'、'inner' 和 'next',分别表示放置在目标节点前、插入至目标节点和放置在目标节点后
        allowDrop: {
          type: Function
        },
        // 相邻级节点间的水平缩进,单位为像素
        indent: {
          type: Number,
          default: 16
        },
        // 自定义树节点的图标
        iconClass: {
          type: String,
          default: 'el-icon-plus'
        }
      },
      data () {
        return {
          // 选中节点的数据,此处选中为点击显示按钮的图标,不要修改该数据
          currentData: {},
          scrollAction: {
            x: undefined,
            y: undefined
          },
          // 当前展开的节点的vnode对象,再 loadData 方法中被使用
          currentNode: null
        }
      },
      computed: {
        btnFilterOps () {
          return this.btnOps.filter(d => {
            // return this.$store.getters.getPermission(d.value)
            /** 测试用代码 */
            return true
            /** end */
          })
        }
      },
      watch: {
        data: {
          handler () {
            // 初始化一次div.node-button元素的位置
            this.$nextTick(() => {
              this.nodeButtonElementMove()
            })
          },
          deep: true,
          immediate: true
        },
        currentNode: {
          handler (val) {
            if (val && val.loading === false) {
              this.$nextTick(() => {
                this.nodeButtonElementMove(val)
              })
              this.currentNode = null
            }
          },
          deep: true
        },
        filterText (val) {
          if (this.isDebounce) {
            this.filter(val)
          } else {
            this.$refs.elTree.filter(val)
          }
        }
      },
      mounted () {
        // 操作dom必须再节点挂载之后,为treeButtonBox元素绑定滚动事件
        this.treeButtonBoxElementBindEvent()
        // 为过滤事件绑定this值
        // this.filter.bind(this)
      },
      methods: {
        // 不可以使用箭头函数,this指向会出现问题
        filter: _.debounce(function (val) {
          console.log('过滤节点触发')
          this.$refs.elTree.filter(val)
        }, 100),
        // 是否显示所有与弹出按钮相关的内容
        showBtnAll (data) {
          return this.btnFilterOps.length !== 0 && data[this.defaultProps.btn] && data[this.defaultProps.btn].length !== 0
        },
        // 是否显示按钮列表
        showList (data) {
          const currentId = this.currentData[this.defaultProps.id]
          const dataId = data[this.defaultProps.id]
          // console.log(currentId, dataId, currentId === dataId)
          return currentId !== undefined && dataId === currentId
        },
        // 是否显示按钮
        showBtn (data, item) {
          // const permission = this.$store.getters.getPermission(item.value)
          // return this.defaultProps.btn && data[this.defaultProps.btn].includes(item.value) && permission
          console.log('是否显示按钮')
          /** 测试用代码 */
          return data[this.defaultProps.btn].includes(item.value)
          /** end */
        },
        // 按钮图标被点击时触发
        buttonIconClick (data) {
          const currentId = this.currentData[this.defaultProps.id]
          const dataId = data[this.defaultProps.id]
          // 若点击节点是当前存储节点,则清除存储节点数据
          if (currentId !== undefined && dataId === currentId) {
            this.currentData = {}
          } else {
            this.currentData = data
          }
        },
        // 为treeButtonBox元素绑定滚动事件
        treeButtonBoxElementBindEvent () {
          const elTreeBox = document.getElementById('treeButtonBox')
          elTreeBox.addEventListener('scroll', () => {
            if (this.scrollAction.x !== undefined && this.scrollAction.x !== elTreeBox.scrollLeft) {
              this.nodeButtonElementMove()
            }
          })
        },
        // 为div.node-button元素设置left值
        nodeButtonElementMove (data) {
          // 若按钮无需显示,避免运行下面的代码消耗性能
          if (!this.btnFilterOps.length) {
            return
          }
          if (data && data[this.defaultProps.btn] && data[this.defaultProps.btn].length === 0) {
            return
          }
          const el = window.document.getElementById('treeButtonBox')
          this.scrollAction.x = el.scrollLeft
          el.querySelectorAll('.node-button').forEach(e => {
            // 注意: 这里的21px是div.node-button元素的高度,因为旋转了90deg,高成了宽
            e.style.left = `${el.scrollLeft + el.clientWidth - 22}px`
          })
        },
        // 按钮被点击时触发
        // @arg (data, value)接收两个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
        // @arg 2.item 按钮对应的对象
        buttonClick (data, item) {
          this.currentData = {}
          this.$emit('buttonClick', data, item)
        },
        loadData (node, resolve) {
          // 加载子树数据的方法,仅当 lazy 属性为true 时生效
          // @arg (node, resolve) 接收两个参数,1. 当前节点 2. 渲染数据的方法
          // console.log(node, resolve, 'reslove')
          this.currentNode = node
          this.$emit('loadData', node, resolve)
        },
        // @vuese
        // 自定义树节点图标的方法
        handleBG (data, node) {
          let expanded = node.expanded
          let bgUrl
          if (!expanded) {
            // 未打开
            bgUrl = `url(${data.icon.iconOpen})`
          } else {
            // 已打开
            bgUrl = `url(${data.icon.iconClose})`
          }
          return {
            backgroundImage: bgUrl
          }
        },
        // @vuese
        // 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点所组成的数组
        // @arg (leafOnly, includeHalfChecked)接收两个参数 1.leafOnly 是否只是叶子节点,默认值为 false
        // @arg 2.includeHalfChecked 是否包含半选节点,默认值为 false
        getCheckedNodes (leafOnly, includeHalfChecked) {
          return this.$refs.elTree.getCheckedNodes(leafOnly, includeHalfChecked)
        },
        // @vuese
        // 设置目前勾选的节点,使用此方法必须设置 node-key 属性
        // @arg (nodes)接收一个参数 1.nodes 接收勾选节点数据的数组
        setCheckedNodes (nodes) {
          this.$refs.elTree.setCheckedNodes(nodes)
        },
        // @vuese
        // 若节点可被选择(即 show-checkbox 为 true),则返回目前被选中的节点的 key 所组成的数组
        // @arg (leafOnly)接收一个参数 1.leafOnly 若为 true 则仅返回被选中的叶子节点的 keys,默认值为 false
        getCheckedKeys (leafOnly) {
          return this.$refs.elTree.getCheckedKeys(leafOnly)
        },
        // @vuese
        // 通过 keys 设置目前勾选的节点,使用此方法必须设置 node-key 属性
        // @arg (keys, leafOnly)接收两个参数 1.keys 勾选节点的 key 的数组
        // @arg 2.leafOnly 若为 true 则仅设置叶子节点的选中状态,默认值为 false
        setCheckedKeys (keys, leafOnly) {
          this.$refs.elTree.setCheckedKeys(keys, leafOnly)
        },
        // @vuese
        // 获取当前被选中节点的 key,使用此方法必须设置 node-key 属性,若没有节点被选中则返回 null
        getCurrentKey () {
          return this.$refs.elTree.getCurrentKey()
        },
        // @vuese
        // 获取当前被选中节点的 data,若没有节点被选中则返回 null
        getCurrentNode () {
          return this.$refs.elTree.getCurrentNode()
        },
        // @vuese
        // 通过 key 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性
        // @arg (key)接收一个参数 1.key 待被选节点的 key,若为 null 则取消当前高亮的节点
        setCurrentKey (key) {
          this.$refs.elTree.setCurrentKey(key)
        },
        // @vuese
        // 通过 node 设置某个节点的当前选中状态,使用此方法必须设置 node-key 属性
        // @arg (node)接收一个参数 1.node 待被选节点的 node
        setCurrentNode (node) {
          this.$refs.elTree.setCurrentNode(node)
        },
        // @vuese
        // 根据 data 或者 key 拿到 Tree 组件中的 node
        // @arg (data)接收一个参数 1.data 要获得 node 的 key 或者 data
        getNode (data) {
          return this.$refs.elTree.getNode(data)
        },
        // @vuese
        // 删除 Tree 中的一个节点,使用此方法必须设置 node-key 属性
        // @arg (data)接收一个参数 1.data 要删除的节点的 data 或者 node
        remove (data) {
          this.$refs.elTree.remove(data)
        },
        // @vuese
        // 为 Tree 中的一个节点追加一个子节点
        // @arg (data, parentNode)接收两个参数 1.data 要增加的节点的 data
        // @arg 2.parentNode 要增加的节点的后一个节点的 data、key 或者 node
        append (data, parentNode) {
          this.$refs.elTree.append(data, parentNode)
        },
        // @vuese
        // 为 Tree 的一个节点的前面增加一个节点
        // @arg (data, refNode)接收两个参数 1.data 要增加的节点的 data
        // @arg 2.refNode 要增加的节点的后一个节点的 data、key 或者 node
        insertBefore (data, refNode) {
          this.$refs.elTree.insertBefore(data, refNode)
        },
        // @vuese
        // 为 Tree 的一个节点的后面增加一个节点
        // @arg (data, refNode)接收两个参数 1.data 要增加的节点的 data
        // @arg 2.refNode 要增加的节点的前一个节点的 data、key 或者 node
        insertAfter (data, refNode) {
          this.$refs.elTree.insertAfter(data, refNode)
        },
        nodeClick (data, node, nodeVue) {
          // 节点被点击时的回调
          // @arg (data, node, nodeVue)接收三个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 2.node 节点对应的 Node
          // @arg 3.nodeVue 节点组件本身
          console.log('节点被点击')
          // 节点被点击后
          this.$emit('nodeClick', data, node, nodeVue)
        },
        nodeContextMenu (event, data, node, nodeVue) {
          // 当某一节点被鼠标右键点击时会触发该事件
          // @arg (event, data, node, nodeVue)接收四个参数 1.event 事件对象
          // @arg 2.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 3.node 节点对应的 Node
          // @arg 4.nodeVue 节点组件本身
          this.$emit('nodeContextMenu', event, data, node, nodeVue)
        },
        contentContextMenu (data, node, event) {
          // 当某一节点内容被鼠标右键点击时会触发该事件
          // @arg (event, data, node)接收三个参数 1.event 事件对象
          // @arg 2.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 3.node 节点对应的 Node
          this.$emit('contentContextMenu', event, data, node)
        },
        checkChange (data, checked, childrenChecked) {
          // 节点选中状态发生变化时的回调
          // @arg (data, checked, childrenChecked)接收三个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 2.checked 节点本身是否被选中
          // @arg 3.childrenChecked 节点的子树中是否有被选中的节点
          this.$emit('checkChange', data, checked, childrenChecked)
        },
        check (data, checkedObj) {
          // 当复选框被点击的时候触发
          // @arg (data, checkedObj)接收两个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 2.checkedObj 树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
          this.$emit('check', data, checkedObj)
        },
        currentChange (data, node) {
          // 当前选中节点变化时触发的事件
          // @arg (data, node)接收两个参数 1.data 当前节点的数据
          // @arg 2.node 当前节点的 Node 对象
          this.$emit('currentChange', data, node)
        },
        nodeExpand (data, node, nodeVue) {
          // 节点被展开时触发的事件
          // @arg (data, node, nodeVue)接收三个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 2.node 节点对应的 Node
          // @arg 3.nodeVue 节点组件本身
          // 当并非懒加载时,节点展开后,且dom挂载完成时,需要将div.node-button元素位置重新计算一次
          if (!this.lazy) {
            this.$nextTick(() => {
              this.nodeButtonElementMove()
            })
          }
          this.$emit('nodeExpand', data, node, nodeVue)
        },
        nodeCollapse (data, node, nodeVue) {
          // 节点被关闭时触发的事件
          // @arg (data, node, nodeVue)接收三个参数 1.data 传递给 data 属性的数组中该节点所对应的对象
          // @arg 2.node 节点对应的 Node
          // @arg 3.nodeVue 节点组件本身
          this.$emit('nodeCollapse', data, node, nodeVue)
        },
        nodeDragStart (node, event) {
          // 节点开始拖拽时触发的事件
          // @arg (node, event)接收两个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.event 事件对象
          this.$emit('nodeCollapse', node, event)
        },
        nodeDragEnter (node, enterNode, event) {
          // 拖拽进入其他节点时触发的事件
          // @arg (node, enterNode, event)接收三个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.enterNode 所进入节点对应的 Node
          // @arg 3.event 事件对象
          this.$emit('nodeDragEnter', node, enterNode, event)
        },
        nodeDragLeave (node, leaveNode, event) {
          // 拖拽离开某个节点时触发的事件
          // @arg (node, leaveNode, event)接收三个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.leaveNode 所离开节点对应的 Node
          // @arg 3.event 事件对象
          this.$emit('nodeDragLeave', node, leaveNode, event)
        },
        nodeDragOver (node, enterNode, event) {
          // 在拖拽节点时触发的事件(类似浏览器的 mouseover 事件)
          // @arg (node, enterNode, event)接收三个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.enterNode 当前进入节点对应的 Node
          // @arg 3.event 事件对象
          this.$emit('nodeDragOver', node, enterNode, event)
        },
        nodeDragEnd (node, overNode, pos, event) {
          // 拖拽结束时(可能未成功)触发的事件
          // @arg (node, overNode, pos, event)接收四个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.overNode 结束拖拽时最后进入的节点(可能为空)
          // @arg 3.pos 被拖拽节点的放置位置(before、after、inner)
          // @arg 4.event 事件对象
          this.$emit('nodeDragEnd', node, overNode, pos, event)
        },
        nodeDrop (node, overNode, pos, event) {
          // 拖拽成功完成时触发的事件
          // @arg (node, overNode, pos, event)接收四个参数 1.node 被拖拽节点对应的 Node
          // @arg 2.overNode 结束拖拽时最后进入的节点
          // @arg 3.pos 被拖拽节点的放置位置(before、after、inner)
          // @arg 4.event 事件对象
          this.$emit('nodeDrop', node, overNode, pos, event)
        }
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style lang="scss" scoped>
     .tree-button-wrapper {
      position: relative; // 该属性不可删除
      height: 100%;
      overflow: auto;
      .tree-button-box {
        min-width: 100%;
        display: inline-block;
        // ::v-deep .el-tree{
        // }
      }
      // .el-tree-node>.el-tree-node__children {
      //   overflow: auto;
      // }
      ::v-deep .el-tree-node__content {
        height: 24px;
        position: relative;
        &:hover{
          z-index: 3;
          .custom-tree-node {
            .node-content {
              opacity: 0.3;
            }
            .node-button {
              .node-button-icon {
                display: inline-block;
              }
            }
          }
        }
        .custom-tree-node {
          display: inline-block;
          height: 24px;
          line-height: 24px;
          .icon {
            margin: 0 4px 0 0;
            width: 22px;
            height: 22px;
            display: inline-block;
            vertical-align: top;
            // vertical-align: ;
            border: 0 none;
            cursor: pointer;
            outline: none;
            background-repeat: no-repeat;
            background-attachment: scroll;
            background-size: contain;
          }
          .node-content {
            display: inline-block;
            padding: 0;
          }
          .node-button {
            // display: none;
            position: absolute;
            top: 0;
            right: 8px;
            width: 18px;
            height: 100%;
            font-size: 20px;
            color: #909399;
            text-align: center;
            .node-button-icon {
              display: none;
              transform: rotateZ(-90deg);
            }
            .node-button-list {
              user-select: none;
              // display: none;
              position: absolute;
              top: 24px;
              right: 8px;
              list-style: none;
              font-size: 14px;
              color: #909399;
              padding: 2px 0px;
              border: 1px solid #e4e7ed;
              border-radius: 4px;
              background-color: #fff;
              box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
              z-index: 1;
              > li {
                padding: 0px 12px;
                &:hover {
                  color: #1B8CF2;
                  background-color: #f5f7fa;
                }
                // text-decoration: underline;
                // list-style: none;
              }
            }
          }
        }
      }
      ::v-deep .el-tree-node__children {
        overflow: inherit;
      }
    }
    </style>
    
    展开全文
  • 点击按钮出现一个dom节点,既可以再点击dom节点关闭也可以点击页面其他部分关闭,点击页面其他...如果想让div也能拥有失焦方法,只能通过其他事件来达到类似onBlur的方法。 1.用防抖实现鼠标移出DIV消失 利...
  • 处理失焦图像

    2021-06-29 19:40:02
    主要是使用图像锐化的方法,处理失焦的图像 * This example program shows how a defocused image can be sharpened * with shock_filter. dev_close_window () dev_open_window (0, 0, 640, 480, 'black', Window...
  • onblur失焦事件

    千次阅读 2022-05-27 21:50:34
    对于onblur 事件的小记 定义和用法: onblur 事件发生在对象失去焦点时。 onblur 事件最常与表单验证代码一起使用(例如,当用户离开表单字段时)。 提示: onblur 事件与 onfocus 事件相反。 提示: onblur 事件类似...
  • 同一个浏览器切换不同页面,导致el-input重复聚焦,我只想让它聚焦一次之后就失焦,请问该怎么实现
  • 圆形的PSF因为只有一个半径参数R,是一个非常好的失焦畸变近似,所以算法采用圆形的PSF。 模糊恢复,模板恢复本质是获得一个对原图的近似估算图像,在频率域可以表示如下: 其中SNR表示信噪比,因此可以基于维纳滤波...
  • vue input组件设置失焦与聚焦

    千次阅读 2022-01-29 16:34:22
    我在iview-admin这个后台管理系统中,使用input输入框失焦时触发了一个axios请求,但是,当我从其它页面,携带input输入框的数据进入该页面,进行数据填充的时候发现,数据填充没有问题,但是因为没有触及到失焦事件...
  • 使el-input失焦

    2022-05-25 16:12:48
    //html部分 <el-input v-model="ruleForm.pwd" @keyup.enter="login($event)"></el-input> //js部分 login:(event)=>{ event.target.blur() }, ...使用$event事件,触发失焦
  • js:聚焦和失焦事件示例

    千次阅读 2022-01-03 22:03:19
    <!... <... <head> ...meta charset="UTF-8">...4.聚焦和失焦</title> </head> <body> <div> 用户名: <input type="text" name="userName" onfocus="testFocus(this)" onblu.
  • pyqt5 失焦 无操作
  • JS实现input失焦累加

    2021-11-16 14:34:27
    失去焦点函数:blur 获取焦点函数:focus var IMPLEMENT=document.querySelector("#IMPLEMENT"); //失去焦点 IMPLEMENT.blur(()=>{ sum() }) function sum(){ //判断 必填input 全部填写才能计算 ...
  • 页面中只能有一个元素有焦点,一个聚焦,另一个就失焦,默认在document。例子结构如下:js操作如下:1.form.txt1.focus(); // 让元素获得焦点,该方法不会触发onfocus()事件。2.form.txt1.onfocus=function(){...
  • 【JQuery】两种失焦事件的使用

    千次阅读 2021-11-21 11:17:02
    在JQuery框架中,blur()失焦事件 / change()内容改变事件都可以作为失焦事件来使用。所不同的是,blur()事件会在用户离开input输入框后就触发,不在乎input输入框中的变化状况;change()事件只会在用户离开input...
  • element中级联选择器实现失焦事件
  • 失焦图像的 PSF (PSF of an out-of-focus image)是多少 如何恢复模糊的图像(restore a blurred image) 什么是维纳滤波器(Wiener filter) Theory 笔记 解释基于书籍[95]和[303]。 另外,您可以参考 ...
  • 我想要聚焦input 出现下面sousuo这个div,然后失焦消失,但是我要点sousuo 这个div里面内容的时候不消失,这就有一个问题,失焦和点击事件发生冲突该怎么解决...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,677
精华内容 3,870
关键字:

失焦