Vue

基于 MobileSelect 的 MobileSelectIn

2020-01-15  本文已影响0人  sphenginx

缘起

产品又双叒叕来提需求了,这次的需求是 用户可以滑块滚动选择,也可以手动输入,即:

image.png

需要的效果如下:

后来查看 MobileSelect 的源码,发现了 renderWheels 方法,定义了 Dom 的信息:

renderWheels: function(wheelsData, cancelBtnText, ensureBtnText){
            var _this = this;
            var cancelText = cancelBtnText ? cancelBtnText : '取消';
            var ensureText = ensureBtnText ? ensureBtnText : '确认';
            _this.mobileSelect = document.createElement("div");
            _this.mobileSelect.className = "mobileSelect";
            _this.mobileSelect.innerHTML =
                '<div class="grayLayer"></div>'+
                '<div class="content">'+
                    '<div class="btnBar">'+
                        '<div class="fixWidth">'+
                            '<div class="cancel">'+ cancelText +'</div>'+
                            '<div class="title"></div>'+
                            '<div class="ensure">'+ ensureText +'</div>'+
                        '</div>'+
                    '</div>'+
                    '<div class="panel">'+
                        '<div class="fixWidth">'+
                            '<div class="wheels">'+
                            '</div>'+
                            '<div class="selectLine"></div>'+
                            '<div class="shadowMask"></div>'+
                        '</div>'+
                    '</div>'+
                '</div>';
            document.body.appendChild(_this.mobileSelect);

            //根据数据长度来渲染

            var tempHTML='';
            for(var i=0; i<wheelsData.length; i++){
            //列
                tempHTML += '<div class="wheel"><ul class="selectContainer">';
                if(_this.jsonType){
                    for(var j=0; j<wheelsData[i].data.length; j++){
                    //行
                        tempHTML += '<li data-id="'+wheelsData[i].data[j][_this.keyMap.id]+'">'+wheelsData[i].data[j][_this.keyMap.value]+'</li>';
                    }
                }else{
                    for(var j=0; j<wheelsData[i].data.length; j++){
                    //行
                        tempHTML += '<li>'+wheelsData[i].data[j]+'</li>';
                    }
                }
                tempHTML += '</ul></div>';
            }
            _this.mobileSelect.querySelector('.wheels').innerHTML = tempHTML;
        }

那么,可以重写 renderWheels 方法,重新定义Dom即可:

  // 重写渲染方法
    renderWheels(wheelsData, cancelBtnText, ensureBtnText) {
        let _this = this;
        let cancelText = cancelBtnText ? cancelBtnText : '取消';
        let ensureText = ensureBtnText ? ensureBtnText : '确认';
        _this.mobileSelect = document.createElement("div");
        _this.mobileSelect.className = "mobileSelect";
        _this.mobileSelect.innerHTML =
            '<div class="grayLayer"></div>'+
            '<div class="content">'+
                '<div class="btnBar">'+
                    '<div class="fixWidth">'+
                        '<div class="cancel">'+ cancelText +'</div>'+
                        '<div class="title"></div>'+
                        '<div class="ensure">'+ ensureText +'</div>'+
                    '</div>'+
                '</div>'+
                '<div class="panel">'+
                    '<div class="fixWidth">'+
                        '<div class="wheels">'+
                        '</div>'+
                        '<div class="selectLine"></div>'+
                        '<div class="shadowMask"></div>'+
                    '</div>'+
                '</div>'+
                '<div class="input">'+
                    '<div class="inputLabel"></div>'+
                    '<div class="fixWidth">'+
                        '<div class="inputs">'+
                        '</div>'+
                    '</div>'+
                '</div>'+
            '</div>';
        document.body.appendChild(_this.mobileSelect);

        //根据数据长度来渲染
        let tempHTML='';
        for (let i=0; i<wheelsData.length; i++) {
            tempHTML += '<div class="wheel"><ul class="selectContainer">';
            if(_this.jsonType){
                for(let j=0; j<wheelsData[i].data.length; j++){
                //行
                    tempHTML += '<li data-id="'+wheelsData[i].data[j][_this.keyMap.id]+'">'+wheelsData[i].data[j][_this.keyMap.value]+'</li>';
                }
            }else{
                for(let j=0; j<wheelsData[i].data.length; j++){
                //行
                    tempHTML += '<li>'+wheelsData[i].data[j]+'</li>';
                }
            }
            tempHTML += '</ul></div>';
        }
        _this.mobileSelect.querySelector('.wheels').innerHTML = tempHTML;
        _this.renderInputs();
    }

