使用vue來開發一個下拉菜單組件(1)


一、新建demo工程

vue init webpack-simple demo

添加src/mixins/emitter.js文件(見前幾篇博文)

安裝font-awesome字體庫:

cnpm install font-awesome --save

配置webpack.config.js,引入字體文件:

{
  test: /\.(otf|eot|ttf|woff|woff2)$/,
  loader: 'file-loader'
}

在src/main.js中引入font-awesome:

import '../node_modules/font-awesome/css/font-awesome.min.css'

二、組件設計

新建src/components/mySelect.vue和myOption.vue文件

1) 先來設計選項組件,這個比較簡單

先來考慮一下使用場景,一般的下拉菜單都是由無序列表組成,而選項則是一個個列表項:

但是直接slot標簽很可能會出現重名,所以需要分別prop一個label和value,其中value是必須的,如果沒有slot標簽則顯示label,所以myOption的基本結構為:

<template>
  <li class="my-option">
    <span v-if="!$slots.default">{{ label }}</span>
    <slot></slot>
  </li>
</template>

<script>
import emitter from "../mixins/emitter";

export default {
  name: "myOption",
  mixins: [emitter],
  props: {
    label: {
      type: String,
      default: "empty-label"
    },
    value: {
      type: String,
      required: true
    }
  }
};
</script>

然后來考慮一下myOption可能會存在的狀態,選項有選擇和取消兩種事件,對應的狀態就是是否已經被選擇,而且選擇的狀態需要高亮顯示:

先來加一個狀態:

data() {
  return {
    selected: true
  }
}

然后在最外層的li添加一個selected類名和一個右浮的check圖標(可以用v-show="selected"來控制顯示,我這里用css與文字顏色一起控制):

<template>
  <li :class="['my-option', { selected: selected }]">
    <span v-if="!$slots.default">{{ label ? label : value }}</span>
    <slot></slot>
    <i class="fa fa-check pull-right">&nbsp;</i>
  </li>
</template>

css代碼:

<style lang="scss" scoped>
.my-option {
  > .fa-check {
    display: none;
  }
  &.selected {
    color: blue;
    > .fa-check {
      display: inline;
    }
  }
}
</style>

由於父組件select需要接收label的值,而prop不能改變,只好再定義一個myLabel標簽,然后通過事件發送給父級:

myLabel: this.label || this.value

先后添加點擊事件和監聽的選擇/取消事件:

methods: {
  handleClick() {
    this.dispatch(
      "mySelect",
      "option-click",
      this.selected,
      this.myLabel,
      this.value
    );
  }
},
created() {
  this.$on("select", value => {
    if (this.value === value) {
      this.selected = true;
    }
  });
  this.$on("cancel", value => {
    if (this.value === value) {
      this.selected = false;
    }
  });
}

然后,不帶樣式的選項組件基本就完成了,完整代碼如下:

<template>
  <li :class="['my-option', { selected: selected }]">
    <span v-if="!$slots.default">{{ myLabel }}</span>
    <slot></slot>
    <i class="fa fa-check pull-right">&nbsp;</i>
  </li>
</template>

<script>
import emitter from "../mixins/emitter";

export default {
  name: "myOption",
  mixins: [emitter],
  props: {
    label: {
      type: String,
      default: ""
    },
    value: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      selected: false,
      myLabel: this.label || this.value
    };
  },
  methods: {
    handleClick() {
      this.dispatch(
        "mySelect",
        "option-click",
        this.selected,
        this.myLabel,
        this.value
      );
    }
  },
  created() {
    this.$on("select", value => {
      if (this.value === value) {
        this.selected = true;
      }
    });
    this.$on("cancel", value => {
      if (this.value === value) {
        this.selected = false;
      }
    });
  }
};
</script>

<style lang="scss" scoped>
.my-option {
  > .fa-check {
    display: none;
  }
  &.selected {
    color: blue;
    > .fa-check {
      display: inline;
    }
  }
}
</style>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM