国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

vue 指令---氣泡提示(手?jǐn)]實(shí)戰(zhàn))

adie / 1789人閱讀

摘要:自己寫了個(gè)組件,想加個(gè)氣泡提示。為了復(fù)用和省事特此寫了個(gè)指令來解決。的生命周期生成前生成后生成真正更新更新銷毀。而的指令則是依賴于的生命周期,無非也是有以上類似的鉤子。當(dāng)鼠標(biāo)放到上就會(huì)顯示出來,離開就會(huì)消失。

菜鳥學(xué)習(xí)之路
//L6zt github
自己在造組件輪子,也就是瞎搞。
自己寫了個(gè)slider組件,想加個(gè)氣泡提示。為了復(fù)用和省事特此寫了個(gè)指令來解決。
預(yù)覽地址
項(xiàng)目地址 github 我叫給它胡博

我對指令的理解: 前不久看過 一部分vnode實(shí)現(xiàn)源碼,奈何資質(zhì)有限...看不懂。
vnode的生命周期-----> 生成前、生成后、生成真正dom、更新 vnode、更新dom 、 銷毀。
而Vue的指令則是依賴于vnode 的生命周期, 無非也是有以上類似的鉤子。
代碼效果
指令掛A元素上,默認(rèn)生成一個(gè)氣泡容器B插入到 body 里面,B 會(huì)獲取 元素 A 的位置信息 和 自己的
大小信息,經(jīng)過 一些列的運(yùn)算,B 元素會(huì)定位到 A 的 中間 上 位置。 當(dāng)鼠標(biāo)放到 A 上 B 就會(huì)顯示出來,離開就會(huì)消失。

以下代碼

氣泡指令

import { on , off , once, contains, elemOffset, position, addClass, removeClass } from "../utils/dom";
import Vue from "vue"
const global = window;
const doc = global.document;
const top = 15;
export default {
  name : "jc-tips" ,
  bind (el , binding , vnode) {
    // 確定el 已經(jīng)在頁面里 為了獲取el 位置信信 
    Vue.nextTick(() => {
      const { context } = vnode;
      const { expression } = binding;
      // 氣泡元素根結(jié)點(diǎn)
      const fWarpElm = doc.createElement("div");
      // handleFn 氣泡里的子元素(自定義)
      const handleFn = binding.expression && context[expression] || (() => "");
      const createElm = handleFn();
      fWarpElm.className = "hide jc-tips-warp";
      fWarpElm.appendChild(createElm);
      doc.body.appendChild(fWarpElm);
      // 給el 綁定元素待其他操作用
      el._tipElm = fWarpElm;
      el._createElm = createElm;
      // 鼠標(biāo)放上去的 回調(diào)函數(shù)
      el._tip_hover_fn = function(e) {
        // 刪除節(jié)點(diǎn)函數(shù)
          removeClass(fWarpElm, "hide");
          fWarpElm.style.opacity = 0;
          // 不加延遲 fWarpElm的大小信息 (元素大小是 0 0)---> 刪除 class 不是立即渲染
          setTimeout(() => {
            const offset = elemOffset(fWarpElm);
            const location = position(el);
            fWarpElm.style.cssText =  `left: ${location.left  - offset.width / 2}px; top: ${location.top - top - offset.height}px;`;
            fWarpElm.style.opacity = 1;
          }, 16);
      };
      //鼠標(biāo)離開 元素 隱藏 氣泡
      const handleLeave = function (e) {
        fWarpElm.style.opacity = 0;
        // transitionEnd 不太好應(yīng)該加入兼容
        once({
          el,
          type: "transitionEnd",
          fn: function() {
            console.log("hide");
            addClass(fWarpElm, "hide");
          }
        })
      };
      el._tip_leave_fn =  handleLeave;
      // 解決 slider 移動(dòng)結(jié)束 提示不消失
      el._tip_mouse_up_fn = function (e) {
        const target = e.target;
        console.log(target);
        if (!contains(fWarpElm, target) && el !== target) {
          handleLeave(e)
        }
      };
      on({
        el,
        type: "mouseenter",
        fn: el._tip_hover_fn
      });
      on({
        el,
        type: "mouseleave",
        fn: el._tip_leave_fn
      });
      on({
        el: doc.body,
        type: "mouseup",
        fn: el._tip_mouse_up_fn
      })
    });
  } ,
  // 氣泡的數(shù)據(jù)變化 依賴于 context[expression] 返回的值
  componentUpdated(el , binding , vnode) {
    const { context } = vnode;
    const { expression } = binding;
    const handleFn = expression && context[expression] || (() => "");
    Vue.nextTick( () => {
      const createNode = handleFn();
      const fWarpElm = el._tipElm;
      if (fWarpElm) {
        fWarpElm.replaceChild(createNode, el._createElm);
        el._createElm = createNode;
        const offset = elemOffset(fWarpElm);
        const location = position(el);
        fWarpElm.style.cssText =  `left: ${location.left  - offset.width / 2}px; top: ${location.top - top - offset.height}px;`;
      }
    })
  },
 // 刪除 事件
  unbind (el , bind , vnode) {
    off({
      el: dov.body,
      type: "mouseup",
      fn: el._tip_mouse_up_fn
    });
    el = null;
  }
}

