Vue 實現(xiàn)點擊空白處隱藏某節(jié)點(三種方式:指令、普通哥放、遮罩)

在項目中往往會有這樣的需求: 彈出框(或Popover)在 show 后,點擊空白處可以將其 hide。
針對此需求柠衍,整理了三種實現(xiàn)方式,大家按實際情況選擇晶乔。

當然珍坊,我們做項目肯定會用到 UI 框架,常見的 Element 中的組件提供了這樣的方法正罢。
但是阵漏,就算使用框架,有些時候還是要用到的翻具,比如:

Element 中的 Popover履怯,當我們想使用手動方式(trigger 觸發(fā)方式為 manual時)控制它的 show & hide 的時候,就要自己實現(xiàn)這個功能啦裆泳。

第一種方式:最普通的手動監(jiān)聽判斷

<span ref="projectButton">
    <el-popover v-model="visible" trigger="manual" placement="bottom" @show="show" @hide="hide">
      <p>啦啦啦</p>
      <el-button slot="reference" type="primary" @click="visible = !visible">show</el-button>
    </el-popover>
</span>


data () {
 return {
    visible: false
  }
},
methods: {
  show () {
    document.addEventListener('click', this.hidePanel, false)
  },
  hide () {
    document.removeEventListener('click', this.hidePanel, false)
  },
  hidePanel (e) {
    if (!this.$refs.projectButton.contains(e.target)) {
      this.visible = false
      this.hide()
    }
  }
}

上面就是在 Popover show 的時候監(jiān)聽 document 的 click 事件虑乖,觸發(fā)進入 hidePanel 方法,判斷當前點擊的 el 是否在 Popover 內部晾虑,如果不在疹味,則手動 hide Popover ,并且移除監(jiān)聽事件帜篇。

這個還是蠻好理解的糙捺,我使用的也是這種方式,因為我的項目中需要這種需求的很少(好吧笙隙,就一個地方)洪灯,所以我采用了這種方式。


第二種方式: 指令

<template>
 <div>
 <div class="show" v-show="show" v-clickoutside="handleClose">
  顯示
 </div>
 </div>
</template>
 
<script>
const clickoutside = {
  // 初始化指令
  bind(el, binding, vnode) {
    function documentHandler(e) {
      // 這里判斷點擊的元素是否是本身竟痰,是本身签钩,則返回
      if (el.contains(e.target)) {
        return false;
  }
      // 判斷指令中是否綁定了函數(shù)
      if (binding.expression) {
        // 如果綁定了函數(shù) 則調用那個函數(shù),此處binding.value就是handleClose方法
        binding.value(e);
      }
 }
    // 給當前元素綁定個私有變量坏快,方便在unbind中可以解除事件監(jiān)聽
    el.__vueClickOutside__ = documentHandler;
    document.addEventListener('click', documentHandler);
  },
  update() {},
  unbind(el, binding) {
    // 解除事件監(jiān)聽
    document.removeEventListener('click', el.__vueClickOutside__);
    delete el.__vueClickOutside__;
  },
};
export default {
  name: 'HelloWorld',
  data() {
    return {
      show: true,
    };
  },
  directives: {clickoutside},
  methods: {
    handleClose(e) {
      this.show = false;
    },
  },
};
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.show {
  width: 100px;
  height: 100px;
  background-color: red;
}
</style>

上面這種是網上比較火的一種方式(實際我沒有測試過)铅檩,其實思路還是那個思路 (給document增加一個click事件監(jiān)聽,當發(fā)生click事件的時候判斷是否點擊的當前對象莽鸿,不是就隱藏)昧旨,優(yōu)點就是可以封裝成全局/局部的指令拾给,可多處使用。

下面簡單介紹下 vue 指令
一個指令定義對象可以提供如下幾個鉤子函數(shù) (均為可選):

  • bind:只調用一次兔沃,指令第一次綁定到元素時調用蒋得。在這里可以進行一次性的初始化設置。
  • inserted:被綁定元素插入父節(jié)點時調用 (僅保證父節(jié)點存在乒疏,但不一定已被插入文檔中)额衙。
  • update:所在組件的 VNode 更新時調用,但是可能發(fā)生在其子 VNode 更新之前怕吴。指令的值可能發(fā)生了改變入偷,也可能沒有。但是你可以通過比較更新前后的值來忽略不必要的模板更新 (詳細的鉤子函數(shù)參數(shù)見下)械哟。
  • componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后調用疏之。
  • unbind:只調用一次,指令與元素解綁時調用暇咆。

第三種方式:遮罩

<template>
  <div>
    <div class="mask" v-if="showModal" @click="showModal=false"></div>
    <div class="pop" v-if="showModal">
        <button @click="showModal=false" class="btn">點擊出現(xiàn)彈框</button>
    </div>
    <button @click="showModal=true" class="btn">點擊出現(xiàn)彈框</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showModal: false
    };
  }
};
</script>

<style scoped>
.mask {
  background-color: #000;
  opacity: 0.3;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1
}
.pop {
  background-color: #fff;
 
  position: fixed;
  top: 100px;
  left: 300px;
  width: calc(100% - 600px);
  height:calc(100% - 200px);
  z-index: 2
}
.btn {
  background-color: #fff;
  border-radius: 4px;
  border: 1px solid blue;
  padding: 4px 12px;
}
</style>

上面這個就是添加一個看不見的遮罩替代 document 锋爪,點擊遮罩就隱藏。但是要注意:mask(遮罩)層的層級(z-index)要比彈出的pop的層級低爸业。


覺得有幫助的小伙伴點個贊支持下~

覺得有幫助的小伙伴點個贊支持下~

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末其骄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扯旷,更是在濱河造成了極大的恐慌拯爽,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钧忽,死亡現(xiàn)場離奇詭異毯炮,居然都是意外死亡,警方通過查閱死者的電腦和手機耸黑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門桃煎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人大刊,你說我怎么就攤上這事为迈。” “怎么了缺菌?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵葫辐,是天一觀的道長。 經常有香客問我伴郁,道長耿战,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任蛾绎,我火速辦了婚禮昆箕,結果婚禮上鸦列,老公的妹妹穿的比我還像新娘租冠。我一直安慰自己鹏倘,他們只是感情好,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布顽爹。 她就那樣靜靜地躺著纤泵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪镜粤。 梳的紋絲不亂的頭發(fā)上捏题,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機與錄音肉渴,去河邊找鬼公荧。 笑死,一個胖子當著我的面吹牛同规,可吹牛的內容都是我干的循狰。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼券勺,長吁一口氣:“原來是場噩夢啊……” “哼绪钥!你這毒婦竟也來了?” 一聲冷哼從身側響起关炼,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤程腹,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后儒拂,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寸潦,經...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年社痛,在試婚紗的時候發(fā)現(xiàn)自己被綠了甸祭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡褥影,死狀恐怖池户,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情凡怎,我是刑警寧澤校焦,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站统倒,受9級特大地震影響寨典,放射性物質發(fā)生泄漏。R本人自食惡果不足惜房匆,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一耸成、第九天 我趴在偏房一處隱蔽的房頂上張望报亩。 院中可真熱鬧,春花似錦井氢、人聲如沸弦追。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽劲件。三九已至,卻和暖如春约急,著一層夾襖步出監(jiān)牢的瞬間零远,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工厌蔽, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留牵辣,地道東北人。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓奴饮,卻偏偏與公主長得像纬向,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拐云,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容