设想形式-组合+战略形式

完成一个中心部件对象,也就是能够增加恭弘=叶 恭弘子节点的对象,终究这个中心件部件装载在根form对象上.这个中心件的长处是能够依据现实营业需求举行分组.本例中划分了三种营业,分别是名字分组,地点分组和测试分组.本例中还设想了remove依据id删除元素的要领,如许会越发天真.由于援用范例是公用的,纵然前面增加了,背面再删除,末了获得的照样删除后的结果.如许能够不必漫天寻觅代码,也不必非要在增加之前解释某段代码,这就是援用范例的长处.战略形式和组合形式之间是没有任何耦合的,我们完全能够在动态装载完form表单后,再依据详细字段绑定战略,至于依据现实需要拆开某些字段的战略,那就是战略形式本身的事了.

<!DOCTYPE html>
<html>
  <head lang="en">
    <meta charset="UTF-8">
    <title>组合+战略形式</title>
  </head>
  <body>
  </body>
</html>
<script type="text/javascript">
//战略类
var strategies = {
  isNonEmpty: function(value, errorMsg) {
    if(value === '') {
      return errorMsg;
    }
  },
  minLength: function(value, length, errorMsg) {
    if(value.length < length) {
      return errorMsg;
    }
  },
  isMobile: function(value, errorMsg) {
    if(!/1[3|5|8][0-9]{9}$/.test(value)) {
      return errorMsg;
    }
  }
};

var Validator = function() {
  this.cache = [];
}

Validator.prototype.add = function(dom, rules) {
  var self = this;

  for(var i=0; i<rules.length; i++) {
    (function(rule) {
      var arr = rule.strategy.split(':');
      var errorMsg = rule.errorMsg;
      //将函数都压入数组
      self.cache.push(function() {
        //拿出战略字串备用
        var strategy = arr.shift();
        //将dom值放在数组头一个
        arr.unshift(dom.value);
        //报错信息放在数组末了一个
        arr.push(errorMsg);
        return strategies[strategy].apply(dom, arr);
      })
    })(rules[i]);
  }
};

Validator.prototype.start = function() {
  for(var i=0; i<this.cache.length; i++) {
    var msg = this.cache[i]();
    if(msg) {
      return msg;
    }
  }
}

//继续要领
function extend(newobj, obj) {
  var F = function() {};
  F.prototype = obj.prototype;
  newobj.prototype = new F();
  newobj.prototype.constructor = newobj;
}

//恭弘=叶 恭弘子对象
var Field = function(id) {
  this.id = id;
  this.divElement;
}

Field.prototype.save = function() {
  sessionStorage.setItem(this.id, this.getValue());
  console.log(sessionStorage.getItem(this.id));
}
//终究挪用子对象的divElement,这个this指向必需是子对象。
//用call函数能够修改this指向。
//以供下面部件对象CompositeFieldSet中运用。
Field.prototype.getDivElement = function() {
  //这里还要注重divElement必需有个id,在部件对象的容器中作为key值运用。
  return this.divElement;
}
//子类继续运用
Field.prototype.getValue = function() {
  throw new Error('you should override this method');
}

var InputField = function(label, id, type) {
  Field.call(this, id);
  this.input = document.createElement('input');
  //战略考证类运用name寻觅dom
  this.input.name = id;
  this.input.type = type;

  this.label = document.createElement('label');
  var labelTextNode = document.createTextNode(label);
  this.label.appendChild(labelTextNode);

  this.divElement = document.createElement('div');
  this.divElement.id = id;
  this.divElement.className = 'input-field';
  this.divElement.appendChild(this.label);
  this.divElement.appendChild(this.input);
}

extend(InputField, Field);
InputField.prototype.getValue = function() {
  return this.input.value;
};

var SelectField = function(label, id, arr) {
  Field.call(this, id);
  this.select = document.createElement('select');

  for(var i=0; i<arr.length; i++) {
    var option = document.createElement('option');
    option.text = arr[i].text;
    option.value = arr[i].value;
    this.select.options[i] = option;
  }

  this.label = document.createElement('label');
  var labelTextNode = document.createTextNode(label);
  this.label.appendChild(labelTextNode);

  this.divElement = document.createElement('div');
  this.divElement.id = id;
  this.divElement.className = 'select-field';
  this.divElement.appendChild(this.label);
  this.divElement.appendChild(this.select);
}

extend(SelectField, Field);
SelectField.prototype.getValue = function() {
  return this.select.options[this.select.selectedIndex].value;
}

//部件对象:能够依据营业分组表单元素
var CompositeFormSet = function(id, legendText) {
  //注重这里不是数组了。
  this.components = {};
  //legend和fieldset元素在表单元素分组很经常使用
  //一个fieldset包括很多legend
  this.id = id;
  this.element = document.createElement('fieldset');
  this.element.id = id;
  //dom分组
  if(legendText) {
    this.legend = document.createElement('legend');
    this.legend.appendChild(document.createTextNode(legendText));
    this.element.appendChild(this.legend);
  }
}