slider 組件






../utils/dom

const global = window;
export const on = ({el, type, fn}) => {
         if (typeof global) {
             if (global.addEventListener) {
                 el.addEventListener(type, fn, false)
            } else {
                 el.attachEvent(`on${type}`, fn)
            }
         }
    };
    export const off = ({el, type, fn}) => {
        if (typeof global) {
            if (global.removeEventListener) {
                el.removeEventListener(type, fn)
            } else {
                el.detachEvent(`on${type}`, fn)
            }
        }
    };
    export const once = ({el, type, fn}) => {
        const hyFn = (event) => {
            try {
                fn(event)
            }
             finally  {
                off({el, type, fn: hyFn})
            }
        }
        on({el, type, fn: hyFn})
    };
    // 最后一個(gè)
    export const fbTwice = ({fn, time = 300}) => {
        let [cTime, k] = [null, null]
        // 獲取當(dāng)前時(shí)間
        const getTime = () => new Date().getTime()
        // 混合函數(shù)
        const hyFn = () => {
            const ags = argments
            return () => {
                clearTimeout(k)
                k = cTime =  null
                fn(...ags)
            }
        };
        return () => {
            if (cTime == null) {
                k = setTimeout(hyFn(...arguments), time)
                cTime = getTime()
            } else {
                if ( getTime() - cTime < 0) {
                    // 清除之前的函數(shù)堆 ---- 重新記錄
                    clearTimeout(k)
                    k = null
                    cTime = getTime()
                    k = setTimeout(hyFn(...arguments), time)
                }
            }}
    };
    export  const contains = function(parentNode, childNode) {
        if (parentNode.contains) {
            return parentNode !== childNode && parentNode.contains(childNode)
        } else {
            // https://developer.mozilla.org/zh-CN/docs/Web/API/Node/compareDocumentPosition
            return (parentNode.compareDocumentPosition(childNode) === 16)
        }
    };
    export const addClass = function (el, className) {
        if (typeof el !== "object") {
            return null
        }
        let  classList = el["className"]
        classList = classList === "" ? [] : classList.split(/s+/)
        if (classList.indexOf(className) === -1) {
            classList.push(className)
            el.className = classList.join(" ")
        }
    };
    export const removeClass = function (el, className) {
        let classList = el["className"]
        classList = classList === "" ? [] : classList.split(/s+/)
        classList = classList.filter(item => {
            return item !== className
        })
        el.className =     classList.join(" ")
    };
    export const delay = ({fn, time}) => {
        let oT = null
        let k = null
        return () => {
            // 當(dāng)前時(shí)間
            let cT = new Date().getTime()
            const fixFn = () => {
                k = oT = null
                fn()
            }
            if (k === null) {
                oT = cT
                k = setTimeout(fixFn, time)
                return
            }
            if (cT - oT < time) {
                oT = cT
                clearTimeout(k)
                k = setTimeout(fixFn, time)
            }
        
        }
    };
    export const position = (son, parent = global.document.body) => {
        let top  = 0;
        let left = 0;
        let offsetParent = son;
        while (offsetParent !== parent) {
            let dx = offsetParent.offsetLeft;
            let dy = offsetParent.offsetTop;
            let old = offsetParent;
            if (dx === null) {
                return {
                    flag: false
                }
            }
            left += dx;
            top += dy;
      offsetParent = offsetParent.offsetParent;
            if (offsetParent === null && old !== global.document.body) {
                return {
                    flag: false
                }
            }
        }
        return  {
            flag: true,
            top,
            left
        }
    };
    export  const getElem = (filter) => {
        return Array.from(global.document.querySelectorAll(filter));
    };
    export const elemOffset = (elem) => {
        return {
            width: elem.offsetWidth,
            height: elem.offsetHeight
        }
    };

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/98442.html

