基于 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