关于困扰我一下午的vue指令 clickoutside.js;以及我对指令的测试结果

https://github.com/ElemeFE/element/blob/d419e260d0fc1463ccbc4f5e45e129ec0e972255/src/utils/clickoutside.js

下面的代码是element ui中的clickoutside.js

const on = (function() {
  if (!Vue.prototype.$isServer && document.addEventListener) {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.addEventListener(event, handler, false);
      }
    };
  } else {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.attachEvent(‘on‘ + event, handler);
      }
    };
  }
})();

import Vue from ‘vue‘;

const nodeList = [];
const ctx = ‘@@clickoutsideContext‘;

let startClick;
let seed = 0;

!Vue.prototype.$isServer && on(document, ‘mousedown‘, e => (startClick = e));

!Vue.prototype.$isServer && on(document, ‘mouseup‘, e => {
  nodeList.forEach(node => node[ctx].documentHandler(e, startClick));
});

function createDocumentHandler(el, binding, vnode) {
  return function(mouseup = {}, mousedown = {}) {
    console.log(vnode.context.popperElm)
    if (!vnode ||
      !vnode.context ||
      !mouseup.target ||
      !mousedown.target ||
      el.contains(mouseup.target) ||
      el.contains(mousedown.target) ||
      el === mouseup.target ||
      (vnode.context.popperElm &&
      (vnode.context.popperElm.contains(mouseup.target) ||
      vnode.context.popperElm.contains(mousedown.target)))){
        return;
      }

    console.log(binding.expression);
    if (binding.expression &&
      el[ctx].methodName &&
      vnode.context[el[ctx].methodName]) {
      vnode.context[el[ctx].methodName]();
    } else {
      el[ctx].bindingFn && el[ctx].bindingFn();
    }
  };
}

/**
 * v-clickoutside
 * @desc 点击元素外面才会触发的事件
 * @example
 * ```vue
 * <div v-element-clickoutside="handleClose">
 * ```
 */
export default {
  bind(el, binding, vnode) {
    nodeList.push(el);
    const id = seed++;
    el[ctx] = {
      id,
      documentHandler: createDocumentHandler(el, binding, vnode),
      methodName: binding.expression,
      bindingFn: binding.value
    };
  },

  update(el, binding, vnode) {
    el[ctx].documentHandler = createDocumentHandler(el, binding, vnode);
    el[ctx].methodName = binding.expression;
    el[ctx].bindingFn = binding.value;
  },

  unbind(el) {
    let len = nodeList.length;

    for (let i = 0; i < len; i++) {
      if (nodeList[i][ctx].id === el[ctx].id) {
        nodeList.splice(i, 1);
        break;
      }
    }
    delete el[ctx];
  }
};

这个是我写的alert.vue

<template>
    <div class=‘dialog-alert‘ v-show="alert">
        <div class=‘dialog-content‘v-clickoutside="hideAlert">
            <div class="dialog-body">{{message}}</div>
            <a href="javascript:;" class="dialog-button" @click="hideAlert">确定</a>
        </div>
        <div class="dialog-mask"></div>
    </div>
</template>
<script>
import clickoutside from‘./../directives/vue-directive-clickout.js‘
 export default{
     props:{
         alert:{
             type:Boolean,
             required: true
         },
         message:{
             type:String,
             required: true
         }
     },
     methods:{
        hideAlert() {
            this.$emit(‘hideAlert‘);
        }
     },
    directives: {
        clickoutside
    },

 }

</script>
<style lang="scss" rel="stylesheet/scss" scoped>
   .dialog-alert {
        z-index: 21px;
        .dialog-content {
            position: absolute;
            left: 50%;
            top: 50%;
            margin-left: -4.6875rem;
            margin-top: -1.734375rem;
            z-index: 21;
            border-radius: .3125rem;
            background-color: #fff;
        }
        .dialog-body,
        .dialog-button {
            width: 9.375rem;
            height: 1.734375rem;
            margin: 0 auto;
            line-height: 1.734375rem;
        }
        .dialog-body {
            border-bottom: 1px solid #999;
            color: #6c6c6c
        }
        .dialog-button {
            color: #ff5000
        }
    }
    .dialog-mask {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        bottom: 0;
        z-index: 20;
        background: rgba(0, 0, 0, .6)
    }
</style>

还有我在login.vue中写的触发条件;loginIn函数是将alert的值改为true,hideAlert是将alert的值设置为false

    <button class="btn-login" type="button" @click="loginIn">登录</button>

    <alert :alert="alert" message="wowoowow" @hideAlert=‘hideAlert‘></alert>

这里的我的问题就是为什么点击登录的时候,弹窗还出的来;点击的时候hideAlert被执行了 所以应该是false;所以呢我就就行了各种的测试,始终找不到答案。

