省市区三级联动实例(select居中显示)

1. 需求

页面初始化时如图。与用户交互时实现省市区三级联动,并居中显示。
这里写图片描述

2. 分析

(1)select居中显示

  • 问题:原生的select无法居中显示。
  • 解决方案:用span标签显示初始值及选择的内容,select标签设置成和span同样的大小通过定位的方式覆盖在其上方,并且设置opacity: 0,不可见。
  • demo如下:
  
<html>  
<head>  
<title>title>  
<style>  
.select-container {  
    text-align: center;  
    border:solid 1px; 
    position: relative; 
}  
.select-container select {  
    position: absolute;  
    left: 0px;  
    top: 0px;  
    width: 100%;  
    height: 2em;  
    opacity: 0;  
}  

style>  
head>  
<body>  
    <div class="select-container">  
        <span>省份span>  
        <select>  
            <option value="1">四川option>  
            <option value="2">湖南option>  
            <option value="3">湖北option>  
            <option value="4">内蒙古option>  
        select>  
    div>  
body>  
html>  

(2)省市区三级联动jQuery插件

使用distpicker插件
参见https://www.npmjs.com/package/distpicker

需要的dom结构如下:
通过data-toggle属性进行识别及初始化。原生select会默认显示第一项,通常把第一项设置为select的显示名称,而此处,初始状态下select是看不到的,所以不需要这个名称提示,于是将data-placeholder设置为false。

<div data-toggle="distpicker" data-placeholder="false">
  <select>select>
  <select>select>
  <select>select>
div>

3. 代码实现

注意:使用的jsx语法

(1)静态部分

由于distpicker的DOM结构不可改变,所以只能把省市区三个select作为一个整体覆盖到省市区文字显示的区域上。

<div className="form-select-area">
    <ul className="select-item-list">
      <li>
        <span className="item" name="省份">省份span>
        <img className="arrow" src={arrow} alt="" />
      li>
      <li>
        <span className="item" name="城市">城市span>
        <img className="arrow" src={arrow} alt="" />
      li>
      <li>
        <span className="item" name="区县">区县span>
        <img className="arrow" src={arrow} alt="" />
      li>
    ul>
    <div className="select-area" data-toggle="distpicker" data-placeholder="false">
      <select className="form-select" name="0" id="" />
      <select className="form-select" name="1" id="" />
      <select className="form-select" name="2" id="" />
    div>
  div>
$border-style: solid 1px rgba(255, 255, 255, 0.3);

.form-select-area {
  display: inline-block;
  width: 100%;
  position: relative;

  .select-area {
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    font-size: 0;

    select {
      background-color: transparent;
      width: 33.3%;
      opacity: 0;
      height: 100%;
    }
  }

  .select-item-list {
    font-size: 0;

    > li {
      display: inline-block;
      width: 33.3%;
      vertical-align: top;
      border: $border-style;
      border-right: none;
      text-align: center;
      position: relative;
      font-size: 14px;
      height: 2.8em;

      &:last-child {
        border-right: $border-style;
      }

      .item {
        color: #fff;
        font-weight: bold;
        white-space: nowrap;
        max-width: 77%;
        overflow: hidden;
        display: inline-block;
        text-overflow: ellipsis;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);

        &.error {
          color: #d20202;
        }
      }

      .arrow {
        position: absolute;
        right: 5%;
        width: 10px;
        top: 50%;
        transform: translateY(-50%);
      }
    }
  }
}

(2)js部分

  • $('.form-select')选择器选中的是三个select,也就是说任意select都会触发
  • select框被第一次点击(无论点击的哪个select),清除错误样式。
  • select框被第一次点击或者发生改变,都进行遍历,此处不使用$(this),因为是三级联动,任何一个选项修改,都需要重新把select中被选中的渲染到span标签的显示区域中。
const getTextItemFromSelect = (self) => {
  const _index = self.attr('name');//select上标记的0,1,2
  return self.parents('.select-area').prevAll('.select-item-list').find('li:eq('+_index+')').find('.item');
};
const selectArea = (self) => {
  const _val = self.find('option:selected').html();
  const _$item = getTextItemFromSelect(self);
  _$item.html(_val).addClass('selected');
};

$('.form-select').change(() => {
  $('.form-select').each(function () {
    selectArea($(this));
  });
}).one('click', () => {
  const _item = $('.form-select-area .item');
  _item.removeClass('error');
  $('.form-select').each(function () {
    selectArea($(this));
  });
});

你可能感兴趣的:(前端)