v-auto-disable

現(xiàn)在有個(gè)場景,需要轉(zhuǎn)賬盗冷。當(dāng)點(diǎn)擊按鈕提交的時(shí)候怠苔,調(diào)用后端接口實(shí)現(xiàn)轉(zhuǎn)賬,有時(shí)候會出現(xiàn)誤點(diǎn)擊仪糖,用戶連續(xù)點(diǎn)擊N次按鈕柑司,那么就會發(fā)生N比轉(zhuǎn)賬。
對于以上場景锅劝,解決方法之一就是:在一筆轉(zhuǎn)賬請求返回響應(yīng)結(jié)果之前disable按鈕攒驰,使得后續(xù)點(diǎn)擊失效,angular對此提供了一個(gè)插件ng-auto-disable故爵,在寫Vue代碼的時(shí)候玻粪,對應(yīng)寫了一個(gè)基于Vue的auto-disable
注意:此處,統(tǒng)一給disable的元素添加了一個(gè)classis-disabled樣式


import Vue from 'vue'
const EVENT = {
  click: 'click',
  submit: 'submit'
}

/**
 * <button
 *   v-auto-disable="confirm"
 *   @click="confirm">
 *   confirm
 * </button>
 *
 * inform:
 *   confirm() must return a Promise
 *   not only support button, but also for any html labels
 *
 */

const toggleDisable = el => {
  if (el.getAttribute('disabled')) {
    el.removeAttribute('disabled')
    el.classList.remove('is-disabled')
  } else {
    el.setAttribute('disabled', 'disabled')
    el.classList.add('is-disabled')
  }
}

function disableButton (el, flag = true) {
  el.__scheduled = flag
  toggleDisable(el)
  console.log('begin ' + (flag ? 'disable' : 'enable'))
}

function checkBindingValue (val) {
  if (val instanceof Array) {
    let fn = val[0]
    let args = val[1]
    if (!(fn instanceof Function)) {
      console.error('the first element of the array must be a function handle the event')
      return ''
    }
    if (!(args instanceof Array)) {
      console.error('the second element is an array, it is the params of the event handler')
      return ''
    }
    return {
      fn,
      args
    }
  } else if (val instanceof Function) {
    return {
      fn: val,
      args: ''
    }
  }
  console.error('autoDisable must accept a Array or an Function, like v-auto-disable.click="[handleClick, [param1, param2, ..., paramn]]" or v-auto-disable.click="handleClick"')
  return null
}
/**
 * v-auto-disable Accept an Array or a Function
 * when accept an array诬垂,the first element is the funtion name of the v-auto-disable event handler and the second element is arguments of the Function
 *    v-auto-disable.click="[handleClick, [param1, param2, ..., paramn]]"
 * when accept a function, it the the v-auto-disable event handler
 *    v-auto-disable.click="handleClick"
 */
Vue.directive('autoDisable', {
  bind (el, binding, vnode) {
    // let fn = binding.value
    let fnObj = checkBindingValue(binding.value)
    if (!fnObj) {
      return
    }
    let { fn, args } = fnObj
    el.__eName = binding.modifiers.submit ? EVENT.submit : (binding.modifiers.click ? EVENT.click : '')
    // let v_listener = vnode.data.on || (vnode.componentInstance && vnode.componentInstance.$listeners)
    // console.log(v_listener)
    if (!el.__eName) {
      console.error('please define the event modified by auto-disable')
    }
    el.__listener = async function () {
      let cb = fn(...args)
      if (!isPromise(cb)) {
        console.error(cb, binding, 'autoDisable must accept a valid Function which return a Promise!')
        return
      }
      if (el.__scheduled) {
        return
      }
      try {
        disableButton(el)
        cb
          .catch(e => {
            throw e
          })
          .finally(() => disableButton(el, false))
      } catch (e) {
        console.error(e.message)
      }
    }
    el.addEventListener(el.__eName, el.__listener, true)
  },
  unbind (el, binding, vnode) {
    el.removeEventListener(el.__eName, el.__listener, true)
  }
})

function isPromise (promise) {
  return promise && (promise.then instanceof Function)
}

此處劲室,可以傳入一個(gè)函數(shù)或者數(shù)組
傳入數(shù)組:v-auto-disable.click="[handler, [param1, param2, ..., paramn]]",第一個(gè)參數(shù)是處理函數(shù)handler结窘,第二個(gè)函數(shù)是handler的參數(shù)痹籍。
傳入一個(gè)函數(shù)名v-auto-disable.click="handler"
.click是修飾詞,表示在click事件時(shí)觸發(fā)handler晦鞋。也可以是v-auto-disable.submit