// 渲染 inputs 数据
    renderInputs() {
        this.mobileSelect.querySelector('.inputLabel').innerHTML = this.inputLabel;
        let tempHTML='';
        let inputsData = this.inputsData;
        for (let i=0; i<inputsData.length; i++) {
            tempHTML += '<div class="inputContainer">';
            if(this.jsonType){
                for(let j=0; j<inputsData[i].data.length; j++){
                //行
                    tempHTML += '<input data-id="'+inputsData[i].data[j][this.keyMap.id]+'" placeholder="'+inputsData[i].data[j].placeholder+'" value="'+inputsData[i].data[j].value+'" >';
                }
            }else{
                for(let j=0; j<inputsData[i].data.length; j++){
                //行
                    tempHTML += '<input value="'+ inputsData[i].data[j].value +'">';
                }
            }
            tempHTML += '</div>';
        }
        this.mobileSelect.querySelector('.inputs').innerHTML = tempHTML;
    }

性空

重写 renderWheels 方法内,调用 renderInputs 方法, 渲染 input 框,然后 编写 input 相关信息的方法,下附重写的 MobileSelectInput 类:

// mobile select with input 
require('./mobileSelectInput.css');
import MobileSelect from 'mobile-select';

export class MobileSelectInput extends MobileSelect {
    init(config) {
        if(config.inputs[0].data.length==0){
            console.error('MobileSelectInput has been successfully installed, but the input data is empty and cannot be initialized.');
            return false;
        }
        this.inputsData = config.inputs;
        this.inputLabel = config.inputLabel;
        // 调用父类的 初始化方法,实例化 mobileSelect 属性
        super.init(config);
        // 获取 input 的div
        this.inputContainer = this.mobileSelect.getElementsByClassName('inputContainer');
        this.fixInputStyle();
    }

    // 渲染 inputs 数据
    renderInputs() {
        this.mobileSelect.querySelector('.inputLabel').innerHTML = this.inputLabel;
        let tempHTML='';
        let inputsData = this.inputsData;
        for (let i=0; i<inputsData.length; i++) {
            tempHTML += '<div class="inputContainer">';
            if(this.jsonType){
                for(let j=0; j<inputsData[i].data.length; j++){
                //行
                    tempHTML += '<input data-id="'+inputsData[i].data[j][this.keyMap.id]+'" placeholder="'+inputsData[i].data[j].placeholder+'" value="'+inputsData[i].data[j].value+'" >';
                }
            }else{
                for(let j=0; j<inputsData[i].data.length; j++){
                //行
                    tempHTML += '<input value="'+ inputsData[i].data[j].value +'">';
                }
            }
            tempHTML += '</div>';
        }
        this.mobileSelect.querySelector('.inputs').innerHTML = tempHTML;
    }

    fixInputStyle () {
        let width = (100/this.inputContainer.length).toFixed(2);
        for(let i=0; i<this.inputContainer.length; i++){
            this.inputContainer[i].style.width = width+'%';
        }
    }

