阅读 178

简单的vue下拉组件

自己写组件还是非常快乐的事情,所以决定从简单组件开始练手,也跟大家一起学习和成长。

工作中,经常遇到需要输入input,请求后台数据再渲染下拉列表的情况。类似于element-ui的select组件。但element组件必须输入item后再点击select-item,input的值才能录入。于是就有了想法,自己写一个可输入的下拉组件。

不啰嗦上干货~

组件结构分析


index.vue

<template><div class="dropdown-container"  v-clickOutside="hide">   <!--slot 无法绑定事件 -->    <div @click="handleClick"><slot></slot></div>    <slot name="dropdown"></slot></div></template>复制代码

首先看下模板, v-clickOutside 和 handleClick 实现下拉框组件的显示和隐藏。组件调用方不用关心如何控制dropdown的显示和隐藏。

<script>import Clickoutside from 'element-ui/src/utils/clickoutside';import Emitter from 'element-ui/src/mixins/emitter';export default {  name: 'dropdown',  componentName: 'dropdown',  mixins: [Emitter],  directives: {    Clickoutside  },  data() {    return {      visible: false    }  },  props: {  },  methods: {     hide() {       this.visible = false     },     handleMenuItemClick(command, instance) {      this.visible = false;      this.$emit('command', command, instance);     },     handleClick(e) {        this.visible = true     }  },  watch: {   visible(val) {     this.broadcast('dropdownMenu', 'visible', val);   }  },  mounted() {    this.$on('menu-item-click', this.handleMenuItemClick);  }}</script>复制代码

引入clickOutSide、emiiter。不了解这两个插件的可以自行补充一下,这里不做详细阐述。 this.broadcast('dropdownMenu', 'visible', val);将父组件的visible属性,传给子组件dropdownMenu

this.$on('menu-item-click', this.handleMenuItemClick);
handleMenuItemClick
// 当menu-item被点击后,将事件传给command复制代码

<style lang="less">.dropdown-container {  display: inline-block;  ul {    position: absolute;    top: 50px;    background-color: #283340;    border: 1px solid #7e8b9d;    max-height: 400px;    padding: 5px;    white-space: nowrap;    li {      cursor: pointer;      a {        max-width: 300px;        line-height: 25px;        text-overflow: ellipsis;        white-space: nowrap;        overflow: hidden;        color: #fff;        line-clamp: 2;        &:hover {          color: #fff;        }      }    }  }}</style>复制代码

dropdown-menu.vue

这个部分逻辑很简单,直接上代码

<template>  <transition name="el-zoom-in-top">    <ul v-show="showPopper">      <slot></slot>    </ul>  </transition></template>
<script>  export default {    name: 'dropdownMenu',    componentName: 'dropdownMenu',    props: {      visibleArrow: {        type: Boolean,        default: true      },      arrowOffset: {        type: Number,        default: 0      }    },    data() {      return {        showPopper: false      };    },    created() {      this.$on('visible', val => {        this.showPopper = val;      });    }  }</script>
复制代码

设置transition特效,showPopper控制dropdown-menu的显示和隐藏。index.vue 广播过来的visible事件,来改变showPopper的值。

dropdown-item.vue

最巧妙的设计在于command和menu-item-click之间的关联。避免我们在外部调用该组件的时候,还要手动添加点击事件。

<template>  <li    class="dropdown-menu__item"    @click="handleClick"  >    <slot></slot>  </li></template><script>  import Emitter from 'element-ui/src/mixins/emitter';  export default {    name: 'dropdownItem',    mixins: [Emitter],    props: {      command: {}    },    methods: {      handleClick(e) {        this.dispatch('dropdown', 'menu-item-click', [this.command, this]);      }    }  };</script>复制代码

用到Emitter,将menu-click-click事件广播给dropdown,然后通过command暴露给外部组件。props:command来存储点击选中的值。

是不是这个组件非常简单就实现了呢?

接下来看我们怎么调用

template

 <dropdown @command="handleCommand">    <el-input v-model="value" @input="handleInput"  laceholder="请输入具体地址" />  <dropdown-menu slot="dropdown">       <dropdown-item :command="item" v-for="(item,index) in list" :key="index" @click="syncInput(item.value)">{{item.address}}</dropdown-item>       <dropdown-item v-if="areaList.length === 0">暂无数据</dropdown-item>   </dropdown-menu>   </dropdown>复制代码

script

<script>
export default {
  data(){
    return {
      value:"",
       list:[{value:'a',key:1}] 
      }
    },
   methods:{
      handleCommand(command) {       this.value = command.value    },    handleInput(){
       // 处理业务逻辑
    }
    }
}
</script>复制代码

是不是so easy!


如果想要源码请关注我的git



关注下面的标签,发现更多相似文章
评论