vue-自定義指令-實現提示功能

eagle發表於2018-11-29

參考資料:

  1. www.cnblogs.com/kidney/p/62…
<template>
  <div id="example">
    <div class="icon" v-tip.top="'背景色top'"><i>top</i></div>
    <div class="icon" v-tip.right="'背景色right'"><i>right</i></div>
    <div class="icon" v-tip.left="'背景色left'"><i>left</i></div>
    <div class="icon" v-tip.bottom="'背景色bottom'"><i>bottom</i></div>

    <div class="card-wrap" v-clickoutside="bindClose">
      <input type="text" placeholder="請輸入" @focus="cardIsShow = true">
      <ul class="card" v-show="cardIsShow">
        <li v-for="val of 3" :key="val" @click="cardIsShow = false">{{val}}</li>
      </ul>
    </div>
  </div>
</template>

<script>
var obj = {
  foo: 'bar'
}

export default {
  name: 'HelloWorld',
  data () {
    return {
      cardIsShow: false,
    }
  },
  components: {
  },
  computed:{
    
  },
  created() {
  },
  methods:{
    bindClose() {
      this.cardIsShow = false;
    },
    show() {}
  },
  directives: {
    tip: {
      inserted: function(el, binding) {
        let oTip = document.createElement('div'),
            modifiers = binding.modifiers;
        oTip.innerHTML = `<div>${binding.value}</div>`;
        oTip.className='v-tooltip__content';
        el.style.position = 'relative';
        
        el.appendChild(oTip);
        for(let attr in modifiers) {
          if(attr == 'top') {
            oTip.style.cssText = 'left: 50%; top: -10px;  transform: translate(-50%,-100%);';
          }else if(attr == 'right') {
            oTip.style.cssText = 'right: -10px; top: 50%; transform: translate(100%,-50%)';
          }else if( attr == 'left') {
              oTip.style.cssText = 'left: -10px; top: 50%; transform: translate(-100%,-50%)';
          }else {
              oTip.style.cssText = 'left: 50%; bottom: -10px; transform: translate(-50%,100%)';
          }
        }
        el.onmousemove = function() {
          oTip.style.opacity = 1;
        }
        el.onmouseout = function() {
          oTip.style.opacity = 0;
        }
      }
    },
    clickoutside: {
      bind(el, binding, vnode) {
        function documentHandler(e) {
            // 這裡判斷點選的元素是否是本身,是本身,則返回
            if (el.contains(e.target)) {
                return false;
            }
            // 判斷指令中是否繫結了函式
            if (binding.expression) {
                // 如果繫結了函式 則呼叫那個函式,此處binding.value就是bindClose方法
                binding.value(e);
            }
          }
          // 給當前元素繫結個私有變數,方便在unbind中可以解除事件監聽
          el.__vueClickOutside__ = documentHandler;
          document.addEventListener('click', documentHandler);
      },
      unbind(el, binding) {//只呼叫一次,指令與元素解綁時呼叫,指的是DOM元素被VUE移除,如通過v-if判斷移除
        // 解除事件監聽
        document.removeEventListener('click', el.__vueClickOutside__);
        delete el.__vueClickOutside__;
      }
    }
  }
      
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>

.v-tooltip__content {
    background: #616161;
    border-radius: 2px;
    color: #fff;
    font-size: 12px;
    line-height: 12px;
    padding: 5px 8px;
    position: absolute;
    transition: 0.15s cubic-bezier(0.25, 0.8, 0.5, 1);
    box-shadow: 0px 3px 1px -2px rgba(0,0,0,0.2), 0px 2px 2px 0px rgba(0,0,0,0.14), 0px 1px 5px 0px rgba(0,0,0,0.12);
    display: block;
    width: auto;
    white-space: nowrap;
    opacity: 0;
}

</style>

<style scoped>
  ul,li {
    margin: 0;
    list-style: none;
    padding: 0;
  }
  .icon {
    margin-bottom: 50px;
    position: relative;
    width: 100px;
    line-height: 35px;
    border: 1px solid #ccc;
    margin-left: 100px;
  }
  
  .card-wrap {
    position: relative;
    width: 200px;
    margin-top: 50px;
  }
  .card-wrap input {
    line-height: 32px;
    width: 100%;
    box-sizing: border-box;
    padding: 0;
    padding: 0 5px;
  }
  .card-wrap .card {
    position: absolute;
    left: 0;
    top: 36px;
    width: 100%;
    box-sizing: border-box;
    border: 1px solid #ccc;
    padding: 20px 0;
  }
  .card-wrap .card li {
    line-height: 32px;
    margin-bottom: 20rpx;

  }
  .card-wrap .card li:hover {
    background: #f5f5f5;
  }
</style>

複製程式碼

相關文章