    // 重写渲染方法
    renderWheels(wheelsData, cancelBtnText, ensureBtnText) {
        let _this = this;
        let cancelText = cancelBtnText ? cancelBtnText : '取消';
        let ensureText = ensureBtnText ? ensureBtnText : '确认';
        _this.mobileSelect = document.createElement("div");
        _this.mobileSelect.className = "mobileSelect";
        _this.mobileSelect.innerHTML =
            '<div class="grayLayer"></div>'+
            '<div class="content">'+
                '<div class="btnBar">'+
                    '<div class="fixWidth">'+
                        '<div class="cancel">'+ cancelText +'</div>'+
                        '<div class="title"></div>'+
                        '<div class="ensure">'+ ensureText +'</div>'+
                    '</div>'+
                '</div>'+
                '<div class="panel">'+
                    '<div class="fixWidth">'+
                        '<div class="wheels">'+
                        '</div>'+
                        '<div class="selectLine"></div>'+
                        '<div class="shadowMask"></div>'+
                    '</div>'+
                '</div>'+
                '<div class="input">'+
                    '<div class="inputLabel"></div>'+
                    '<div class="fixWidth">'+
                        '<div class="inputs">'+
                        '</div>'+
                    '</div>'+
                '</div>'+
            '</div>';
        document.body.appendChild(_this.mobileSelect);

        //根据数据长度来渲染
        let tempHTML='';
        for (let i=0; i<wheelsData.length; i++) {
            tempHTML += '<div class="wheel"><ul class="selectContainer">';
            if(_this.jsonType){
                for(let j=0; j<wheelsData[i].data.length; j++){
                //行
                    tempHTML += '<li data-id="'+wheelsData[i].data[j][_this.keyMap.id]+'">'+wheelsData[i].data[j][_this.keyMap.value]+'</li>';
                }
            }else{
                for(let j=0; j<wheelsData[i].data.length; j++){
                //行
                    tempHTML += '<li>'+wheelsData[i].data[j]+'</li>';
                }
            }
            tempHTML += '</ul></div>';
        }
        _this.mobileSelect.querySelector('.wheels').innerHTML = tempHTML;
        _this.renderInputs();
    }

    // 获取 input 的值
    getInputValue () {
        let tempVal = [];
        for (let inputContainer of this.inputContainer) {
            let inputDom = inputContainer.getElementsByTagName('input')[0];
            tempVal.push(inputDom.value);
        }
        return tempVal;
    }

    // 更新全部 input 值
    updateInputs(data) {
        let _this = this;
        for (let i in data) {
            let inputDom = _this.inputContainer[i].getElementsByTagName('input')[0];
            inputDom.value = data[i].value;
        }
    }

    // 更新单个 input 值
    updateInput(index, data) {
        let inputDom = this.inputContainer[index].getElementsByTagName('input')[0];
        inputDom.value = data.value;
    }
}

下附调用该组件的方法:

async initKnowlegeSelect() {
          let self = this;
          let wheels = self.getKnowledgeWheels();
          let knowledgeOpts = {
           trigger: '.j-building-unit-room',
           title: '楼栋/单元/房号',
           inputLabel: '您还可以手动输入楼栋/单元/房号:',
           inputs: [
             {data: [{id: 'building', value: self.info.buildNo || '', placeholder: '请输入楼栋'}]},
             {data: [{id: 'unit', value: self.info.unit || '', placeholder: '请输入单元'}]},
             {data: [{id: 'roomNo', value: self.info.roomNo || '', placeholder: '请输入房号'}]}
            ],
           wheels: [{data: wheels}],
           triggerDisplayData: false, //关闭时不默认填写数据
           transitionEnd() {  // 滚轮结束回调, 因为是级联的,这里需要延迟防抖获取数据
             let func = () => this.updateInputs(this.getCurValue());
             self.debounce(func);
           },
           callback () { //确认按钮回调
              self.initKnowlegeRalations(this);
           }
        }
        // 如果该对象 存在, 更新数据即可,定义多个实例会绑定多次…… 
        if (this.mobileSelectInput) {
           this.mobileSelectInput.updateWheels(wheels);
           this.mobileSelectInput.updateInputs([{value: null}, {value: null}, {value: null}]);
        } else {
           const {MobileSelectInput} = await import('@/assets/MobileSelectInput/MobileSelectInput.js');
           this.mobileSelectInput = new MobileSelectInput(knowledgeOpts);
        }
      }

最后实现效果如下:

image.png
上一篇下一篇

猜你喜欢

热点阅读