開始的時(shí)候蹲缠,v-auto-disable.click="[handleClick, [param1, param2, ..., paramn]]"是想寫成v-auto-disable.click="handleClick(param1, param2, ..., paramn)"的形式棺克,在directive綁定至組件上時(shí)候,會計(jì)算binding.value的值线定,handleClick(param1, param2, ..., paramn)就會在directive綁定的時(shí)候而不是發(fā)生相應(yīng)事件的時(shí)候觸發(fā)執(zhí)行娜谊。

一些思考,也是本人最初的想法模仿ng-autodisable的方式來構(gòu)造v-auto-disable斤讥,也就是如@click="handleClick(param1, param2, ..., paramn)" v-auto-disable.click=""纱皆。首先說一下ng-autodisable的思想是:獲取對應(yīng)事件的handlers --> 使用unbind方法移除監(jiān)聽事件 --> 添加監(jiān)聽事件,監(jiān)聽事件的回調(diào)函數(shù)首先disable按鈕之類的元素芭商,再調(diào)用handlers(handlers要求返回promise)派草,在promise被resolve之后,重新enable按鈕之類的元素铛楣。Vue避免直接操作DOM元素近迁,沒有提供unbind之類的方法,所以最后放棄了簸州,也沒繼續(xù)深入研究鉴竭,有想法的朋友,也歡迎提供更好的解決方案岸浑。代碼中注釋掉的v_listener可以獲取到綁定在元素上的事件搏存,比如let clickEvent = v_listener.click

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市矢洲,隨后出現(xiàn)的幾起案子璧眠,更是在濱河造成了極大的恐慌,老刑警劉巖读虏,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛆橡,死亡現(xiàn)場離奇詭異,居然都是意外死亡掘譬,警方通過查閱死者的電腦和手機(jī)泰演,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來葱轩,“玉大人睦焕,你說我怎么就攤上這事⊙ス埃” “怎么了垃喊?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袜炕。 經(jīng)常有香客問我本谜,道長,這世上最難降的妖魔是什么偎窘? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任乌助,我火速辦了婚禮溜在,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘他托。我一直安慰自己掖肋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布赏参。 她就那樣靜靜地躺著志笼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪把篓。 梳的紋絲不亂的頭發(fā)上纫溃,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天,我揣著相機(jī)與錄音韧掩,去河邊找鬼紊浩。 笑死,一個(gè)胖子當(dāng)著我的面吹牛揍很,可吹牛的內(nèi)容都是我干的郎楼。 我是一名探鬼主播万伤,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼窒悔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敌买?” 一聲冷哼從身側(cè)響起简珠,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎虹钮,沒想到半個(gè)月后聋庵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芙粱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年祭玉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片春畔。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡脱货,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出律姨,到底是詐尸還是另有隱情振峻,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布择份,位于F島的核電站扣孟,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏荣赶。R本人自食惡果不足惜凤价,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一鸽斟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧料仗,春花似錦湾盗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氛改,卻和暖如春帐萎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胜卤。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工疆导, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人葛躏。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓澈段,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舰攒。 傳聞我的和親對象是個(gè)殘疾皇子败富,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,030評論 0 2
  • 1.JQuery 基礎(chǔ) 改變web開發(fā)人員創(chuàng)造搞交互性界面的方式。設(shè)計(jì)者無需花費(fèi)時(shí)間糾纏JS復(fù)雜的高級特性摩窃。 1....
    LaBaby_閱讀 1,171評論 0 1
  • ??JavaScript 是一種極其靈活的語言猾愿,具有多種使用風(fēng)格鹦聪。 ??一般來說,編寫 JavaScript 要么...
    霜天曉閱讀 744評論 0 0
  • 這個(gè)不錯(cuò)分享給大家蒂秘,從扣上看到的泽本,就轉(zhuǎn)過來了 《電腦專業(yè)英語》 file [fail] n. 文件;v. 保存文...
    麥子先生R閱讀 6,564評論 5 24
  • 自從有了拷貝臺,我就可以拷貝復(fù)雜的圖畫了段化,不過今天的配色和厚度沒有掌握好嘁捷,沒有畫出少年如玉的感覺,不過我好喜歡門的...
    倉央梅朵閱讀 442評論 3 2