使用vue 指令怎么實(shí)現(xiàn)氣泡提示效果?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
10年的迪慶州網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營銷型網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整迪慶州建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)從事“迪慶州網(wǎng)站設(shè)計(jì)”,“迪慶州網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。氣泡指令
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 移動結(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 組件
<template> <div class="jc-slider-cmp"> <section class="slider-active-bg" : > </section> <i class="jc-slider-dot" : ref="dot" @mousedown="moveStart" v-jc-tips="createNode" > </i> </div> </template> <script> import {elemOffset, on, off, once} from "../../utils/dom"; const global = window; const doc = global.document; export default { props: { step: { type: [Number], default: 0 }, rangeEnd: { type: [Number], required: true }, value: { type: [Number], required: true }, minValue: { type: [Number], required: true }, maxValue: { type: [Number], required: true } }, data () { return { startX: null, width: null, curValue: 0, curStep: 0, left: 0, tempLeft: 0 } }, computed: { wTov () { let step = this.step; let width = this.width; let rangeEnd = this.rangeEnd; if (width) { if (step) { return width / (rangeEnd / step) } return width / rangeEnd } return null }, postValue () { let value = null; if (this.step) { value = this.step * this.curStep; } else { value = this.left / this.wTov; } return value; } }, watch: { value: { handler (value) { this.$nextTick(() => { let step = this.step; let wTov = this.wTov; if (step) { this.left = value / step * wTov; } else { this.left = value * wTov; } }) }, immediate: true } }, methods: { moveStart (e) { e.preventDefault(); const body = window.document.body; const _this = this; this.startX = e.pageX; this.tempLeft = this.left; on({ el: body, type: 'mousemove', fn: this.moving }); once({ el: body, type: 'mouseup', fn: function() { console.log('end'); _this.$emit('input', _this.postValue); off({ el: body, type: 'mousemove', fn: _this.moving }) } }) }, moving(e) { let curX = e.pageX; let step = this.step; let rangeEnd = this.rangeEnd; let width = this.width; let tempLeft = this.tempLeft; let startX = this.startX; let wTov = this.wTov; if (step !== 0) { let all = parseInt(rangeEnd / step); let curStep = (tempLeft + curX - startX) / wTov; curStep > all && (curStep = all); curStep < 0 && (curStep = 0); curStep = Math.round(curStep); this.curStep = curStep; this.left = curStep * wTov; } else { let left = tempLeft + curX - startX; left < 0 && (left = 0); left > width && (left = width); this.left = left; } }, createNode () { const fElem = document.createElement('i'); const textNode = document.createTextNode(this.postValue.toFixed(2)); fElem.appendChild(textNode); return fElem; } }, mounted () { this.width = elemOffset(this.$el).width; } }; </script> <style lang="scss"> .jc-slider-cmp { position: relative; display: inline-block; width: 100%; border-radius: 4px; height: 8px; background: #ccc; .jc-slider-dot { position: absolute; display: inline-block; width: 15px; height: 15px; border-radius: 50%; left: 0; top: 50%; transform: translate(-50%, -50%); background: #333; cursor: pointer; } .slider-active-bg { position: relative; height: 100%; border-radius: 4px; background: red; } } </style> ../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 } };
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。
分享標(biāo)題:使用vue指令怎么實(shí)現(xiàn)氣泡提示效果-創(chuàng)新互聯(lián)
分享URL:http://www.rwnh.cn/article28/dspscp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、網(wǎng)站制作、小程序開發(fā)、微信小程序、虛擬主機(jī)、網(wǎng)站設(shè)計(jì)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容