vue 項目中遇到的常用自定義指令

1.el-input 輸入框扫夜,只能輸入數(shù)字,并且可限制上下限驰徊,保留小數(shù)位數(shù)

  • 1.輸入的不是數(shù)字失去焦點時值會被清空【包括科學計數(shù)法 e 也不能輸入】
  • 2.可配置輸入值的范圍笤闯,超出范圍給出提示并清空
  • 3.可配置小數(shù)位數(shù)
import { Message } from 'element-ui';
// 判斷值是否為空,注意:0是有值的
function isNUll(val) {
  return val === null || val === void 0 || val === '' || val.toString() === 'NaN';
}

/**
 * author: yf
 * date: 20241212
 * 對input type="number" 類型輸入框的擴展棍厂,
 * 1.輸入的不是數(shù)字失去焦點時值會被清空【包括科學計數(shù)法 e 也不能輸入】
 * 2.可配置輸入值的范圍颗味,超出范圍給出提示并清空
 * 3.可配置小數(shù)位數(shù)
 *
 * 注意搭配 type="number" 使用效果最佳
 * 使用方式:
 *
 * 方式一:使用默認配置,只是限制了輸入的只能是數(shù)字【包括e也不能輸入】牺弹,不然會被清空
 * v-number-input-extend
 *
 * 方式二:帶參數(shù)浦马,注意: 所有參數(shù)都是可選
 * v-number-input-extend = "{
      label: 'xxx輸入框', // 這個輸入框的label值,用于提示
      min: 0, // 輸入值的最小值 - 不傳則不會處理
      max: 100, // 輸入值的最大值 - 不傳則不會處理
      toFixed: 2, // 值的小數(shù)位數(shù) - 不傳則不會處理
      isPrompt: true, // 不滿足驗證條件時是否提示张漂,比如最大最小值的驗證
      isClearZero: false // 值為0時晶默,是否置為空 - 不傳則不會處理
 * }"
 */
Vue.directive('number-input-extend', {
  inserted(el, binding, vnode) {
    // 配置
    let {
      label = '', // 這個輸入框的label值,用于提示
      min, // 輸入值的最小值
      max, // 輸入值的最大值
      toFixed, // 值的小數(shù)位數(shù)
      isPrompt = true, // 不滿足驗證條件時是否提示航攒,比如最大最小值的驗證
      isClearZero = false // 值為0時磺陡,是否置為空 - 某些場景會用到
    } = binding.value || {};

    let $input = vnode.componentInstance;
    // 設置輸入框的值,觸發(fā)input事件,改變v-model綁定的值
    const setVal = val => {
      if ($input) {
        // 如果是自定義組件就觸發(fā)自定義組件的input事件
        $input.$emit('input', val);
      } else {
        // 如果是原生組件就觸發(fā)原生組件的input事件
        el.value = val;
        el.dispatchEvent(new Event('input'));
      }
    };

    el._customData = {
      blur: event => {
        const e = event || window.event;
        // 去掉非數(shù)字字符
        let strVal = String(e.target.value || '').replace(/[^\-\d.]/g, '')
        let val = parseFloat(strVal);
        if (isNUll(val)) {
          val = '';
        }
        if (val !== '' && !isNUll(toFixed)) {
          val = Number(val.toFixed(toFixed));
        }

        // 值為0時,置為空
        if (isClearZero && val === 0) {
          val = '';
        }

        // #region 值范圍判斷
        if (val !== '') {
          if (!isNUll(min) && !isNUll(max)) {
            if (val < min || val > max) {
              val = '';
              isPrompt &&
                Message({
                  message: `${label}值的范圍應該是${min}-${max}`,
                  type: 'warning'
                });
            }
          } else if (!isNUll(min)) {
            if (val < min) {
              val = '';
              isPrompt &&
                Message({
                  message: `${label}值的最小值為${min}`,
                  type: 'warning'
                });
            }
          } else if (!isNUll(max)) {
            if (val > max) {
              val = '';
              isPrompt &&
                Message({
                  message: `${label}值的最大值為${max}`,
                  type: 'warning'
                });
            }
          }
        }
        // #endregion 值范圍判斷

        e.target.value = val;
        setVal(val);
      }
    };
    el.addEventListener('focusout', el._customData.blur);
  },
  /* eslint-disable no-unused-vars */
  unbind(el) {
    // 解綁
    if (el._customData && el._customData.blur) return;
    el.removeEventListener('focusout', el._customData.blur);
  }
});

2.div 盒子寬高變化觸發(fā)resize回調

/**
 * div resize
 * author: yf
 */
