招商加盟网站建设,高坪网站建设,wordpress json插件安装,郑州做网站那像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重#xff0c;而且如果要整合到其他工具中#xff0c;显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件#xff08;widget#xff09;#xff0c;它是一个标准…像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重而且如果要整合到其他工具中显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件widget它是一个标准 Vue 可复用的组件能够轻易地被整合。整个组件最终界面如下。 该组件特性
基于 vue2/iview 方案标准 npm 前端项目代码短小精悍不过几个文件不到一千行代码。依赖只有 iview 和 vue-codemirror低耦合功能简单清晰易上手代码易于理解与扩展
构建这么一个小组件可以说根本没什么难度我也是一边仿着 Postman一边“画界面”两三天就完事了。当然后续还有很多的想法很多的功能需要添加。不过前期肯定先出个初版从最简单的开始。
名字就叫平淡无奇的 “api-helper” 吧~ 在线演示 源码
使用方式
标准 vue 组件。
开发历程心得
整体界面
整体界面就是调用 ivew 组件库这部分没什么好多说的了。代码编辑器使用了 vue-codemirror也比较简单。
!-- JSON 源码编辑器--
codemirror classcode-editor v-modelresponseBody :optionscmOption styleheight:300px;/codemirrorvue-codemirror 配置如下
cmOption: {tabSize: 4,styleActiveLine: true,lineNumbers: true,mode: application/json,// theme: monokai
},编辑表格
各种 Form、QueryString、Head 需要一个表格放置参数类似于 Postman 的 一开始打算使用 iView 的 table 组件但感觉太笨重于是还是用原生 table 自己搞一个。 这样无论源码还是界面显得清爽很多。实际源码如下
templatetable classinput-tabletheadth width50/ththKey/ththValue/thth说明/thth操作/th/theadtr v-for(item, index) in tableData :keyindex :class{disable: !item.enable}td aligncenterinput typecheckbox v-modelitem.enable //tdtdinput focusonInputFocus bluronInoutBlur inputonInput(index) v-modelitem.key //tdtdinput focusonInputFocus bluronInoutBlur v-modelitem.value //tdtdinput focusonInputFocus bluronInoutBlur v-modelitem.desc //tdtd aligncenterIcon typemd-trash classdelBtn title删除 clickdelRow(index) //td/tr/table
/templatescript
export default {data() {return {tableData: this.data,};},props: {data: { type: Array, required: true },},methods: {onInputFocus(e) {let input e.target;if (input.parentNode input.parentNode.parentNode input.parentNode.parentNode.tagName TR) {let tr input.parentNode.parentNode;tr.classList.add(highlight);}},onInoutBlur(e) {let input e.target;if (input.parentNode input.parentNode.parentNode input.parentNode.parentNode.tagName TR) {let tr input.parentNode.parentNode;tr.classList.remove(highlight);}},onInput(index) {if (index 1 this.tableData.length) {// 最后一行this.tableData.push({enable: true,key: ,value: ,desc: ,});}},delRow(index) {if (this.tableData.length 1) {} else {this.$delete(this.tableData, index);}},},
};
/scriptstyle langless scoped
.input-table {width: 100%;border-collapse: collapse;input {border: 1px solid transparent;outline: none;padding: 0px 3px;width: 100%;}input:focus {border: 1px solid lightgray !important;background-color: white !important;}tr {.highlight {background-color: #f9f9f9;input {border-color: #f9f9f9;background-color: #f9f9f9;}}.disable {input {color: lightgray;}}}td,th {padding: 5px 5px;border: 1px solid lightgray;}
}.delBtn {cursor: pointer;
}
/style输入的 tableData 格式如下。 tableData: [{enable: true,key: sdsd,value: sdssds3,},{enable: false,key: sdsd,value: sdssds3,},],XHR 请求
HTTP 请求的核心自然是 XMLHttpRequest(); 的使用。必须要高度订制化而不是复用某个 xhr 组件。写原生 xhr 实际也很简单参见我的 xhr.js 源码。
// XHR 发送组件
export default {data() {return {loading: false,response: {readyState: 0,status: 0,elapsed: 0,},};},methods: {doRequest(method, url, params, cfg) {let el new Date();let xhr new XMLHttpRequest();xhr.open(method, url);xhr.timeout 5000; // 设置超时时间为5秒xhr.ontimeout () this.loading false;// 请求超时后的处理xhr.onreadystatechange () {this.loading true;this.response.readyState xhr.readyState;this.response.status xhr.status;if (xhr.readyState 4) {try {if (!xhr.responseText) {this.$Message.error(服务端返回空的字符串);this.loading false;return;}// 跨域可能不能获取完整的响应头 https://qzy.im/blog/2020/09/can-not-get-response-header-using-javascript-in-cors-request/let heads xhr.getAllResponseHeaders();heads heads.split(;).join(\n);this.responseHead heads;let parseContentType cfg cfg.parseContentType;switch (parseContentType) {case text:data responseText;break;case xml:data xhr.responseXML;break;case json:default:this.responseBody JSON.stringify(JSON.parse(xhr.responseText), null, 2);}} catch (e) {alert(HTTP 请求错误:\n e \nURL: url); // 提示用户 异常} finally {this.loading false;this.response.elapsed new Date() - el;}}};let requestAll HEAD \n method.toUpperCase() url \n;if (cfg cfg.header) {for (let i in cfg.header) {requestAll i : cfg.header[i] \n;xhr.setRequestHeader(i, cfg.header[i]);}}if (params)requestAll BODY:\n params;this.requestAll requestAll;xhr.send(params || null);},formatStatusCode() {let code this.response.status;let str code ;if (str[0] 2)return span stylecolor:green${code}/span;else if (str[0] 4 || str[0] 5)return span stylecolor:red${code}/span;elsereturn str;}},
};它基于 vue 的 mixins 特性进行分离。主意是控制一些请求状态之类的已经返回特定的数据给前端显示。
工具函数
还有一些小的工具函数值得说下。
格式化 JSON
格式化 JSON利用 JSON.stringify()指定第三个参数即可加入缩进indent。
formatJs() {let json this.requestParams.raw.json;json JSON.stringify(JSON.parse(json), null, 4);this.requestParams.raw.json json;
}读写剪贴板
用 Javascript 的 navigator.clipboard 对象来复制文本或图片到剪贴板但运行时会遇到以下错误
navigator.clipboard undefined这个错误的原因是 navigator.clipboard 对象只能在安全网络环境中才能使用换言之localhost、127.0.0.1 或者 https 中才能正常使用否则用 http 或 IP 地址不允许访问。
最终的读取方法
// 读取粘贴板
try {navigator.clipboard.readText().then((v) {console.log(获取剪贴板成功, v);this.requestParams.head.unshift({enable: true,key: Authorization,value: Bearer v,desc: 认证用的 token,});}).catch((v) {console.log(获取剪贴板失败: , v);});
} catch (e) {console.log(e);this.$Message.error(不支持读取粘贴板);
}写入剪切板却有兼容方法。
/**
* 复制文字到剪切板
*
* param {*} text
*/
aj.copyToClipboard function (text) {if (navigator.clipboard) {// clipboard api 复制navigator.clipboard.writeText(text);} else {var textarea document.createElement(textarea);document.body.appendChild(textarea);// 隐藏此输入框textarea.style.position fixed;textarea.style.clip rect(0 0 0 0);textarea.style.top 10px;// 赋值textarea.value text;// 选中textarea.select();// 复制document.execCommand(copy, true);// 移除输入框document.body.removeChild(textarea);}
}小结
虽然这只是个小工具但仍有不少的想象空间。不一定都把功能加到这个组件里面但可能跟其他组件有更多的联动。希望我有时间能够进一步丰富各种功能也希望你们用户能提出多的宝贵意见