Vue.js自定义下拉列表,如何实现在下拉列表区域外点击即可关闭下拉列表的功能
来源:互联网 发布:淘宝开店一件代发经验 编辑:程序博客网 时间:2024/05/20 02:26
在开发过程中,为了效果好看,往往需要自己开发一个下拉列表,而不是使用 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>
- Vue.js自定义下拉列表,如何实现在下拉列表区域外点击即可关闭下拉列表的功能
- Android自定义点击下拉列表
- ABAP如何自定义下拉列表
- ABAP如何自定义下拉列表
- 下拉列表实现(自定义)
- 使用PopupWindow实现的自定义下拉列表
- Android自定义控件实现下拉列表刷新,上拉刷新
- DataSet&DataTable如何绑定下拉列表控件获取不重复的值,如何添加一列自定义文字,并在下拉列表控件中显示自定义文字[winform学习实例]
- JS实现下拉列表联动
- js+div实现的下拉列表
- js 实现下拉列表的重复利用
- Android实现RecyclerView自定义列表、点击事件以及下拉刷新
- Android实现RecyclerView自定义列表、点击事件以及下拉刷新
- 自定义Spinner下拉列表
- mvchtmlstring 自定义下拉列表
- Spinner自定义下拉列表
- Android 自定义下拉列表
- ios自定义下拉列表
- gerrit及git的基本安装使用
- XML+DTD+SAX+DOM4j+Schema
- SpringBoot搭建Java web工程
- HDU3746:Cyclic Nacklace
- 状压DP<旅行商问题>
- Vue.js自定义下拉列表,如何实现在下拉列表区域外点击即可关闭下拉列表的功能
- 初学-HTML
- PCL_超体聚类实现
- (一) CentOS7下RPM安装MYSQL-5.7.18
- C++中子类构造函数写法总结
- 排序算法C++ && Python实现---堆排序
- 计蒜客 商汤科技的行人检测(困难)
- Effective Java
- 如何在word文档中插入参考文献,并管理参考文献