<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          開(kāi)箱即用,超實(shí)用的 Vue 自定義指令合集

          共 12669字,需瀏覽 26分鐘

           ·

          2021-05-25 14:43

          作者:Huup_We

          juejin.cn/post/6963840401899782175

          在 Vue2.0 中,代碼復(fù)用和抽象的主要形式是組件。然而,有的情況下,你仍然需要對(duì)普通 DOM 元素進(jìn)行底層操作,這時(shí)候就會(huì)用到自定義指令。

          你可以將一些 css 樣式抽象到指令中,也可以將一些 js 操作放到指令中去執(zhí)行。就使用上來(lái)說(shuō),指令不用像組件一樣需要引入和注冊(cè),注冊(cè)后使用非常簡(jiǎn)潔方便。

          對(duì)于在項(xiàng)目中常用到的指令,在此做了一個(gè)合集介紹,附源碼可以直接在項(xiàng)目中使用。

          元素點(diǎn)擊范圍擴(kuò)展指令 v-expandClick

          使用該指令可以隱式的擴(kuò)展元素的點(diǎn)擊范圍,由于借用偽元素實(shí)現(xiàn),故不會(huì)影響元素在頁(yè)面上的排列布局。

          可傳入的參數(shù)為:上右下左擴(kuò)展的范圍,單位 px,默認(rèn)向外擴(kuò)展 10px。指令的代碼如下:

          export default function (el, binding) {
          const s = document.styleSheets[document.styleSheets.length - 1]
          const DEFAULT = -10 // 默認(rèn)向外擴(kuò)展10px
          const ruleStr = `content:"";position:absolute;top:-${top || DEFAULT}px;bottom:-${bottom || DEFAULT}px;right:-${right || DEFAULT}px;left:-${left || DEFAULT}px;`
          const [top, right, bottom, left] = binding.expression && binding.expression.split(',') || []
          const classNameList = el.className.split(' ')
          el.className = classNameList.includes('expand_click_range') ? classNameList.join(' ') : [...classNameList, 'expand_click_range'].join(' ')
          el.style.position = el.style.position || "relative"
          if (s.insertRule) {
          s.insertRule('.expand_click_range::before' + '{' + ruleStr + '}', s.cssRules.length)
          } else { /* IE */
          s.addRule('.expand_click_range::before', ruleStr, -1)
          }
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          top, right, bottom, left上右下左擴(kuò)展寬度(逗號(hào)分割),
          單位px
          10,10,10,10String可填

          然后你可以在模板中任何元素上使用新的 v-expandClick property,如下:

          <div v-expandClick="20,30,40,50" @click="glabClickoutside"> 點(diǎn)擊范圍擴(kuò)大</div>
          復(fù)制代碼

          文本內(nèi)容復(fù)制指令 v-copy

          使用該指令可以復(fù)制元素的文本內(nèi)容(指令支持單擊復(fù)制 v-copy、雙擊復(fù)制 v-copy.dblclick、點(diǎn)擊icon復(fù)制 v-copy.icon 三種模式),不傳參數(shù)時(shí),默認(rèn)使用單擊復(fù)制。

          指令的代碼如下:

          export default {
          bind (el, binding) {
          // 雙擊觸發(fā)復(fù)制
          if (binding.modifiers.dblclick) {
          el.addEventListener('dblclick', () => handleClick(el.innerText))
          el.style.cursor = 'copy'
          }
          // 點(diǎn)擊icon觸發(fā)復(fù)制
          else if (binding.modifiers.icon) {
          if (el.hasIcon) return
          const iconElement = document.createElement('i')
          iconElement.setAttribute('class', 'el-icon-document-copy')
          iconElement.setAttribute('style', 'margin-left:5px')
          el.appendChild(iconElement)
          el.hasIcon = true
          iconElement.addEventListener('click', () => handleClick(el.innerText))
          iconElement.style.cursor = 'copy'
          }
          // 單擊觸發(fā)復(fù)制
          else {
          el.addEventListener('click', () => handleClick(el.innerText))
          el.style.cursor = 'copy'
          }
          }
          }

          function handleClick (text) {
          // 創(chuàng)建元素
          if (!document.getElementById('copyTarget')) {
          const copyTarget = document.createElement('input')
          copyTarget.setAttribute('style', 'position:fixed;top:0;left:0;opacity:0;z-index:-1000;')
          copyTarget.setAttribute('id', 'copyTarget')
          document.body.appendChild(copyTarget)
          }

          // 復(fù)制內(nèi)容
          const input = document.getElementById('copyTarget')
          input.value = text
          input.select()
          document.execCommand('copy')
          // alert('復(fù)制成功')
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          dblclick雙擊復(fù)制文本內(nèi)容/String可選
          icon單擊icon復(fù)制文本內(nèi)容/String可選

          然后你可以在模板中任何元素上使用新的 v-copy property,如下:

          <div v-copy> 單擊復(fù)制 </div>
          <div v-copy.dblclick> 雙擊復(fù)制 </div>
          <div v-copy.icon> icon復(fù)制 </div>
          復(fù)制代碼

          元素全屏指令 v-screenfull

          全屏指令,點(diǎn)擊元素進(jìn)行全屏/退出全屏的操作。支持元素后面是否插入 element-ui 的全屏圖標(biāo) el-icon-full-screen

          指令的代碼如下:

          import screenfull from 'screenfull'

          export default {
          bind (el, binding) {
          if (binding.modifiers.icon) {
          if (el.hasIcon) return
          // 創(chuàng)建全屏圖標(biāo)
          const iconElement = document.createElement('i')
          iconElement.setAttribute('class', 'el-icon-full-screen')
          iconElement.setAttribute('style', 'margin-left:5px')
          el.appendChild(iconElement)
          el.hasIcon = true
          }
          el.style.cursor = el.style.cursor || 'pointer'
          // 監(jiān)聽(tīng)點(diǎn)擊全屏事件
          el.addEventListener('click', () => handleClick())
          }
          }

          function handleClick () {
          if (!screenfull.isEnabled) {
          alert('瀏覽器不支持全屏')
          return
          }
          screenfull.toggle()
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          icon是否添加 icon/String可選

          然后你可以在模板中任何元素上使用新的 v-screenfull property,如下:

          <div v-screenfull.icon> 全屏 </div>
          復(fù)制代碼

          元素說(shuō)明指令 v-tooltip

          為元素添加說(shuō)明,如同 element-ui 的 el-tooltip(問(wèn)號(hào) icon 在鼠標(biāo)覆蓋后,展示說(shuō)明文字)。

           指令的代碼如下:

          import Vue from 'vue'
          export default function (el, binding) {
          if (el.hasIcon) return
          const iconElement = structureIcon(binding.arg, binding.value)
          el.appendChild(iconElement)
          el.hasIcon = true
          }

          function structureIcon (content, attrs) {
          // 拼接綁定屬性
          let attrStr = ''
          for (let key in attrs) {
          attrStr += `${key}=${attrs[key]} `
          }
          const a = `<el-tooltip content=${content} ${attrStr}><i class="el-icon-question" style="margin:0 10px"></i></el-tooltip>`
          // 創(chuàng)建構(gòu)造器
          const tooltip = Vue.extend({
          template: a
          })
          // 創(chuàng)建一個(gè) tooltip 實(shí)例并返回 dom 節(jié)點(diǎn)
          const component = new tooltip().$mount()
          return component.$el
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          content傳給指令的參數(shù)。例如 v-tooltip:content 中,參數(shù)為 "content" ,tooltip中展示的內(nèi)容為:"content"/String可選
          tootipParamselement-ui 支持的 tooltip 屬性/Object可選

          然后你可以在模板中任何元素上使用新的 v-tooltip property,如下:

          <div v-tooltip:content='tootipParams'> 提示 </div>
          復(fù)制代碼

          舉例:

          <div v-tooltip:提示內(nèi)容為XXX1> 提示1</div>
          <div v-tooltip:提示內(nèi)容為XXX='tootipParams'> 提示2 </div>
          復(fù)制代碼

          為指令傳入 element-ui 支持的參數(shù):

          data() {
          return {
          tootipParams: {
          placement: 'top',
          effect: 'light',
          }
          }
          }
          復(fù)制代碼

          文字超出省略指令 v-ellipsis

          使用該指令當(dāng)文字內(nèi)容超出寬度(默認(rèn) 100 px)時(shí)自動(dòng)變?yōu)槭÷孕问?。等同于使?nbsp;css

          width: 100px;
          whiteSpace: nowrap
          overflow: hidden;
          textOverflow: ellipsis;
          復(fù)制代碼

          使用指令效果:

          指令的代碼如下:

          export default function (el, binding) {
          el.style.width = binding.arg || 100 + 'px'
          el.style.whiteSpace = 'nowrap'
          el.style.overflow = 'hidden';
          el.style.textOverflow = 'ellipsis';
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          width元素寬度100Number必填

          然后你可以在模板中任何元素上使用新的 v-ellipsis property,如下:

          <div v-ellipsis:100> 需要省略的文字是阿薩的副本阿薩的副本阿薩的副本阿薩的副本</div>
          復(fù)制代碼

          回到頂部指令 v-backtop

          使用該指令可以讓頁(yè)面或指定元素回到頂部。

          可選指定元素,如果不指定則全局頁(yè)面回到頂部??蛇x在元素偏移多少 px 后顯示 backtop 元素,例如在滾動(dòng) 400px 后顯示回到頂部按鈕。

          指令的代碼如下:

          export default {
          bind (el, binding, vnode) {
          // 響應(yīng)點(diǎn)擊后滾動(dòng)到元素頂部
          el.addEventListener('click', () => {
          const target = binding.arg ? document.getElementById(binding.arg) : window
          target.scrollTo({
          top: 0,
          behavior: 'smooth'
          })
          })
          },
          update (el, binding, vnode) {
          // 滾動(dòng)到達(dá)參數(shù)值才出現(xiàn)綁定指令的元素
          const target = binding.arg ? document.getElementById(binding.arg) : window
          if (binding.value) {
          target.addEventListener('scroll', (e) => {
          if (e.srcElement.scrollTop > binding.value) {
          el.style.visibility = 'unset'
          } else {
          el.style.visibility = 'hidden'
          }
          })
          }
          // 判斷初始化狀態(tài)
          if (target.scrollTop < binding.value) {
          el.style.visibility = 'hidden'
          }
          },
          unbind (el) {
          const target = binding.arg ? document.getElementById(binding.arg) : window
          target.removeEventListener('scroll')
          el.removeEventListener('click')
          }
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          id給需要回到頂部的元素添加的id/String可選
          offset偏移距離為 height 時(shí)顯示指令綁定的元素/Number可選

          然后你可以在模板中任何元素上使用新的 v-backtop property,如下表示在 id 為 app 的元素滾動(dòng) 400px 后顯示綁定指令的元素:

          <div  v-backtop:app="400"> 回到頂部 </div>
          復(fù)制代碼

          也可以這樣使用,表示為一直顯示綁定指令的元素,并且是全局頁(yè)面回到頂部:

          <div  v-backtop> 回到頂部 </div>
          復(fù)制代碼

          空狀態(tài)指令 v-empty

          使用該指令可以顯示缺省的空狀態(tài)。可以傳入默認(rèn)圖片(可選,默認(rèn)無(wú)圖片)、默認(rèn)文字內(nèi)容(可選,默認(rèn)為暫無(wú)數(shù)據(jù))、以及標(biāo)示是否顯示空狀態(tài)(必選)。

          指令的代碼如下:

          import Vue from "vue";
          export default {
          update (el, binding, vnode) {
          el.style.position = el.style.position || 'relative'
          const { offsetHeight, offsetWidth } = el
          const { visible, content, img } = binding.value
          const image = img ? `<img src="${img}" height="30%" width="30%"></img>` : ''
          const defaultStyle = "position:absolute;top:0;left:0;z-index:9999;background:#fff;display:flex;justify-content: center;align-items: center;"
          const empty = Vue.extend({
          template: `<div style="height:${offsetHeight}px;width:${offsetWidth}px;${defaultStyle}">
          <div style="text-align:center">
          <div>${image}</div>
          <div>${content || '暫無(wú)數(shù)據(jù)'}</div>
          </div>
          </div>`

          })
          const component = new empty().$mount().$el
          if (visible) {
          el.appendChild(component)
          } else {
          el.removeChild(el.lastChild)
          }
          },
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          emptyValue包含文字內(nèi)容 content、圖片 img、是否顯示 visible,僅 visible 必傳/Object必須

          然后你可以在模板中任何元素上使用新的 v-empty property,如下傳入對(duì)象 emptyValue

          <div style="height:500px;width:500px" v-empty="emptyValue"> 原本內(nèi)容

          復(fù)制代碼

          需要傳入一個(gè)參數(shù)對(duì)象,例如顯示文字為:暫無(wú)列表,圖片路徑為 ../../assets/images/blue_big.png,控制標(biāo)示 visible

          emptyValue = {
          content: '暫無(wú)列表',
          img: require('../../assets/images/blue_big.png'),
          visible: true,
          },
          復(fù)制代碼

          徽標(biāo)指令 v-badge

          使用該指令在元素右上角顯示徽標(biāo)。

          支持配置徽標(biāo)的背景顏色、徽標(biāo)形狀;支持傳入徽標(biāo)上顯示的數(shù)字。

           

          指令的代碼如下:

          import Vue from 'vue'

          const SUCCESS = '#72c140'
          const ERROR = '#ed5b56'
          const WARNING = '#f0af41'
          const INFO = '#4091f7'
          const HEIGHT = 20
          let flag = false
          export default {
          update (el, binding, vnode) {
          const { modifiers, value } = binding
          const modifiersKey = Object.keys(modifiers)
          let isDot = modifiersKey.includes('dot')
          let backgroundColor = ''
          if (modifiersKey.includes('success')) {
          backgroundColor = SUCCESS
          } else if (modifiersKey.includes('warning')) {
          backgroundColor = WARNING
          } else if (modifiersKey.includes('info')) {
          backgroundColor = INFO
          } else {
          backgroundColor = ERROR
          }

          const targetTemplate = isDot
          ? `<div style="position:absolute;top:-5px;right:-5px;height:10px;width:10px;border-radius:50%;background:${backgroundColor}"></div>`
          : `<div style="background:${backgroundColor};position:absolute;top:-${HEIGHT / 2}px;right:-${HEIGHT / 2}px;height:${HEIGHT}px;min-width:${HEIGHT}px;border-radius:${HEIGHT / 2}px;text-align:center;line-height:${HEIGHT}px;color:#fff;padding:0 5px;">${value}</div>`

          el.style.position = el.style.position || 'relative'
          const badge = Vue.extend({
          template: targetTemplate
          })
          const component = new badge().$mount().$el
          if (flag) {
          el.removeChild(el.lastChild)
          }
          el.appendChild(component)
          flag = true
          }
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          normal、dot徽標(biāo)形狀normal為正?;諛?biāo);dot 僅為一個(gè)點(diǎn)normalString可選
          success、error、info、warning徽標(biāo)顏色errorString可選
          number徽標(biāo)上顯示的數(shù)字/Number可選

          然后你可以在模板中任何元素上使用新的 v-badge property,如下:

          <div v-badge.dot.info="badgeCount" style="height:50px;width:50px;background:#999"> </div>
          復(fù)制代碼

          拖拽指令 v-drag

          使用該指令可以對(duì)元素進(jìn)行拖拽。

          指令的代碼如下:

          export default {
          let _el = el
          document.onselectstart = function() {
          return false //禁止選擇網(wǎng)頁(yè)上的文字
          }

          _el.onmousedown = e => {
          let disX = e.clientX - _el.offsetLeft //鼠標(biāo)按下,計(jì)算當(dāng)前元素距離可視區(qū)的距離
          let disY = e.clientY - _el.offsetTop
          document.onmousemove = function(e){
          let l = e.clientX - disX
          let t = e.clientY - disY;
          _el.style.left = l + "px"
          _el.style.top = t + "px"
          }
          document.onmouseup = e => {
          document.onmousemove = document.onmouseup = null
          }
          return false
          }
          }

          復(fù)制代碼

          然后你可以在模板中任何元素上使用新的 v-drag property,如下:

          <div v-drag> 支持拖拽的元素 </div>
          復(fù)制代碼

          響應(yīng)縮放指令 v-resize

          使用該指令可以響應(yīng)元素寬高改變時(shí)執(zhí)行的方法。

          指令的代碼如下:

          export default {
          bind(el, binding) {
          let width = '', height = '';
          function isReize() {
          const style = document.defaultView.getComputedStyle(el);
          if (width !== style.width || height !== style.height) {
          binding.value(); // 執(zhí)行傳入的方法
          }
          width = style.width;
          height = style.height;
          }
          el.__timer__ = setInterval(isReize, 300); // 周期性監(jiān)聽(tīng)元素是否改變
          },
          unbind(el) {
          clearInterval(el.__timer__);
          }
          }
          復(fù)制代碼

          參數(shù) Attributes:

          參數(shù)說(shuō)明默認(rèn)值類(lèi)型可選
          resize()傳入元素改變 size 后執(zhí)行的方法/Function必選

          然后你可以在模板中任何元素上使用新的 v-resize property,如下:

          // 傳入 resize() 方法
          <div v-resize="resize"></div>
          復(fù)制代碼

          如何使用這些指令?

          為了便于管理指令,我們將每個(gè)指令都存在于單獨(dú)的 js 文件中,你可以像這樣將指令 import 進(jìn)來(lái)后注冊(cè)指令:

          import Vue from 'vue'
          import ellipsis from './ellipsis' // 引入指令
          // import other directives

          const directives = {
          ellipsis
          // other directives
          }

          Object.keys(directives).forEach(name => Vue.directive(name, directives[name]))
          復(fù)制代碼

          或者你可以直接使用 Vue.deirect 進(jìn)行注冊(cè):

          // 注冊(cè)一個(gè)全局自定義指令 `v-focus`
          Vue.directive('focus', {
          // 當(dāng)被綁定的元素插入到 DOM 中時(shí)……
          inserted: function (el) {
          // 聚焦元素
          el.focus()
          }
          })
          復(fù)制代碼

          這樣就可以正常使用這些指令了:

          <div v-指令名稱(chēng) />
          復(fù)制代碼

          總結(jié)

          我們常常在引入全局功能時(shí),主要都是寫(xiě)于 js 文件、組件中。不同于他們?cè)谑褂脮r(shí)每次需要引用或注冊(cè),在使用上指令更加簡(jiǎn)潔。

          除了將功能封裝成組件,還可以多多考慮將一些簡(jiǎn)潔實(shí)用的功能放到 deirect 中。例如:常用的 css 樣式、js 的一些操作、utils 中的一些工具方法、甚至是一個(gè)完整的組件都可以放進(jìn)去(不過(guò)需要考慮一下性能和復(fù)雜度)。

          瀏覽 100
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  8x8x皇冠视频免费观看 | 激情五月网在线 | 日韩中出在线播放 | 一级a性色毛片 | 天堂无码不卡 |