CompositeFormSet.prototype.add = function(child) {
  //容器内的元素依据id分组。
  //每一个child是一个恭弘=叶 恭弘子对象。
  this.components[child.getDivElement().id] = child;
  this.element.appendChild(child.getDivElement());
}
//猎取这个部件对象,以供下面CompositeForm对象中运用。
CompositeFormSet.prototype.getElement = function() {
  return this.element;
}

CompositeFormSet.prototype.save = function() {
  console.log(this.components);
  for(var id in this.components) {
    //假如容器没有这个元素,直接跳过。
    if(!this.components.hasOwnProperty(id)) {
      continue;
    }
    this.components[id].save();
  }
}
//拆开某个恭弘=叶 恭弘子对象
//如许就不必去寻觅增加元素的处所解释代码。
CompositeFormSet.prototype.remove = function() {
  var child;
  for(var key in this.components) {
    if(this.components[key]['id'] === id) {
      child = this.components[key];
      delete this.components[child.getDivElement().id];
      this.element.removeChild(child.getDivElement());
      break;
    }

  }
}

var CompositeForm = function(id) {
  this.formComponents = [];
  this.formElement = document.createElement('form');
  this.formElement.id = id;
  this.formElement.onsubmit = function() {
    return false;
  }
}

CompositeForm.prototype.add = function(child) {
  this.formComponents.push(child);
  //增加部件元素
  //每一个child是一个部件对象。
  this.formElement.appendChild(child.getElement());
}

CompositeForm.prototype.save = function() {
  for(var i=0; i<this.formComponents.length; i++) {
    this.formComponents[i].save();
  }
}
//拆掉某个元素
CompositeForm.prototype.remove = function(id) {
  var child;
  for(var i=0; i<this.formComponents.length; i++) {
    if(this.formComponents[i].id === id) {
      child = this.formComponents[i];
      this.formComponents.splice(i, 1);
      this.formElement.removeChild(child.getElement);
      break;
    }
  }
}
//猎取终究form对象,以供追加到body下。
CompositeForm.prototype.getFinalElement = function() {
  var submitButton = document.createElement('input');
  submitButton.id = 'sub';
  submitButton.type = 'submit';
  this.formElement.appendChild(submitButton);
  return this.formElement;
}

//最先组合
var form = new CompositeForm('comtact-form');

//造部件:名字分组
var nameFieldSet = new CompositeFormSet('name-fieldset', 'nameArea');
nameFieldSet.add(new InputField('first-name', 'firstName', 'text'));
nameFieldSet.add(new InputField('last-name', 'lastName', 'text'));

//造部件:地点分组
var addressFieldSet = new CompositeFormSet('address-fieldset', 'addressArea');
addressFieldSet.add(new SelectField('国度', 'country', [{text:'美国', value:'us'}, {text:'日本', value:'jp'}]));
addressFieldSet.add(new InputField('地点', 'detail', 'text'));
addressFieldSet.add(new InputField('手机号', 'phone', 'text'));

//造部件:测试分组
var testFieldSet = new CompositeFormSet('test-fieldset', 'testArea');
testFieldSet.add(new InputField('测试', 'test', 'text'));

form.add(nameFieldSet);
form.add(addressFieldSet);
form.add(testFieldSet);

//倏忽有一天,司理让你去掉测试分组,
//而且去掉地点分组中的国度元素。
//然则我并不想去找add的代码到底在那里
//因而能够从掌握台中直接找到id的相干信息,用remove删除就好
addressFieldSet.remove('country');
form.remove('test-fieldset');

var formNode = form.getFinalElement();
document.body.appendChild(formNode);

var todoFunc = function() {
  var validator = new Validator();
  validator.add(formNode.firstName, [
    {strategy: 'isNonEmpty', errorMsg: 'firstName不能为空'},
    {strategy: 'minLength:5', errorMsg: 'firstName长度不能少于5位'}
  ]);
  validator.add(formNode.lastName, [
    {strategy: 'isNonEmpty', errorMsg: 'lastName不能为空'},
    {strategy: 'minLength:3', errorMsg: 'lastName长度不能少于3位'}
  ]);
  validator.add(formNode.detail, [
    {strategy: 'isNonEmpty', errorMsg: '地点不能为空'},
    {strategy: 'minLength:10', errorMsg: '地点长度不能少于10位'}
  ]);
  validator.add(formNode.phone, [
    {strategy: 'isNonEmpty', errorMsg: '手机号不能为空'},
    {strategy: 'isMobile', errorMsg: '手机号码花样不正确'}
  ]);

  var errorMsg = validator.start();
  return errorMsg;
}

document.getElementById('sub').onclick = function() {
  form.save();
  var errorMsg = todoFunc();
  if(errorMsg) {
    alert(errorMsg);
  }
  return false;
}
</script>
    原文作者:小被子
    原文地址: https://segmentfault.com/a/1190000008729705
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