相關(guān)文章

  • 滾動(dòng)加載插件.手?jǐn)]實(shí)戰(zhàn)

    摘要:滾動(dòng)插件設(shè)計(jì)原理獲取滾動(dòng)元素的視口高度和滾動(dòng)高度得出滾動(dòng)軸最大滾動(dòng)距離根據(jù)滾動(dòng)時(shí)計(jì)算滾動(dòng)時(shí)滾動(dòng)軸的滾動(dòng)高度與比較做差,判斷是否觸發(fā)動(dòng)作。 // github L6zt滾動(dòng)插件設(shè)計(jì)原理 獲取滾動(dòng)元素的視口高度viewH和滾動(dòng)高度scrollH,得出 滾動(dòng)軸最大滾動(dòng)距離 scrollMaxTop = viewH - scrollH; 根據(jù)滾動(dòng)時(shí)計(jì)算滾動(dòng)時(shí)滾動(dòng)軸的滾動(dòng)高度 scrollTo...

    Meils 評論0 收藏0
  • 滾動(dòng)加載插件.手?jǐn)]實(shí)戰(zhàn)

    摘要:滾動(dòng)插件設(shè)計(jì)原理獲取滾動(dòng)元素的視口高度和滾動(dòng)高度得出滾動(dòng)軸最大滾動(dòng)距離根據(jù)滾動(dòng)時(shí)計(jì)算滾動(dòng)時(shí)滾動(dòng)軸的滾動(dòng)高度與比較做差,判斷是否觸發(fā)動(dòng)作。 // github L6zt滾動(dòng)插件設(shè)計(jì)原理 獲取滾動(dòng)元素的視口高度viewH和滾動(dòng)高度scrollH,得出 滾動(dòng)軸最大滾動(dòng)距離 scrollMaxTop = viewH - scrollH; 根據(jù)滾動(dòng)時(shí)計(jì)算滾動(dòng)時(shí)滾動(dòng)軸的滾動(dòng)高度 scrollTo...

    wanglu1209 評論0 收藏0
  • 如何使用CSS創(chuàng)建巧妙的動(dòng)畫提示

    摘要:我們巧妙的提示框打算使用屬性選擇器也就是方括號表示法。相對性這是用在提示框的父元素上的。向上向下提示框要用到關(guān)鍵幀,而向左向右提示框使用關(guān)鍵幀。注意,在這些關(guān)鍵幀中,我們只定義了提示框所需的終止?fàn)顟B(tài)。 原文:https://webdesign.tutsplus.co...原作:Jase Smith翻譯:Stypstive 當(dāng)你的用戶需要漂亮的圖標(biāo)給出額外的文字信息時(shí),亦或是當(dāng)他們在點(diǎn)擊...

    wmui 評論0 收藏0
  • 如何使用CSS創(chuàng)建巧妙的動(dòng)畫提示

    摘要:我們巧妙的提示框打算使用屬性選擇器也就是方括號表示法。相對性這是用在提示框的父元素上的。向上向下提示框要用到關(guān)鍵幀,而向左向右提示框使用關(guān)鍵幀。注意,在這些關(guān)鍵幀中,我們只定義了提示框所需的終止?fàn)顟B(tài)。 原文:https://webdesign.tutsplus.co...原作:Jase Smith翻譯:Stypstive 當(dāng)你的用戶需要漂亮的圖標(biāo)給出額外的文字信息時(shí),亦或是當(dāng)他們在點(diǎn)擊...

    vpants 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<