最后呢?我在走路回家的路上想通了这个问题,因为mouseup、mousedown先执行的,click时间后执行的。有点小难受。

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="bbb">点击</div>
<script>
     document.getElementById(‘bbb‘).addEventListener(‘click‘, function(){
         console.log(‘click‘)
     }, false);
     document.addEventListener(‘mouseup‘, function(){
         console.log(‘mouseup‘)
     }, false);
     document.addEventListener(‘mousedown‘, function(){
         console.log(‘mousedown‘)
     }, false);
</script>
</body>
</html>

结果:

测试的结果就是:  clickoutside.js

1、当一个指令在同一页面上有多个时;绑定的是document事件;document的时间被重复触发;

原文地址:https://www.cnblogs.com/heyinwangchuan/p/8124438.html

时间: 2024-10-16 15:48:09

关于困扰我一下午的vue指令 clickoutside.js;以及我对指令的测试结果的相关文章

vue自定义指令(Directive中的clickoutside.js)的理解

.array p { counter-increment: longen; margin-left: 10px } .array p::before { content: counter(longen) "." } .alink { font-size: 16px; color: blue } 阅读目录 vue自定义指令clickoutside.js的理解 回到顶部 vue自定义指令clickoutside.js的理解 vue自定义指令请看如下博客: vue自定义指令 一般在需要 DO

vue.js 学习四(指令和自定义指令)

官方的指令说明已经很简单了,这里再写一遍,也是自己加深一下印象 v-text 就是写入单纯的文本,可以忽略这个指令直接双花括号代替 <span v-text="msg"></span> <!-- 和下面的一样 --> <span>{{msg}}</span> v-html 更新元素的 innerHTML,如果取回的值里面包含了html的样式,可以使用这个指令. 以下抄写了官方注意事项,对于用户输入的HTML,显示的时候需要谨慎

Vue.js学习(常用指令)

Vue.js的指令是以v-开头,它们用于HTML元素,指令提供了一些特殊的特性,将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为,我们可以将指令看作特殊的HTML特性. Vue.js提供了一些内置指令,现在来介绍一下常用的内置指令. v-if指令           v-if是条件渲染指令,它根据表达式的真假来添加或删除元素,它的基本语法:v-if = "expression",expression是一个bool值的表达式,该表达式既可以是bool属性,也可以是一个返回b

vue.js实现内部自定义指令和全局自定义指令------directive

在Vue中,我们平时数据驱动视图时候,内部自带的指令有时候解决不了一些需求,这时候,Vue给我们一个很好用的东东 directive 这个单词是我们写自定义指令的关键字哦 之定义指令为我们提供了几个钩子函数,这时候你一定好奇什么是钩子函数,说简单点,就是集中表现状态 bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作. inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中). update:

[vue]vue条件渲染v-if(template)和自定义指令directives

条件渲染: v-if/template <div id="app"> <h1>v-show: display: none</h1> <div v-show="false">yes</div> <!--<div v-else>no</div>--> <h1>v-for: 判断1</h1> <div v-if="false"&

Vue基础(环境配置、内部指令、全局API、选项、内置组件)

1.环境配置 安装VsCode 安装包管理工具:直接下载 NodeJS 进行安装即可,NodeJS自带 Npm 包管理工具,下载地址:https://nodejs.org/en/download/安装完成后在命令行执行以下命令查看npm包管理器版本 npm -v npm中文文档:https://www.npmjs.cn/ 配置淘宝镜像 npm install cnpm -g --registry=https://registry.npm.taobao.org 然后执行 cnpm -v 查看版本信

vue自定义指令clickoutside使用以及扩展用法

vue自定义指令clickoutside使用以及扩展用法 产品使用vue+element作为前端框架.在功能开发过程中,难免遇到使用element的组件没办法满足特殊的业务需要,需要对其进行定制,例如要求选择器的弹出框中,增加搜索过滤(跟目前element的输入建议不太一样).于是想说说之前修改element组件,并定制为业务组件过程中遇到的问题. ps:因为对某些组件改动很大,所以是直接拷贝了一份源码,然后再进行修改,但是这样会遇到挺多问题,建议对于vue组件如果改动不大,只是简单功能扩展,就

Vue躬行记(2)——指令

Vue不仅内置了各类指令,包括条件渲染.事件处理等,还能注册自定义指令. 一.条件渲染 条件渲染的指令包括v-if.v-else.v-else-if和v-show. 1)v-if 该指令的功能和条件语句中的if类似,可根据表达式的计算结果,判断是否渲染分支中的元素和它所包含的子元素.在下面的示例中,当把数据对象的exist属性设为true时,<div>和<p>两个元素就会被添加到页面的DOM中. <div v-if="exist"> <p>

什么是vue.js中的自定义指令?

问题一:什么是vue.js中的自定义指令? 自定义一些指令对底层DOM进行操作 更多参考 Vue里面有许多内置的指令,比如v-if和v-show,这些丰富的指令能满足我们的绝大部分业务需求,不过在需要一些特殊功能时,我们仍然希望对DOM进行底层的操作,这时就要用到自定义指令. 问题二:自定义指令的几个钩子函数 bind:只调用一次,指令第一次绑定到元素时调用.在这里可以进行一次性的初始化设置. inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中). upda