Vue.directive('resize', {
  bind: function(el, binding) {
    let callbackFn = binding.value; // div resize后的回調函數(shù)
    if (!callbackFn) return;

    let t = binding.arg; // arg:傳給指令的參數(shù),可選仅政。例如 v-resize:60 中垢油,參數(shù)為 "60"
    t = t === void 0 ? 100 : Number(t); // 防抖時間

    // console.log(callbackFn, t)

    let resizeBox = el;
    let domInfo = {
      width: 0,
      height: 0
    };
    let resizeObserver = new ResizeObserver(
      debounce(() => {
        let oldDomInfo = domInfo;
        let newDomInfo = (domInfo = getDomWH(el));
        try {
          // console.log('div resize ....');
          callbackFn &&
            callbackFn({
              resizeBox: el, // 當前 resize 的dom信息
              oldDomInfo, // resize 前的寬高信息
              newDomInfo // resize 后的寬高信息
            });
        } catch (e) {
          // console.error('div resize', e);
        }
      }, t)
    ); // 會在繪制前和布局后調用 resize 事件,因此不用提前調用 event_resize 方法

    el._vResize = resizeObserver;
    resizeObserver.observe(resizeBox);
  },
  unbind: function(el, binding) {
    let callbackFn = binding.value; // 回調函數(shù)
    if (!callbackFn) return;

    let resizeBox = el;
    let resizeObserver = el._vResize;
    if (!resizeObserver) return;
    resizeObserver.unobserve(resizeBox);
    delete el._vResize;
  }
});

3 input focus

/**
 * author: yf
 * date: 20250109
 * input focus
 * 注意:在 el-table 行編輯時使用此指令可能不會生效圆丹,因為 el-table 存在fixed列時滩愁,focus的是fixed table 中的 input
 * */
Vue.directive('input-focus', {
  inserted: function (el) {
    if(el.nodeName.toLocaleLowerCase() === 'input'){
      el.focus()
    }else{
      let input = el.querySelector('input')
      input && input.focus()
    }
  }
});

4 el-table 內某個el-input 的 td 掛載時focus

給el-input 綁定了 blur 事件時可能用到這個指令,因為如果沒觸發(fā)focus是不會觸發(fā) blur 事件的

// 組件內自定義指令
  directives: {
    'tableIn-elInput-focus': {
      // 指令的定義
      inserted: function (el, binding, vnode) {
        try {
          let tableInx = vnode.context.$refs['MaterialTable'] // 這個el-table 節(jié)點是綁定了ref的辫封, ref =“MaterialTable”
          if(!tableInx || !tableInx.$el) return
          // 因為el-table 表格在表格列 fixed 的時候會創(chuàng)建一模一樣的節(jié)點硝枉,有以下操作為了正確定位節(jié)點:
          let parentDom = tableInx.$el.querySelector('.el-table__body-wrapper')
          if(parentDom && parentDom!== el && parentDom.contains(el)){
            el.querySelector('.el-input__inner').focus()
          }
        }catch(e){
          console.error('tableIn-focus', e)
        }
      }
    }
  },

若對你有幫助,請點個贊吧倦微,若能打賞不勝感激妻味,謝謝支持!
本文地址:http://www.reibang.com/p/6af71018f716欣福,轉載請注明出處责球,謝謝。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末拓劝,一起剝皮案震驚了整個濱河市雏逾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌郑临,老刑警劉巖栖博,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異厢洞,居然都是意外死亡仇让,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門躺翻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丧叽,“玉大人,你說我怎么就攤上這事获枝〈勒” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵省店,是天一觀的道長嚣崭。 經常有香客問我,道長懦傍,這世上最難降的妖魔是什么雹舀? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮粗俱,結果婚禮上说榆,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好签财,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布串慰。 她就那樣靜靜地躺著,像睡著了一般唱蒸。 火紅的嫁衣襯著肌膚如雪邦鲫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天神汹,我揣著相機與錄音庆捺,去河邊找鬼。 笑死屁魏,一個胖子當著我的面吹牛滔以,可吹牛的內容都是我干的。 我是一名探鬼主播氓拼,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼你画,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了桃漾?” 一聲冷哼從身側響起撬即,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呈队,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唱歧,經...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡宪摧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了颅崩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片几于。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沿后,靈堂內的尸體忽然破棺而出沿彭,到底是詐尸還是另有隱情,我是刑警寧澤尖滚,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布喉刘,位于F島的核電站,受9級特大地震影響漆弄,放射性物質發(fā)生泄漏睦裳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一撼唾、第九天 我趴在偏房一處隱蔽的房頂上張望廉邑。 院中可真熱鬧,春花似錦、人聲如沸蛛蒙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牵祟。三九已至深夯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間课舍,已是汗流浹背塌西。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留筝尾,地道東北人捡需。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像筹淫,于是被迫代替她去往敵國和親站辉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353