• 如何修复在移动动表现差异很大的选择框---中级程序员研究


    在移动端开发中,我们往往需要按照设计稿去高度还原效果图,并且实现交互方式,下面看一下一个标签的表现形式: select 

    在iOS中的表现:

    但是在安卓上并不是这样的效果

     交互表现得差异性需要优化,那么问题来了,怎么优化。如何去保持同一标签可以表现相同得样式和交互方式。其实这也是前端的重要工作之一:兼容性和适配,也对应着招聘的要求之一:高度还原设计稿;言归正传,看到select不同的表现。我们如何实现这个替换呢?用过element-ui,iview等框架的小伙伴都知道,他们为了保持统一的表现,放弃了select,option;而是封装了自己的el-select 或者Select; 

     iviewui中的select

    vant中的picker

    element-ui

    以上框架都实现了select的封装,但是在开放中,我们如果没有使用它们自身的框架,而是我们项目本身的框架,用起来很是费劲;大家都知道前端开发现在最火的是组件化开发,组件就是组件,可以快速移植和安装;最重要的是可以差异化这个组件,而且你也便于维护;安装其中的某个组件,你可能要花费30分钟去修改配置和调试,但是极有可能不会成功,这是很痛心、很扎心;

    那么推荐下面一个最简单的替换组件,

    yh-select

    这个组件昨天发布,对没有错就是我写的,支持 npm install yh-select ,目前只支持vue, 安装完成后,select option ,可以用一行标签搞定了,详情请看yh-select;(如果你想一起组队开发组件,那么请加微信xingguangbi,我们一起发布自己的组件)

    修复不同的表现方式和交互方式,需要我们去替换产生差异的一些标签,用相同的标签去组装我们想要的效果:

    下面分享一下我替换select的思路:

    ul>li存放option的每一列,外面再来一个div包裹它,下拉的箭头实现,背景色去填充,不使用图片和字体图标,好处:尽量减少组件的依赖性,减少请求;

    一个点击外部的指令

    const clickoutsideContext = "@@clickoutsideContext";
    
    export default {
      /*
       @param el 指令所绑定的元素
       @param binding {Object} 
       @param vnode vue编译生成的虚拟节点
       */
      bind(el, binding, vnode) {
        const documentHandler = function(e) {
          if (!vnode.context || el.contains(e.target)) {
            return false;
          }
          if (binding.expression) {
            vnode.context[el[clickoutsideContext].methodName](e);
          } else {
            el[clickoutsideContext].bindingFn(e);
          }
        };
        el[clickoutsideContext] = {
          documentHandler,
          methodName: binding.expression,
          bindingFn: binding.value
        };
        setTimeout(() => {
          document.addEventListener("click", documentHandler);
        }, 0);
      },
      update(el, binding) {
        el[clickoutsideContext].methodName = binding.expression;
        el[clickoutsideContext].bindingFn = binding.value;
      },
      unbind(el) {
        document.removeEventListener(
          "click",
          el[clickoutsideContext].documentHandler
        );
      }
    };
    

     核心组件如下:

    <template>
      <div
        v-clickoutside="handleClose"
        class="select-wrapper"
        @click.prevent="selF"
        :class="{'active':selFlag}"
        :style="{'z-index':min}"
      >
        <div class="inners">{{models[names]}}</div>
        <div class="arrow" @click.stop="selF"></div>
        <ul v-show="selFlag">
          <li
            :class="{'active':models.value==item.value}"
            v-for="(item,index) in options"
            :key="index"
            :value="item[val]"
            @click.stop="sels(item)"
          >{{item[names]}}</li>
        </ul>
      </div>
    </template>
    <script>
    import clickoutside from "./close";
    export default {
      directives: { clickoutside },
      model: {
        prop: "sel",
        event: "change"
      },
      props: ["options", "sel", "val", "names"],
      data() {
        return {
          selFlag: false,
          models: "",
          min: 0
        };
      },
      methods: {
        selF() {
          this.min = 100;
          this.selFlag = !this.selFlag;
        },
        init() {
          this.models = this.sel;
        },
        sels(item) {
          this.models = item;
          this.selFlag = !this.selFlag;
          this.$emit("change", item);
        },
        handleClose() {
          this.min = 0;
          this.selFlag = false;
        }
      },
      mounted() {
        this.init();
      }
    };
    </script>
    <style scoped>
    .select-wrapper {
       120px;
      border: 1px solid #999;
      padding: 2px 30px 0 5px;
      font-size: 12px;
      height: 18px;
      position: relative;
      z-index: -1;
    }
    .inners {
      padding-right: 30px;
      overflow: hidden;
    }
    .select-wrapper .arrow {
      position: absolute;
      top: 50%;
      right: 10px;
      z-index: 30;
      transform: translateY(-50%);
      border-top: 5px solid #999;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
    }
    .active {
      box-shadow: 0 0 3px #1e90ff;
    }
    .select-wrapper ul {
      list-style: none;
      margin: 0;
      padding: 0;
       fit-content;
      text-align: left;
      position: absolute;
      max-height: 160px;
      overflow-y: auto;
      bottom: 0;
      transform: translateY(101%);
      left: 0;
      z-index: 10;
      background: #fff;
      border: 1px solid #1e90ff;
      min- 100%;
    }
    .select-wrapper li {
      padding: 0 45px 0 0;
      background: #fff;
    }
    .select-wrapper li:hover {
      background: #1e90ff;
      color: #fff;
    }
    .select-wrapper li.active {
      background: #1e90ff;
      color: #fff;
    }
    </style>
    

      源码地址:我要下载源码 (如果喜欢,请记得star一下);

    最后提供一个问题解答的机会,交流的微信群,可以一起交流学习,如果你想进入请加微信:xingguangbi(备注交流解答);

  • 相关阅读:
    学习进度表
    第十三周
    硅谷之谜
    第12周
    我的成就故事
    学习进度表
    第8周总结
    测试作业
    第六周周总结
    问卷调查
  • 原文地址:https://www.cnblogs.com/starryqian/p/10301999.html
Copyright © 2020-2023  润新知