20 有序车站——职责链模式
场景:领导叫过去说实现一个表单,要有输入验证和输入提示交互体验,具体是什么类型的表单,还没确定。
这是我们面对一个"半成品"的需求,由于需求不明确,没法直接做,做了还有改,不如不做。这时我们可以应用职责链模式
分解需求
把这个任务分解为
- 请求模块,ajax发送表单内容
- 响应数据模块,处理返回信息交互
- 创建组件模块,根据返回信息创建对应的模块
第一站,请求模块
/**
* 异步请求模块(简化版)
* @param data 请求数据
* @param dealType 响应数据处理对象
* @param dom 事件源
**/
function sendData(data, dataType, dom) {
var xhr = new XMLHttpRequest()
xhr.onload = function(event) {
// 请求成功
if(xhr.status >= 200 || xhr.status < 300 || xhr.status == 304) {
// 返回数据直接传给处理函数
dealData(xhr.responseText, dealType, dom)
} else {
// 请求失败
console.log('请求失败')
}
}
var param = data.data
// data.url = 'getData.php?mod=userinfo'
var url = data.url || ''
// 拼接请求字符串
for( var i in param) {
url += '<li>'+param[i]+'</li>'
}
// 发送异步请求
xhr.open('get', data.url, true)
xhr.send(null)
}
第二站,响应数据适配模块
/**
* 处理响应数据模块
* @param {*} data 响应数据
* @param {*} dealType 响应数据处理对象
* @param {*} dom 事件源
*/
function dealData(data, dealType, dom) {
// 简化处理,获取数据类型
data = Object.prototype.toString.call(data)
switch (dealType) {
case 'sug':
// 数组类型数据
if(data === '[object Array]') {
return createSug(data, dom)
}
if(data === '[object Object]') {
return createSug(data, dom)
}
return createSug([data], dom)
break;
case 'validate':
return createValidateResult(data, dom)
break;
default:
break;
}
}
终点站,创建组件模块
/**
* 创建提示建议组件模块
* @param {*} data 响应适配数据
* @param {*} dom 事件源
*/
function createSug(data, dom) {
var html = ''
for(var i = 0, len = data.length; i < len; i++) {
html += '<li>'+data[i]+'</li>'
}
dom.parentNode.getElementsByTagName('ul')[0].innerHTML = html
}
/**
* 创建校验数据组件模块
* @param {*} data 响应适配数据
* @param {*} dom 事件源
*/
function createValidateResult(data, dom) {
dom.parentNode.getElementsByTagName('span')[0].innerHTML = data
}
站点检测,单元测试
// 单元测试
var input = document.getElementsByName('input')
dealData('用户名不正确', 'validate', input[0])
dealData(['java', 'html', 'css'], 'sug', input[1])