用vue写的一个级联选择器

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title></title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    * {
      padding: 0;
      margin: 0;
      box-sizing: border-box;
    }

    a {
      text-decoration: none;
    }

    .clearfix:before,
    .clearfix:after {
      content: ' ';
      display: table;
    }

    .clearfix:after {
      clear: both;
    }

    input {
      outline: none;
    }

    ol,
    ul {
      list-style: none;
    }

    body {
      padding: 20px;
    }

    .select-box {
      position: relative;
    }

    .select-box .curr {
      width: 240px;
      padding-left: 15px;
      padding-right: 30px;
      border: 1px solid #ddd;
      border-radius: 5px;
      height: 40px;
      line-height: 40px;
      font-size: 14px;
      position: relative;
      z-index: 15;
      background-color: white;
    }

    .select-box .curr:hover {
      border-color: #aaa;
      cursor: pointer;
    }

    .arrow {
      position: absolute;
      right: 10px;
      top: 17px;
      display: block;
      width: 10px;
      height: 10px;
      border-left: 1px solid #aaa;
      border-top: 1px solid #aaa;
      transform: rotate(225deg);
      transform-origin: 2px 2px;
      transition: 200ms;
    }

    .on .arrow {
      transform: rotate(45deg);
    }

    .list-box {
      position: absolute;
      top: 30px;
      left: 0;
      border: 1px solid #ddd;
      box-shadow: 0px 0px 8px 0px #ccc;
      padding: 5px 0;
      z-index: 10;
      transition: 200ms;
    }

    .on .list-box {
      top: 50px;
    }

    .list-box .list {
      float: left;
      width: 180px;
      height: 204px;
      overflow: auto;
      border-left: 1px solid #ccc;
    }

    .list-box .list.first {
      border: none;
    }

    .list .item {
      height: 38px;
      line-height: 38px;
      padding-left: 15px;
      font-size: 14px;
      cursor: pointer;
      position: relative;
    }

    .list .item:hover {
      background-color: rgb(245, 247, 250);
    }

    .list .item.active {
      color: #409EFF;
      font-weight: bold;
    }

    .list .icon {
      position: absolute;
      top: -6px;
      left: 30px;
      width: 10px;
      height: 10px;
      border-left: 1px solid #ddd;
      border-top: 1px solid #ddd;
      z-index: 20;
      transform: rotate(45deg);
      background-color: white;
    }

    .list .arrow-icon {
      position: absolute;
      right: 10px;
      top: 17px;
      display: block;
      width: 10px;
      height: 10px;
      border-left: 1px solid #aaa;
      border-top: 1px solid #aaa;
      transform: rotate(135deg);
      transform-origin: 2px 2px;
      transition: 200ms;
    }
  </style>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>

  <div id="app" :class="{'on':isVisibleFirst}">

    <div class="select-box" @click="showFirstLayer">
      <div class="curr" :class="{'on':isVisibleFirst}"><span v-if="selectionBoxDisplay">请选择</span><span v-else>{{theString}}</span><span class="arrow"></span></div>
      <div class="list-box clearfix" v-if="isVisibleFirst">
        <div class="list">
          <div class="item" v-for="(theitem,index) in list" @click="givenValueOfCurr(index)" :class="{'active':index==curr}">{{theitem.name}}

          </div>

        </div>
        <div class="list" v-if="isVisibleSecond">

          <div class="item" V-for="(theSeItem,index1) in list[curr].children" @click="clickingSecondLayer(index1)" :class="{'active':index1==currSec}">
            {{theSeItem.name}}</div>


        </div>
        <div class="icon"></div>
      </div>
    </div>

  </div>

  <script>
    var vm = new Vue({
      el: '#app',
      data: {

        list: [{
          name: '粤菜',
          children: [{
            name: '清蒸桂花鱼'
          }, {
            name: '梅菜扣肉'
          }]
        }, {
          name: '湘菜',
          children: [{
            name: '小炒肉'
          }, {
            name: '剁椒鱼头'
          }, {
            name: '水煮鱼'
          }]
        }, {
          name: '甜品',
          children: [{
            name: '西米露'
          }, {
            name: '双皮奶'
          }, {
            name: '凉粉'
          }]
        }],
        curr: -1,
        currSec: -1,

        firstTimeClick: 0,

        isVisibleFirst: false,

        isVisibleSecond: false,

        theString: "",

        selectionBoxDisplay: true,

      },
      methods: {
        showFirstLayer() {
          this.isVisibleFirst = true;
          this.firstTimeClick += 1;
          if (this.firstTimeClick > 1) {
            this.isVisibleSecond = true;
          }
          this.selectionBoxDisplay = false;

        },
        givenValueOfCurr(index) {
          this.curr = index;
          console.log(this.list[this.curr].children);
          this.isVisibleSecond = true;
          this.currSec = -1;
          this.theString = this.list[this.curr].name + "\/";
        },
        clickingSecondLayer(index1) {
          this.isVisibleFirst = false;
          this.currSec = index1;
          console.log(this.isVisibleFirst);
          this.isVisibleSecond = false;
          event.stopPropagation();
          this.theString += this.list[this.curr].children[this.currSec].name;
        }

      }
    })
  </script>
</body>

</html>

这是成品的图,主要的技术的话,一个是v-if会让点击后的一级菜单显示出来,然后v-if点击一级菜单中的某个元素后,在v-for里面用上一个下标,把下标传入,然后会相应的把数据放到二级菜单中。

选中变色的话是 v-bind:class的应用, :class的效果就是选中后让curr(也就是当前选中的值)对应的Index的值得那个标签添加上一个类,类会变蓝色。

还有就是注意到冒泡事件,所以要阻止一下冒泡事件

猜你喜欢

转载自blog.csdn.net/raymondlin9292/article/details/82800122