layui的select组件更改

官方的select不能接收更丰富的配置,这就需要适当改动即可。可以看我过去的相关文章,这个改动改动的地方比较多

首先,下载官方开发版的layui。
找到modules->form.js文件
定位到“初始渲染 select 组件选项”部分。

官方的做法是对option内的标签会进一步拆解,这就造成了看上去似乎能渲染但是会有很多重复的选项,此外,option标签内理论上不应该再出现别的元素标签,在部分浏览器会自动过滤掉这些标签,因此代码部分还应当是转义过的文本。

js代码如下

/**
 * form 表单组件
 */
 
layui.define(['lay', 'layer', 'util'], function(exports){
   
   
  "use strict";
  
  var $ = layui.$;
  var layer = layui.layer;
  var util = layui.util;
  var hint = layui.hint();
  var device = layui.device();
  var needCheckboxFallback = lay.ie && parseFloat(lay.ie) === 8;
  
  var MOD_NAME = 'form';
  var ELEM = '.layui-form';
  var THIS = 'layui-this';
  var SHOW = 'layui-show';
  var HIDE = 'layui-hide';
  var DISABLED = 'layui-disabled';
  var OUT_OF_RANGE = 'layui-input-number-out-of-range';
  var BAD_INPUT = 'layui-input-number-invalid';
  
  var Form = function(){
   
   
    this.config = {
   
   
      // 内置的验证规则
      verify: {
   
   
        required: function(value) {
   
   
          if (!/[\S]+/.test(value) || value === undefined || value === null) {
   
   
            return '必填项不能为空';
          }
        },
        phone: function(value) {
   
   
          var EXP = /^1\d{10}$/;
          if (value && !EXP.test(value)) {
   
   
            return '手机号格式不正确';
          }
        },
        email: function(value) {
   
   
          var EXP = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
          if (value && !EXP.test(value)) {
   
   
            return '邮箱格式不正确';
          }
        },
        url: function(value) {
   
   
          var EXP = /^(#|(http(s?)):\/\/|\/\/)[^\s]+\.[^\s]+$/;
          if (value && !EXP.test(value)) {
   
   
            return '链接格式不正确';
          }
        },
        number: function(value){
   
   
          if (value && isNaN(value)) {
   
   
            return '只能填写数字';
          }
        },
        date: function(value){
   
   
          var EXP = /^(\d{4})[-\/](\d{1}|0\d{1}|1[0-2])([-\/](\d{1}|0\d{1}|[1-2][0-9]|3[0-1]))*$/;
          if (value && !EXP.test(value)) {
   
   
            return '日期格式不正确';
          }
        },
        identity: function(value) {
   
   
          var EXP = /(^\d{15}$)|(^\d{17}(x|X|\d)$)/;
          if (value && !EXP.test(value)) {
   
   
            return '身份证号格式不正确';
          }
        }
      },
      autocomplete: null // 全局 autocomplete 状态。 null 表示不干预
    };
  };
  
  // 全局设置
  Form.prototype.set = function(options){
   
   
    var that = this;
    $.extend(true, that.config, options);
    return that;
  };
  
  // 验证规则设定
  Form.prototype.verify = function(settings){
   
   
    var that = this;
    $.extend(true, that.config.verify, settings);
    return that;
  };

  // 获取指定表单对象
  Form.prototype.getFormElem = function(filter){
   
   
    return $(ELEM + function(){
   
   
      return filter ? ('[lay-filter="' + filter +'"]') : '';
    }());
  };
  
  // 表单事件
  Form.prototype.on = function(events, callback){
   
   
    return layui.onevent.call(this, MOD_NAME, events, callback);
  };
  
  // 赋值/取值
  Form.prototype.val = function(filter, object){
   
   
    var that = this
    ,formElem = that.getFormElem(filter);
    
    // 遍历
    formElem.each(function(index, item){
   
   
      var itemForm = $(this);
      
      // 赋值
      for(var key in object){
   
   
        if(!lay.hasOwn(object, key)) continue;

        var type;
        var value = object[key];
        var itemElem = itemForm.find('[name="'+ key +'"]');
        
        // 如果对应的表单不存在,则不执行
        if(!itemElem[0]) continue;
        type = itemElem[0].type;
        
        // 如果为复选框
        if(type === 'checkbox'){
   
   
          itemElem[0].checked = value;
        } else if(type === 'radio') {
   
    // 如果为单选框
          itemElem.each(function(){
   
   
            this.checked = this.value == value + '';
          });
        } else {
   
    // 其它类型的表单
          itemElem.val(value);
        }
      };
    });
    
    form.render(null, filter);
    
    // 返回值
    return that.getValue(filter);
  };
  
  // 取值
  Form.prototype.getValue = function(filter, itemForm){
   
   
    itemForm = itemForm || this.getFormElem(filter);
        
    var nameIndex = {
   
   } // 数组 name 索引
    ,field = {
   
   }
    ,fieldElem = itemForm.find('input,select,textarea') // 获取所有表单域
    
    layui.each(fieldElem, function(_, item){
   
    
      var othis = $(this)
      ,init_name; // 初始 name
      
      item.name = (item.name || '').replace(/^\s*|\s*&/, '');
      if(!item.name) return;
      // 用于支持数组 name
      if(/^.*\[\]$/.test(item.name)){
   
   
        var key = item.name.match(/^(.*)\[\]$/g)[0];
        nameIndex[key] = nameIndex[key] | 0;
        init_name = item.name.replace(/^(.*)\[\]$/, '$1['+ (nameIndex[key]++) +']');
      }
      
      if(/^(checkbox|radio)$/.test(item.type) && !item.checked) return;  // 复选框和单选框未选中,不记录字段     
      // select 多选用 jQuery 方式取值,未选中 option 时,
      // jQuery v2.2.4 及以下版本返回 null,以上(3.x) 返回 []。
      // 统一规范化为 [],参考 https://github.com/jquery/jquery/issues/2562
      field[init_name || item.name] = (this.tagName === 'SELECT' && typeof this.getAttribute('multiple') === 'string') 
        ? othis.val() || []
        : this.value;
    });
    
    return field;
  };
  
  // 表单控件渲染
  Form.prototype.render = function(type, filter){
   
   
    var that = this;
    var options = that.config;
    var elemForm = $(ELEM + function(){
   
   
      return filter ? ('[lay-filter="' + filter +'"]') : '';
    }());
    var items = {
   
   
      // 输入框
      input: function(elem){
   
   
        var inputs = elem || elemForm.find('input,textarea');

        // 初始化全局的 autocomplete
        options.autocomplete && inputs.attr('autocomplete', options.autocomplete);

        var handleInputNumber = function(elem, eventType){
   
   
          var that = this;
          var rawValue = elem.val();
          var value = Number(rawValue);
          var step = Number(elem.attr('step')) || 1; // 加减的数字间隔
          var min = Number(elem.attr('min'));
          var max = Number(elem.attr('max'));
          var precision = Number(elem.attr('lay-precision'));
          var noAction = eventType !== 'click' && rawValue === ''; // 初始渲染和失焦时空值不作处理
          var isInit = eventType === 'init';
          var isBadInput = isNaN(value);
          var isStepStrictly = typeof elem.attr('lay-step-strictly') === 'string';

          elem.toggleClass(BAD_INPUT, isBadInput);
          if(isBadInput) return; // 若非数字,则不作处理

          if(eventType === 'click'){
   
   
            // 兼容旧版行为,2.10 以前 readonly 不禁用控制按钮
            if(elem[0].type === 'text' && typeof elem.attr('readonly') === 'string') return;
            var isDecrement = !!$(that).index() // 0: icon-up, 1: icon-down
            value = isDecrement ? value - step : value + step;
          }

          // 获取小数点后位数
          var decimals = function(step){
   
   
            var decimals = (step.toString().match(/\.(\d+$)/) || [])[1] || '';
            return decimals.length;
          };

          precision = precision >= 0 ? precision : Math.max(decimals(step), decimals(rawValue));

          // 赋值
          if (!noAction) {
   
   
            // 初始渲染时只处理数字精度
            if (!isInit) {
   
   
              if(isStepStrictly){
   
   
                value = Math.round(value / step) * step;
              }
              if(value <= min) value = min;
              if(value >= max) value = max;
            }
            // 若 `lay-precision` 为 0, 则表示只保留整数
            if (precision === 0) {
   
   
              value = parseInt(value);
            } else if(precision > 0) {
   
    // 小数位精度
              value = value.toFixed(precision);
            }

            elem.val(value);
            elem.attr('lay-input-mirror', elem.val())
          }

          // 超出范围的样式
          var outOfRange = value < min || value > max;
          elem[outOfRange && !noAction ? 'addClass' : 'removeClass'](OUT_OF_RANGE);

          if(isInit) return;

          // 更新按钮状态
          var controlBtn = {
   
   
            increment: elem.next().find('.layui-icon-up'),
            decrement: elem.next().find('.layui-icon-down')
          }
          controlBtn.increment[(value >= max && !noAction) ? 'addClass' : 'removeClass'](DISABLED)
          controlBtn.decrement[(value <= min && !noAction) ? 'addClass' : 'removeClass'](DISABLED)
        }

        // 初始化输入框动态点缀
        elemForm.find('input[lay-affix],textarea[lay-affix]').each(function(){
   
   
          var othis = $(this);
          var affix = othis.attr('lay-affix');
          var CLASS_WRAP = 'layui-input-wrap';
          var CLASS_SUFFIX = 'layui-input-suffix';
          var CLASS_AFFIX = 'layui-input-affix';
          var disabled = othis.is('[disabled]') || othis.is('[readonly]');

          // 根据是否空值来显示或隐藏元素
          var showAffix = function(elem, value){
   
   
            elem = $(elem);
            if(!elem[0]) return;
            elem[$.trim(value) ? 'removeClass' : 'addClass'](HIDE);
          };

          // 渲染动态点缀内容
          var renderAffix = function(opts){
   
   
            opts = $.extend({
   
   }, (affixOptions[affix] || {
   
   
              value: affix
            }), opts, lay.options(othis[0]));
            var elemAffix = $('<div class="'+ CLASS_AFFIX +'">');
            var value = layui.isArray(opts.value) ? opts.value : [opts.value];
            var elemIcon = $(function(){
   
   
              var arr = [];
              layui.each(value, function(i, item){
   
   
                arr.push('<i class="layui-icon layui-icon-'+ item + (
                  opts.disabled ? (' '+ DISABLED) : ''
                ) +'"></i>');
              });
              return arr.join('');
            }());
            
            elemAffix.append(elemIcon); // 插入图标元素

            // 追加 className
            if(opts.split) elemAffix.addClass('layui-input-split');
            if(opts.className) elemAffix.addClass(opts.className);

            // 移除旧的元素
            var hasElemAffix = othis.next('.'+ CLASS_AFFIX);
            if(hasElemAffix[0]) hasElemAffix.remove();

            // 是否在规定的容器中
            if(!othis.parent().hasClass(CLASS_WRAP)){
   
   
              othis.wrap('<div class="'+ CLASS_WRAP +'"></div>');
            }

            // 是否已经存在后缀元素
            var hasElemSuffix = othis.next('.'+ CLASS_SUFFIX);
            if(hasElemSuffix[0]){
   
   
              hasElemAffix = hasElemSuffix.find('.'+ CLASS_AFFIX);
              if(hasElemAffix[0]) hasElemAffix.remove();

              hasElemSuffix.prepend(elemAffix);

              othis.css('padding-right', function(){
   
   
                var paddingRight = othis.closest('.layui-input-group')[0] 
                  ? 0 
                : hasElemSuffix.outerWidth();
                return paddingRight + elemAffix.outerWidth()
              });
            } else {
   
   
              elemAffix.addClass(CLASS_SUFFIX);
              othis.after(elemAffix);
            }

            opts.show === 'auto' && showAffix(elemAffix, othis.val());
            
            typeof opts.init === 'function' && opts.init.call(this, othis, opts);
            
            // 输入事件
            othis.on('input propertychange', function(){
   
   
              var value = this.value;
              opts.show === 'auto' && showAffix(elemAffix, value);
            });

            // 失去焦点事件
            othis.on('blur', function(){
   
   
              typeof opts.blur === 'function' 
Layui 是一个非常流行的前端 UI 框架,它的 select 组件支持级联加载多级下拉树的功能。以下是一个简单的使用 Layui select 组件实现级联下拉树的 DEMO 示例: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Layui select 级联加载多级下拉树示例</title> <link rel="stylesheet" href="https://cdn.staticfile.org/layui/2.5.6/css/layui.css"> </head> <body> <div class="layui-container"> <div class="layui-row"> <div class="layui-col-xs12"> <label class="layui-form-label">选择城市</label> <div class="layui-input-inline"> <select name="city" id="citySelect" lay-filter="citySelect"> <option value="">请选择省份</option> </select> </div> </div> </div> </div> <script src="https://cdn.staticfile.org/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdn.staticfile.org/layui/2.5.6/layui.js"></script> <script> layui.use(['form', 'layer', 'jquery'], function(){ var $ = layui.jquery; var form = layui.form; // 模拟从服务器获取数据 function getData(level, father) { var html = ''; for(var i = 0; i < 4; i++) { html += '<option value="' + level + i + '">' + level + i + '</option>'; } return html; } // 省份数据 var data1 = getData('省', ''); // 初始化城市下拉框 $('#citySelect').val('1'); form.render('select'); // 级联操作 var data2 = {}; $('#citySelect').change(function(){ // 根据选择的省份值来显示对应的城市数据 var selectVal = $(this).val(); if(selectVal) { // 用layer弹窗显示下一级数据 layer.open({ type: 1, area: ['80%', '80%'], title: '请选择城市', content: '<select name="city" lay-filter="citySelect2">' + '<option value="">加载中...</option>' + data2[selectVal] || getData('市', selectVal) + '</select>', end: function(){ // 如果有下一级,则继续级联 var citySelect2 = document.querySelector('[name="city"][lay-filter="citySelect2"]'); citySelect2.onchange = function(){ var cityVal = $(this).val(); // 更改数据,实际应用中是去服务器获取数据 data2[cityVal] = getData('区', cityVal); // 重新赋值并渲染 $(this).html(data2[cityVal]); form.render('select'); }; } }); } }); }); </script> </body> </html> ``` 在这个 DEMO 中,我们首先定义了一个名为 `citySelect` 的下拉框,并且通过 `lay-filter` 属性指定了一个过滤器名称。当下拉框的值发生变化时,会触发一个级联加载的操作,这里使用了 Layui 的 layer 组件来弹出一个新的下拉框,并通过 `change` 事件实现级联效果。 需要注意的是,上述代码仅作为一个示例,其中的数据是通过 `getData` 函数模拟生成的。在实际应用中,您需要从服务器动态获取数据,并替换模拟数据部分。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值