app.js(单页面解决方案)
为什么
在开发过程中通常会遇到一些问题。比如说,一个项目,经过与后台开发人员的沟通之后,大概确立了有多少个接口,各个接口需要传什么值,但一般来说都还不太清晰,只有等后台开发人员把接口完全给出来后才清楚。所以,当前端把样式写好之后,而后台开发滞后的时候,前端就得等后端给接口文档,这得多费心啊。而且在拿到文档滞后也免不了各种沟通和改动。
一个字,麻烦。
为了解决这些问题,使前后台沟通尽量简化,所以就写了这么一个解决方案
主要功能
- 全局配置
- 封装ajax请求
- 统一事件监听
- 数据绑定
依赖
内置
使用方式
1. 加载js脚本
<script src="./jquery.js"></script>
<script src="./juicer.js"></script>
<script src="../src/app.js"></script>
2. 载入配置
app.init(appConfig);
示例配置
var appConfig = {
environment: 2 //环境标识(用于数组选值):0->服务器环境, 1->测试环境, 2->本地环境
};
//ajax请求相关
appConfig.ajax = {
//所有请求的名字,这里可以是对象,也可是数组,但请不要使用“common”字段和值
name: {
a: "aaa",
b: "bbb",
c: "ccc",
d: "ddd"
},
//url请求地址
url: {
//数组
aaa: ["url1", "url2", "url3"],
bbb: ["url1", "url2", "url3"],
ccc: ["url1", "url2", "url3"],
ddd: ["url1", "url2", "url3"]
},
//请求的键名
requestKeys: {
//可以是一维数组,也可是二维数组,如果是一维数组,代表没有键,如果是二维数组,代表键值都有
aaa: [["a", "b"], ["c", "d"], ["e", "f"]],
bbb: [["a", "b"], ["c", "d"], ["e", "f"]],
ccc: [{a: "a", b: "b"}, {c: "c", d: "d"}, {e: "e", f: "f"}],
ddd: [{a: "a", b: "b"}, {c: "c", d: "d"}, {e: "e", f: "f"}]
},
//重新格式化json数据,针对每一个
responseRefactor: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [{}, {}, {}],
aaa: [{}, {}],
bbb: [{}],
ccc: {},
ddd: {}
},
//ajax请求前置处理(用于格式化请求参数)
preHandle: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [function (data) {}, function () {}, function () {}],
aaa: [function (data) {}, function () {}],
bbb: [function (data) {}],
ccc: function (data) {},
ddd: function (data) {}
},
//ajax请求后置处理(用于格式化请求到的数据)
postHandle: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [function (data) {}, function () {}, function () {}],
aaa: [function (data) {}, function () {}],
bbb: [function (data) {}],
ccc: function (data) {},
ddd: function (data) {}
}
};
//事件监听
appConfig.event = {
//事件代理元素,默认是document
el: "body",
events: {
//重中之重,元素与事件之间使用空格分隔,多个事件之间用逗号分隔,且不能有空格
//一个事件,一个监听对象,默认使用代理
"click #id": "haha",
//前面加一个感叹号表示不使用代理
"!focus tagName": "haha",
//二级元素,也使用代理
"click .class tagName": "haha",
//多个事件
"click,focus #id": "haha",
//多个事件,不使用代理
"!click,focus tagName": "haha",
//多个元素
"click .class, tagName, #id .class tagName": "haha"
},
haha: function(e) {
}
};
/**
* 模板渲染函数,默认使用 [juicer](https://github.com/PaulGuo/Juicer) (一个小巧的模板引擎)
*
* 比如
* handlebars: Handlebars.compile
* juicer: juicer
*/
appConfig.templateRenderer = void 0;
//模板
appConfig.template = {
tpl1: "cdvbkjd",
tpl2: {
tpl22: "vjjksm"
},
tpl3: {
tpl33: {
tpl333: "vfkdvnjk"
}
}
};
//数据绑定
appConfig.dataBind = {
//数据名
name1: {
element: "el",//元素绑定到某一个元素上
template: "templateName"//模板名
},
name2: {
element: "",//元素绑定到某一个元素上
template: {//可以是对象(多个模板选择)
fieldName: {//字段标识,以数据中的哪个字段来判断是用哪个模板
fieldValue: "templateName.subTemplateName.subSubTemplateName"//fieldValue: 字段值, templateName:模板名,多级请采用点语法
}
}
}
};
配置说明
1. base
var appConfig = {
environment: 2 //环境标识(用于数组选值):0->服务器环境, 1->测试环境, 2->本地环境
};
主要用来辨识本地环境还是服务器环境,一般来说,后面的配置项都会使用数组的形式,这些数组中会有两个元素,本地和服务器端,0和1代表他们在数组中的索引
2. ajax
//ajax请求相关
appConfig.ajax = {
//所有请求的名字,这里可以是对象,也可是数组,但请不要使用“common”字段和值
name: {
a: "aaa",
b: "bbb",
c: "ccc",
d: "ddd"
},
//url请求地址
url: {
//数组
aaa: ["url1", "url2", "url3"],
bbb: ["url1", "url2", "url3"],
ccc: ["url1", "url2", "url3"],
ddd: ["url1", "url2", "url3"]
},
//请求的键名
requestKeys: {
//可以是一维数组,也可是二维数组,如果是一维数组,代表没有键,如果是二维数组,代表键值都有
aaa: [["a", "b"], ["c", "d"], ["e", "f"]],
bbb: [["a", "b"], ["c", "d"], ["e", "f"]],
ccc: [{a: "a", b: "b"}, {c: "c", d: "d"}, {e: "e", f: "f"}],
ddd: [{a: "a", b: "b"}, {c: "c", d: "d"}, {e: "e", f: "f"}]
},
//重新格式化json数据,针对每一个
responseRefactor: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [{}, {}, {}],
aaa: [{}, {}],
bbb: [{}],
ccc: {},
ddd: {}
},
//ajax请求前置处理(用于格式化请求参数)
preHandle: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [function (data) {}, function () {}, function () {}],
aaa: [function (data) {}, function () {}],
bbb: [function (data) {}],
ccc: function (data) {},
ddd: function (data) {}
},
//ajax请求后置处理(用于格式化请求到的数据)
postHandle: {
//数组,根据environmentFlag来判定,如果是非数组,则表示标识为0的环境
common: [function (data) {}, function () {}, function () {}],
aaa: [function (data) {}, function () {}],
bbb: [function (data) {}],
ccc: function (data) {},
ddd: function (data) {}
}
};
- name: 用来标示一个请求,如果是数组,在请求的时候传入index,如果是map,传入key,参见【全局变量app】一节
- url: 请求的地址,每一个值都必须是数组,包含两个元素,服务器和本地
- requestKeys: 请求的参数名,必须是数组。如果数组元素也是数组,则在请求的时候传入的data值也必须是数组,并且顺序需要一一对应;如果是map,则在请求的时候传入的data值也必须是map。参见【全局变量app】一节
- responseRefactor: 针对返回的json数据做重构。json-refactor(common是保留字段,会应用在每一个返回上)
- preHandle: 请求预处理。针对请求做更多的动态处理。(common是保留字段,会应用在每一个返回上)
- postHandle: 请求后置处理。针对返回的数据做更多的动态处理,在json重构之后执行。(common是保留字段,会应用在每一个返回上)
3. event
appConfig.event = {
//事件代理元素,默认是document
el: "body",
events: {
//重中之重,元素与事件之间使用空格分隔,多个事件之间用逗号分隔,且不能有空格
//一个事件,一个监听对象,默认使用代理
"click #id": "haha",
//前面加一个感叹号表示不使用代理
"!focus tagName": "haha",
//二级元素,也使用代理
"click .class tagName": "haha",
//多个事件
"click,focus #id": "haha",
//多个事件,不使用代理
"!click,focus tagName": "haha",
//多个元素
"click .class, tagName, #id .class tagName": "haha"
},
haha: function(e) {
}
};
- el: 事件代理元素,默认是document
- events: 事件总集,与backbone基本一致。如果不想使用代理,可在事件前面加上 "!"
4. template
// 自定义模板编译函数
appConfig.templateRenderer = void 0;
// 模板
appConfig.template = {
tpl1: "cdvbkjd",
tpl2: "vdfvd",
tpl3: "fdsvdf"
};
- 目前支持3级属性,如果以下也是可以解析的,但是访问编译好的模板也需要带上属性值tpl1
appConfig.template = {
tpl1: "cdvbkjd",
tpl2: {
tpl22: "vjjksm"
},
tpl3: {
tpl33: {
tpl333: "vfkdvnjk"
}
}
};
5.data bind
//数据绑定
appConfig.dataBind = {
//数据名
name1: {
element: "el",//元素绑定到某一个元素上
template: "templateName"//模板名
},
name2: {
element: "",//元素绑定到某一个元素上
template: {//可以是对象(多个模板选择)
fieldName: {//字段标识,以数据中的哪个字段来判断是用哪个模板
fieldValue: "templateName.subTemplateName.subSubTemplateName"//fieldValue: 字段值, templateName:模板名,多级请采用点语法
}
}
}
};
- 元素应该是唯一的
- 需要有相应的模板去渲染这个数据
全局变量app
属性:
- init(config) 初始化页面
- get(url, data, callback, type) get请求,url是索引值还是键名(字符串)取决于配置,data是数组还是map也取决于配置
- post(url, data, callback, type, stringify) post请求,其他同get请求(stringify: 是否序列化请求参数)
- setData(name, data) 设置数据
- addData(name, data) 添加数据
- compiledTemplate 编译后的模板,如果配置中有template的话