当前位置: 首页 > news >正文

开源一个通用的 HTTP 请求前端组件

像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重,而且如果要整合到其他工具中,显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件(widget),它是一个标准 Vue 可复用的组件,能够轻易地被整合。整个组件最终界面如下。
在这里插入图片描述
该组件特性:

  • 基于 vue2/iview 方案,标准 npm 前端项目
  • 代码短小精悍,不过几个文件,不到一千行代码。
  • 依赖只有 iview 和 vue-codemirror,低耦合
  • 功能简单清晰易上手,代码易于理解与扩展

构建这么一个小组件可以说根本没什么难度,我也是一边仿着 Postman,一边“画界面”,两三天就完事了。当然后续还有很多的想法,很多的功能需要添加。不过前期肯定先出个初版,从最简单的开始。

名字就叫平淡无奇的 “api-helper” 吧~ 在线演示 源码

使用方式

标准 vue 组件。

开发历程心得

整体界面

整体界面就是调用 ivew 组件库,这部分没什么好多说的了。代码编辑器使用了 vue-codemirror,也比较简单。

<!-- JSON 源码编辑器-->
<codemirror class="code-editor" v-model="responseBody" :options="cmOption" style="height:300px;"></codemirror>

vue-codemirror 配置如下:

cmOption: {tabSize: 4,styleActiveLine: true,lineNumbers: true,mode: "application/json",// theme: "monokai"
},

编辑表格

各种 Form、QueryString、Head 需要一个表格放置参数,类似于 Postman 的:
在这里插入图片描述
一开始打算使用 iView 的 table 组件,但感觉太笨重,于是还是用原生 <table> 自己搞一个。

在这里插入图片描述
这样无论源码还是界面显得清爽很多。实际源码如下:

<template><table class="input-table"><thead><th width="50"></th><th>Key</th><th>Value</th><th>说明</th><th>操作</th></thead><tr v-for="(item, index) in tableData" :key="index" :class="{disable: !item.enable}"><td align="center"><input type="checkbox" v-model="item.enable" /></td><td><input @focus="onInputFocus" @blur="onInoutBlur" @input="onInput(index)" v-model="item.key" /></td><td><input @focus="onInputFocus" @blur="onInoutBlur" v-model="item.value" /></td><td><input @focus="onInputFocus" @blur="onInoutBlur" v-model="item.desc" /></td><td align="center"><Icon type="md-trash" class="delBtn" title="删除" @click="delRow(index)" /></td></tr></table>
</template><script>
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);}},},
};
</script><style lang="less" 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 style="color:green">${code}</span>`;else if (str[0] === '4' || str[0] === '5')return `<span style="color: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);}
}

小结

虽然这只是个小工具,但仍有不少的想象空间。不一定都把功能加到这个组件里面,但可能跟其他组件有更多的联动。希望我有时间,能够进一步丰富各种功能,也希望你们用户能提出多的宝贵意见!

相关文章:

开源一个通用的 HTTP 请求前端组件

像 Postman 这样可视化的 HTTP 请求工具是调试 API 不可或缺的利器。Postman 虽好但也越来越重&#xff0c;而且如果要整合到其他工具中&#xff0c;显然 Postman 又不是一个可行的方案。于是我想打造一个简单的前端组件&#xff08;widget&#xff09;&#xff0c;它是一个标准…...

等保测评机构资质申请条件是什么?个人可以申请吗?

最近看到不少网友在问&#xff0c;等保测评机构资质申请条件是什么&#xff1f;个人可以申请吗&#xff1f;今天我们小编就来给大家详细回答一下。 等保测评机构资质申请条件是什么&#xff1f;个人可以申请吗&#xff1f; 【回答】&#xff1a;首先需要明确一点的是&#xf…...

android 卡顿、ANR优化(1)屏幕刷新机制

前言&#xff1a; 本文通过阅读各种文章和源码总结出来的&#xff0c;如有不对&#xff0c;还望指出 目录 正文 基础概念 视觉暂留 逐行扫描 帧 CPU/GPU/Surface&#xff1a; 帧率、刷新率、画面撕裂 画面撕裂 Android屏幕刷新机制的演变 单缓存&#xff08;And…...

Landsat8中*_MTL.txt文件详解

01 什么是*_MTL.txt文件&#xff1f;所有的Landsat8 1级数据产品中均包含MTL.txt(Metadata File)文件。Landsat MTL文件包含对数据的系统搜索和归档分类有益的信息。该文件还包含关于数据处理和恶对增强陆地卫星数据有重要价值的信息&#xff08;例如转换为反射率和辐射亮度&am…...

好的提高代码质量的方法有哪些?有什么经验和技巧?

用于确保代码质量的6个高层策略&#xff1a; 1 编写易于理解的代码 考虑如下这段文本。我们有意地使其变得难以理解&#xff0c;因此&#xff0c;不要浪费太多时间去解读。粗略地读一遍&#xff0c;尽可能吸收其中的内容。 〓ts〓取一个碗&#xff0c;我们现在称之为A。取一…...

yum保留安装包

一. 用downloadonly下载 1.1 处理依赖关系自动下载到/tmp/pages目录&#xff0c;pages这个目录会自动创建 yum install --downloadonly --downloaddir/tmp/pages ceph-deploy注意&#xff0c;如果下载的包包含了任何没有满足的依赖关系&#xff0c;yum将会把所有的依赖关系包下…...

