您当前的位置:首页 > 网站建设 > javascript
| php | asp | css | H5 | javascript | Mysql | Dreamweaver | Delphi | 网站维护 | 帝国cms | React | 考试系统 | ajax |

vue+element实现下拉菜单并带本地搜索功能示例详解

51自学网 2022-05-02 21:31:00
  javascript

需求:

后台返回数组对像,前端组合成数组,根据name组合成一个个数组并把后台返回的值当成一个children推入数组,在数组中自定义属性备份数据防止搜索的时候改变原数组使得数组无法回退

在这里插入图片描述
在这里插入图片描述

这里是用的vuex存储,因为多个页面使用同一个接口;所以没必要重复请请求
src/store/module/metadata.js

/* * @Author: your name * @Date: 2021-09-02 15:46:45 * @LastEditTime: 2021-09-16 17:39:53 * @LastEditors: Please set LastEditors * @Description: 控制台-数据接入-悬浮菜单 * @FilePath: /vue-ui/src/store/module/metadata.js *//** * 数据资源管理悬浮菜单数据 */import { Loading, Message } from 'element-ui'import { apiManager } from '@/plugins/ajax'let loadingInstanceconst state = {    allList: [],    navList: [],    name: {}}const mutations = {    SET_NAVLIST: (state, list) => {        // 使用深拷贝,防止页面搜索时报错        state.navList = list.map(item => {            if (item.children) {                item.backList = JSON.stringify(item.children)            }        })    },    SET_ALLLIST: (state, list) => {        state.allList = list    },    SET_NAME: (state, obj) => {        Object.assign(state.name, obj)    }}const actions = {    requestMetadata({ commit, state }, { name, navList }) {        return new Promise(resolve => {            const nameKey = Object.keys(state.name)            if (nameKey.indexOf(name) !== -1) {                //阻止重复请求                resolve(state.name[name])            } else {                loadingInstance = Loading.service()                state.name[name] = name                apiManager                    .post('/metadata/tableInfo/query')                    .then(res => {                        commit('SET_ALLLIST', res.data)                        for (const i in res.data) {                            const item = navList.find(v => v.name === i) //把传入的name和请回来的key(name)匹配放入                            if (item) {                                item.children = res.data[i] //把请求回来的每个对象下的数组放入对应的Item.children中                                item.navSearch = ''                                item.backList = [] //建立备份,在搜索的时候防止改变原数组                            }                        }                        commit('SET_NAVLIST', navList)                        commit('SET_NAME', { [name]: navList })                        resolve(navList)                        loadingInstance.close()                    })                    .catch(err => {                        resolve([])                        loadingInstance.close()                        Message.error(err)                    })            }        })    }}export default {    namespaced: true,    state,    mutations,    actions}

页面父组件使用子组件
src/views/console/dataAccessManage/dataResourceTable/FileXs.vue

 <transition name="component-fade" mode="out-in">   <floating-menu v-show="isCollapse" :newList='navList' @getDatails='getDatails' /></transition>
data() {      return {          navList: [              {                  imgSrc: require('./../../../../../public/images/m6.png'),                  name: 'ftp',                  typeName: 'FTP服务器',                  children: [],                  total: 0              },              {                  imgSrc: require('./../../../../../public/images/m5.png'),                  name: 'txt',                  typeName: '文件服务器',                  children: [],                  total: 0              }          ],             },  async mounted() {    const param = {        name: 'fileXs',        navList: this.navList    }    // 请求vuex    this.navlist = await this.$store.dispatch('metadata/requestMetadata', param)},

子组件
src/views/console/dataAccessManage/components/floatingMenu.vue

<!-- * @Author: your name * @Date: 2021-09-02 14:01:58 * @LastEditTime: 2021-09-16 17:43:10 * @LastEditors: Please set LastEditors * @Description: 数据资源表中悬浮菜单 * @FilePath: /vue-ui/src/views/console/dataAccessManage/components/floatingMenu.vue--><template>    <div class="data-sheet-main__nav" v-if="sjktcList.length || newList.length">        <div>            <div class="nav__item" v-for="(item,index) in sjktcList" :key="'info2-' + index">                <div class="item_name sjk_name" :class="{ sjk_active: sjkActive == index }" @click="sjktcShow(item.type,index)">{{item.typeName}}</div>            </div>        </div>        <!-- file -->        <el-collapse class="nav__item" v-model="activeNames">            <el-collapse-item class="item_name" :title="item.typeName" :name="item.typeName" v-for="(item,index) in newList" :key="index">                <ul class="nav__item__list">                    <li class="list__li">                        <el-input v-input-val-bg v-model="item.navSearch" @input="handleNavSearch(item)" prefix-icon="el-icon-search" size="mini" placeholder="请输入关键字" clearable></el-input>                    </li>                    <li v-for="(key,i) in item.children" :key="i" :class="{ 'list__li--active': key.id == dbId }" class="list__li" @click="getDatails(key,item)">                        <span :title="key.name" class="list--title">{{key.name}}</span>                        <span class="list--count">{{key.total || 0}}</span>                    </li>                    <li class="no-data" v-if="!item.children.length">暂无数据</li>                </ul>            </el-collapse-item>        </el-collapse>    </div></template><script>import { debounce } from '@/utils'export default {    name: 'floatingMenu',    props: {        sjktcList: {            type: Array,            default: () => []        },        newList: {            type: Array,            default: () => []        }    },    components: {},    data() {        return {            sjkActive: 0,            navSearch: '',            navChildData: [],            dbId: '',            activeNames: []        }    },    mounted() {    },    methods: {        // 点击列表中的内容        getDatails(args, db) {            this.dbId = args.id            this.$emit('getDatails', { args, db })        },        // eslint-disable-next-line space-before-function-paren        handleNavSearch: debounce(function (obj) {            this.$forceUpdate()//防止input框赋值失败            const currlist = JSON.parse(obj.backList)            if (obj.navSearch == '') {                obj.children = currlist            } else {                obj.children = currlist.filter(item => {                    return item.name.toLowerCase().indexOf(obj.navSearch.toLowerCase()) != -1                })            }        }, 100),        sjktcShow(type, i) {            this.sjkActive = i            this.$emit('sjktcShow', [type])        }    },    watch: {        newList: {            deep: true,            handler(list) {                if (list) {                    // 默认激活显示展开list下的0个菜单                    for (let i = 0; i < list.length; i++) {                        const item = list[i]                        if (!this.dbId && item.children.length) {                            this.activeNames = item.typeName                            this.getDatails(item.children[0], item)//默认请求第一条数据内容                        }                    }                }            }        }    }}</script><style lang='scss' scoped>.data-sheet-main__nav {    width: 180px;    position: absolute;    top: 0px;    left: -190px;    z-index: 100;    background: #fff;    border: 1px solid #6579fe;    padding-top: 10px;    .sjk_active {        color: $theme !important;    }    .nav__item {        position: relative;        margin-bottom: 15px;        .item_name {            width: 100%;            display: inline-block;            padding-left: 17px;            font-size: 14px;            line-height: 24px;            color: rgba(0, 0, 0, 0.85);            /deep/.el-collapse-item__header {                font-weight: bold;                border-bottom: none;                position: relative;                padding-left: 15px;                .el-collapse-item__arrow {                    position: absolute;                    left: 0;                    transform: rotate(270deg);                }                .el-collapse-item__arrow.is-active {                    transform: rotate(90deg);                }            }            &:hover {                cursor: pointer;            }        }        .no-data {            text-align: center;            color: #999;            padding: 10px 0;            width: 100%;        }        img {            width: 100%;            height: 50px;        }        .nav__item--total {            position: absolute;            display: block;            width: 30px;            height: 30px;            background: #fff;            border: 1px solid #ccc;            border-radius: 50%;            line-height: 30px;            border: 1px solid #71b1ec;            box-shadow: 0 3px 6px #156d90;            text-align: center;            color: #fd0b0b;            font-size: 16px; /*no*/            top: 0;            right: 0;            transform: translate(25%, -20%);        }        .nav__item__list {            display: flex;            max-height: 246px;            overflow-y: auto;            flex-wrap: wrap;            .list__li {                width: 100%;                margin-top: 5px;                line-height: 30px;                padding: 0 6px 0 17px;                position: relative;                cursor: pointer;                color: #333;                &:hover {                    color: $blue;                }                .list--title {                    width: 90px;                    overflow: hidden;                    text-overflow: ellipsis;                    white-space: nowrap;                    float: left;                    &:hover {                        color: #409eff;                    }                }                .list--count {                    color: #46a0fc;                    float: right;                }            }            .list__li--active {                color: $blue;            }        }    }    /deep/.el-collapse {        border-top: none;    }}.data-sheet-main__list {    flex: 1;    margin-left: 20px;    .list-header {        flex-direction: column;        .order {            text-align: right;            a {                background: #6579fe;                font-family: PingFangSC-Regular;                font-size: 12px;                line-height: 22px;                color: #ffffff;                padding: 6px;                border-radius: 4px;            }        }    }    .handler--fixed-right {        padding: 25px 10px;    }    .nodata {        text-align: center;        font-size: 16px;    }}</style>

到此这篇关于vue+element实现下拉菜单并带本地搜索功能的文章就介绍到这了,更多相关vue element下拉菜单搜索内容请搜索wanshiok.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持wanshiok.com!


深入浅出探究JavaScript中的async与await
关于怎么在vue项目里写react详情
51自学网,即我要自学网,自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1