zoukankan      html  css  js  c++  java
  • 关于困扰我一下午的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 {
                 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;
             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的时间被重复触发;

  • 相关阅读:
    hadoop yarn
    java 删除文件夹及其里面的文件
    scrapy 429 处理
    java 获取当前时间(年月日时分秒)
    Java测试类
    eclipse环境问题-java版本不兼容
    Java内功修炼系列一工厂模式
    Java内功修炼系列一观察者模式
    Java内功修炼系列一责任链模式
    Java内功修炼系列一拦截器
  • 原文地址:https://www.cnblogs.com/heyinwangchuan/p/8124438.html
Copyright © 2011-2022 走看看