ERP系统哪家比较好?

ERP系统哪家好&#xff1f;在选择ERP系统时&#xff0c;我们可以按照这三个维度&#xff0c;然后再按照需求去选择ERP系统。 市面上ERP软件大概可以分为三大类&#xff1a; ① 标准ERP应用&#xff1a;功能比较固定&#xff0c;难以满足个性化需求&#xff0c;二次开发难度很高…...

Python读写mdb文件的实战代码

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

MAC和IP地址在字符串形式、数字形式和byte数组中的转换

MAC地址 mac地址作为网卡的物理地址,有6个byte的长度。在实际表示形式上,以每个字节的16进制,中间用冒号隔开,比如:“01:02:03:04:05:06”。这就是mac地址的字符串形式 而在网络通信传输中,需要对mac地址从字符串形式转换为数字形式或byte数组形式发送。并且网络上传输…...

时间轮来优化定时器

在raft协议中&#xff0c; 会初始化三个计时器是和选举有关的&#xff1a; voteTimer&#xff1a;这个timer负责定期的检查&#xff0c;如果当前的state的状态是候选者&#xff08;STATE_CANDIDATE&#xff09;&#xff0c;那么就会发起选举 electionTimer&#xff1a;在一定时…...

《和AI交朋友》教学设计——初识人工智能

创新整合点 &#xff08;1借助编程软件的机器学习扩展&#xff0c;使学生初步体验建立训练模型&#xff0c;让电脑进行学习的过程&#xff0c;进而感受人工智能的核心技术之一。 &#xff08;2&#xff09;借助编程软件的人工智能服务&#xff0c; 在编写程序时使用语音交互模块…...

机载雷达的时间简史

从地基起步 蝙蝠&#xff0c;虽然像人一样拥有双眼&#xff0c;但它看起东西来&#xff0c;用到的却不是眼睛。蝙蝠从鼻子里发出的超声波在传输过程中遇到物体后会立刻反弹&#xff0c;根据声波发射和回波接收之间的时间差&#xff0c;蝙蝠就可以轻易地判断出物体的位置。这一工…...

2018年MathorCup数学建模A题矿相特征迁移规律研究解题全过程文档及程序

2018年第八届MathorCup高校数学建模挑战赛 A题 矿相特征迁移规律研究 原题再现&#xff1a; 背景材料:   球团矿具有含铁品位高、粒度均匀、还原性能好、机械强度高、微气孔多等特性, 是高炉炼铁的重要原料之一。近年来国内外普遍认识到球团矿高温状态下冶金性能是评价炉料…...

如何在 Python 中创建对象列表

Python 中要创建对象列表&#xff1a; 声明一个新变量并将其初始化为一个空列表。使用 for 循环迭代范围对象。实例化一个类以在每次迭代时创建一个对象。将每个对象附加到列表中。 class Employee():def __init__(self, id):self.id idlist_of_objects []for i in range(5…...

Canny算法原理和应用

Canny算法的原理使用高斯滤波器滤波使用 Sobel 滤波器滤波获得在 x 和 y 方向上的输出&#xff0c;在此基础上求出梯度的强度和梯度的角度edge为边缘强度&#xff0c;tan为梯度方向上图表示的是中心点的梯度向量、方位角以及边缘方向&#xff08;任一点的边缘与梯度向量正交&am…...

数据挖掘(2.2)--数据预处理

目录 二、数据描述 1.描述数据中心趋势 1.1平均值和截断均值 1.2加权平均值 1.3中位数&#xff08;Median&#xff09;和众数(Mode) 2.描述数据的分散程度 2.1箱线图 2.2方差和标准差 2.3正态分布 3.数据清洗 3.1数据缺失的处理 3.2数据清洗 二、数据描述 描述数…...

JVM堆与堆调优以及出现OOM如何排查

调优的位置——堆 Heap&#xff0c;一个JVM只有一个堆内存&#xff0c;堆内存的大小是可以调节的。 类加载器读取了类文件后&#xff0c;一般会把什么东西放到堆中?类&#xff0c;方法&#xff0c;常量&#xff0c;变量~&#xff0c;保存我们所有引用类型的真实对象; 堆内存中…...

Springboot——自定义Filter使用测试总结

文章目录前言自定义过滤器并验证关于排除某些请求的方式创建测试接口请求测试验证异常过滤器的执行流程注意事项资料参考前言 在Java-web的开发领域&#xff0c;对于过滤器和拦截器用处还是很多&#xff0c;但两者的概念却极易混淆。 过滤器和拦截器都是采用AOP的核心思想&am…...

软件测试(进阶篇)(1)

一)如何根据需求来设计测试用例&#xff1f; 1)验证功能的正确性&#xff0c;合理性&#xff0c;无二义性&#xff0c;逻辑要正确 2)分析需求&#xff0c;细化需求&#xff0c;从需求中提取出测试项&#xff0c;根据测试项找到测试点&#xff0c;根据测试点具体的来进行设计测试…...

(七十三)大白话深入探索多表关联的SQL语句到底是如何执行的?(1)

今天我们来继续跟大家聊聊多表关联语句是如何执行的这个问题&#xff0c;上次讲了一个最最基础的两个表关联的语句和执行过程&#xff0c;其实今天我们稍微来复习一下&#xff0c;然后接着上次的内容&#xff0c;引入一个“内连接”的概念来。 假设我们有一个员工表&#xff0…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...