Vue.js自定義下拉選單,如何實現在下拉選單區域外點選即可關閉下拉選單的功能
在開發過程中,為了效果好看,往往需要自己開發一個下拉選單,而不是使用 HTML 自身的 select 下拉選單。然而當編寫自定義下拉選單的時候,就會碰到一個問題:如果使用者在下拉選單的範圍外進行滑鼠點選的操作,如何關閉已經開啟的下拉選單?
解決思路如下:在 DOM 的根節點上新增一個 click 事件,同時下拉選單內阻止事件的預設行為和冒泡。當響應這個點選事件的時候,說明是在下拉選單範圍外的點選(因為下拉選單內阻止了事件的冒泡),就可以關閉已經開啟的下拉選單。
如果是純 JS 程式碼,有人可能會使用 document.onclick
來新增根節點事件。不過,我現在使用 Vue.js,會選擇使用 Vue.js 的方式處理這個問題。
Vue.js 使用元件化的方式組織程式碼,會有一個根元件,可以在這個根元件上加上 @click
事件,來響應區域外的點選事件。在一個完整的應用中,可能有多種場景需要這種區域外點選關閉的功能。除了最普通的表單裡的下拉選單外,還可能是網站右上角的訊息提示框,或者選單。比較合適的做法是把點選事件的具體處理邏輯放到各個元件中去。
那麼如何讓各個子元件響應根元件上的點選事件呢?可以使用Vuex來做到這一點。在這裡 Vuex 起到了元件之間互相傳遞資訊的作用。
讀者可以在這個網址下載我編寫的 Demo 專案:http://download.csdn.net/detail/zhangchao19890805/9855750。
推薦讀者使用 yarn install
安裝所需的依賴。
下面說一下關鍵程式碼:
程式入口 main.js:
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import routes from './router'
import VueSuperagent from 'vue-superagent'
import Vuex from 'vuex'
import 'babel-polyfill';
import store from './vuex/store';
Vue.use(VueRouter);
Vue.use(VueSuperagent);
Vue.use(Vuex);
const router = new VueRouter({
mode: 'history',
routes
})
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
根節點 App.vue,新增了點選事件。
<template>
<div @click="clickRoot">
<router-view></router-view>
</div>
</template>
<script>
export default {
methods:{
clickRoot(event){
this.$store.dispatch("clickRootNumAction", 1);
}
}
}
</script>
Vuex 檔案結構
vuex
│
└─modules
├─clickRoot
│ ├─actions.js
│ ├─getters.js
│ ├─index.js
│ └─mutations.js
│
└─store.js
actions.js
export default {
// action 允許非同步載入,實際專案中
// 這裡可以發起個請求,再返回。
clickRootNumAction(context, value) {
context.commit('clickRootNum', value);
}
}
getters.js
export default {
getClickRootNum(state) {
return state.clickRootNum;
}
}
index.js
import actions from './actions'
import getters from './getters'
import mutations from './mutations'
const state = {
clickRootNum: 0
}
export default {
state,
actions,
getters,
mutations
}
mutations.js
export default {
clickRootNum(state, value) {
let sum = state.clickRootNum + value
state.clickRootNum = sum;
}
}
store.js
import Vue from 'vue';
import Vuex from 'vuex';
import clickRoot from './modules/clickRoot'
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== 'production';
export default new Vuex.Store({
modules: {
clickRoot
},
strict: debug
})
頁面程式碼 test.vue
<template>
<div >
<p>測試</p>
<table>
<tbody>
<tr>
<td style="vertical-align: top;">
<div class="dropDownList">
<button class="controll" @click.prevent.stop="listShow()"
@keydown.prevent.40="arrowDown1" @keydown.prevent.38="arrowUp1">
{{selectItem}}
<span :class="['triangle',showList==false?'triangleShow':'triangleHidden']"></span>
</button>
<ul class="showList" v-if="showList" @click.prevent.stop>
<input v-model="filterText" class="search"/>
<li v-for="item in newObj" class="optionArea" @click="selectOption(item)"> {{item.type}} </li>
</ul>
</div>
</td>
<td style="vertical-align: top;">
<div class="dropDownList">
<button class="controll" @click.prevent.stop="listShow2()"
@keydown.prevent.40="arrowDown2" @keydown.prevent.38="arrowUp2">
{{selectItem2}}
<span :class="['triangle',showList2==false?'triangleShow':'triangleHidden']"></span>
</button>
<ul class="showList" v-if="showList2" @click.prevent.stop>
<input v-model="filterText2" class="search"/>
<li v-for="item in newObj2" class="optionArea" @click="selectOption2(item)"> {{item.type}} </li>
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data(){
return {
showList:false,
obj:[
{type:"男裝"},
{type:"女裝"},
{type:"童裝"},
{type:"老年裝"},
],
filterText:"",
selectItem:"請選擇",
showList2:false,
obj2:[
{type:"賓士"},
{type:"桑塔納"},
{type:"大眾"},
{type:"比亞迪"},
],
filterText2:"",
selectItem2:"請選擇"
};
},
methods:{
listShow(){
this.showList=!this.showList;
if (this.showList2) {
this.showList2 = false;
}
},
selectOption(item){
this.selectItem=item.type;
this.showList=false;
},
// 第一個下拉選單 按鍵:向下的箭頭
arrowDown1(e){
if (!this.showList) {
this.showList = true;
}
if (this.showList2) {
this.showList2 = false;
}
},
// 第一個下拉選單 按鍵:向上的箭頭
arrowUp1(e){
if (this.showList) {
this.showList = false;
}
if (this.showList2) {
this.showList2 = false;
}
},
listShow2(){
this.showList2=!this.showList2;
if (this.showList) {
this.showList = false;
}
},
selectOption2(item){
this.selectItem2=item.type;
this.showList2=false;
},
// 第二個下拉選單 按鍵:向下的箭頭
arrowDown2(e){
if (!this.showList2) {
this.showList2 = true;
}
if (this.showList) {
this.showList = false;
}
},
// 第一個下拉選單 按鍵:向上的箭頭
arrowUp2(e){
if (this.showList2) {
this.showList2 = false;
}
if (this.showList) {
this.showList = false;
}
}
},
computed:{
newObj:function(){
let self = this;
return self.obj.filter(function (item) {
return item.type.toLowerCase().indexOf(self.filterText.toLowerCase()) !== -1;
})
},
newObj2:function(){
let self = this;
return self.obj2.filter(function (item) {
return item.type.toLowerCase().indexOf(self.filterText2.toLowerCase()) !== -1;
})
}
},
watch:{
'$store.getters.getClickRootNum': function () {
if (this.showList){
this.showList = false;
}
if (this.showList2) {
this.showList2 = false;
}
}
}
};
</script>
<style lang="scss" rel="stylesheet/scss" scoped>
.dropDownList{
margin-left:50px;
width: 150px;
.controll{
position: relative;
width: 150px;
border: 1px solid #E3E9EF;
cursor: pointer;
.triangle{
display: inline-block;
position: absolute;
top: 7px;
right: 10px;
cursor: pointer;
}
.triangleHidden{
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-bottom: 8px solid #676F7F;
}
.triangleShow{
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 8px solid #676F7F;
}
}
.showList{
margin: 0;
padding: 0;
border: 1px solid #E3E9EF;
// padding-top: 5px;
padding-bottom: 5px;
margin-top: 2px;
width: 145px;
.search{
width: 141px;
border: 1px solid #E3E9EF;
}
.optionArea{
list-style: none;
cursor: pointer;
font-size: 14px;
margin-left: 5px;
&:hover{
background-color: #B2CFEB;
color: #fff;
}
}
}
}
</style>
相關文章
- Flutter 自定義功能強大的下拉篩選選單 packageFlutterPackage
- checkbox及css實現點選下拉選單CSS
- vue下拉選單Vue
- 下拉選單「點選外面關閉」的終極解決方案
- vue點選空白區域,下拉選單隱藏Vue
- kendoUI 多選下拉選單 kendoMultiSelectUI
- HTML select 下拉選單HTML
- HTML select下拉選單HTML
- 微信小程式下拉選單自定義元件微信小程式元件
- HTML+CSS實現下拉選單HTMLCSS
- HTML+CSS+JQuery實現下拉選單滑鼠懸浮顯示下拉選單,取消隱藏HTMLCSSjQuery
- android短視訊開發,自定義下拉選單Android
- CSS 二級下拉選單CSS
- jQuery 美化select下拉選單jQuery
- CSS二級下拉選單CSS
- 圓角select下拉選單
- antd design Menu選單下拉回撥以及下拉選單時只能顯示一個列表,其餘關閉
- 使用Vue實現下拉選單框批量新增選項Vue
- vue使用iview實現單選,禁選,下拉框的效果VueView
- WPF實現樹形下拉選單框(TreeComboBox)
- jquery實現四級級聯下拉選單jQuery
- 選擇select下拉選單網頁跳轉網頁
- JQuery實現絢麗的橫向下拉選單jQuery
- 【Android初級】如何實現一個有動畫效果的自定義下拉選單Android動畫
- JavaScript帶下拉選單的文字框JavaScript
- 滑鼠移上去出現下拉選單
- JavaScript滑鼠懸浮出現下拉選單效果JavaScript
- Unclutter for mac多功能下拉選單隱藏工具Mac
- PHP中如何獲取下拉選單的值PHP
- 函式節流實現滑動下拉選單函式
- 012---表單、下拉選單和表單域
- 使用 Java 在Excel中建立下拉選單JavaExcel
- Selenium測試form表單之下拉選單ORM
- 模擬select下拉選單詳解
- 下拉選單框和滾動條
- css滑鼠懸浮下拉選單效果CSS
- CSS導航欄及下拉選單CSS
- jQuery與CSS二級下拉選單jQueryCSS
- 滑鼠經過顯示下拉選單