背景
最近在做中后台相关页面中涉及到录入大量的姓名,手机号码,身份证号码来生成订单,昏天黑地。往往出现bug的页面都是在录入一大堆信息之后才显示。
在开发前期时,对录入input框的内容不做限制的时候,可以随便输入111,222,测试之类的内容,虽然不好看,但是也可以快速录入,但当开发结束进入联调和反馈bug的时候,增加了对身份证号码的正确性校验,增加了手机号码的长度和区号校验,录入资料的时候还要想想。虽然比较简单,但是谁让咱比较懒呢。
其中一种解决方案是在代码中针对debug情况都自动录入默认测试数据。 另一种就是今天拍脑门的方案,做个chrome插件,直接在input框上右键选择随机姓名,随机手机号,随机身份证号码就可以快速录入合格数据,而且插件也可以分享给测试的小伙伴,也记录下chrome插件开发的流程,方便未来制作新的小插件。
基础manifest.json文件讲解
manifest.json是chrome开发指定的配置文件,指明了很多扩展信息,所以开发插件先上这个文件。
{
"name": "MockInput", //插件名称
"version": "1.01", //插件版本
"manifest_version": 2, //manifest文件版本号,填2就是了
"description": "右键录入输入框数据,烦人的手动输入", //插件描述信息
"icons": { //拓展图标,
"16": "image/icon-16.png",
"48": "image/icon-48.png",
"128": "image/icon-128.png"
},
"browser_action": { //在地址栏右侧显示信息,包含图标和弹出页面的设置。
"default_icon": "image/icon-128.png",
"default_title": "右键输入mock数据",
"default_popup": "html/browser.html"
},
"page_action": { //地址栏最后附加图标。含图标及行为等
"default_icon": "image/icon-48.png",
"default_title": "Test",
"default_popup": "html/page.html"
},
"background": { //指定扩展进程的background运行环境
"scripts": [
"js/menu.js"
]
},
"content_scripts": [ //注入web页面运行的脚本和样式。
{
"matches": [
"*://*/*"
],
"js": [
"js/content.js"
]
}
],
"homepage_url": "https://notes.tingno.com", //主页地址
"incognito": "spanning",
"offline_enabled": true,
"options_page": "html/setting.html", //设置选项页面
"options_ui":{
"page": "html/setting.html",
"chrome_style": true
},
"permissions": [ //申请权限
"*://*/*",
"contextMenus",
"tabs",
"activeTab",
"storage",
"notifications"
]
}
我这边用到的也就上面这些信息,直接帖进去载入chrome有错误的话,浏览器会进行提示。
这里特别说明content_scripts文件是在指定域名后进行脚本和样式的注入,大部分插件主要依赖这个部分。可以修改页面。
增加右键菜单
首先在配置文件的permissions中申请右键权限contextMenus,以及对应的增加扩展环境background的选项,见前面配置文件。 路径按照相对路径进行填写就行。
然后在对应的文件(我这里是js/menu.js)中添加增加菜单内容,需要多增加几个菜单就多create几个。
chrome.contextMenus.create({
type: 'normal',
title: '模拟数据插入',
id: 'menuDemo',
contexts: ['editable']
});
create第一个参数是options对象,对应的内容
- id (文本) 必备,子菜单可以指定父菜单项ID
- type ( 枚举值:[“normal”, “checkbox”, “radio”, “separator”] )右键菜单项的类型。默认为“normal”。
- title ( 文本 ) 右键菜单项的显示文字;除非类型为“separator”类否则此参数是必须的。如果类型为“selection”,您可以在字符串中使用%s显示选定的文本。例如,如果参数的值为 “Translate ‘%s’ to Pig Latin”,而用户还选中了文本“cool”,那么显示在菜单中的将会是 “Translate ‘cool’ to Pig Latin”。
- checked ( optional boolean )Checkbox或者radio的初始状态:true代表选中,false代表未选中。在给定的radio中只能有一个处于选中状态。
- contexts ( optional array of string [“all”, “page”, “frame”, “selection”, “link”, “editable”, “image”, “video”, “audio”] )右键菜单项将会在这个列表指定的上下文类型中显示。默认为“page”。
- onclick ( optional function )当菜单项被点击时触发的函数。参数info ( OnClickData )右键菜单项被点击时相关的上下文信息。 参数tab ( Tab )右键菜单项被点击时,当前标签的详细信息。
- parentId ( optional integer )右键菜单项的父菜单项ID。指定父菜单项将会使此菜单项成为父菜单项的子菜单。
- documentUrlPatterns ( optional array of string )这使得右键菜单只在匹配此模式的url页面上生效(这个对框架也适用)。详细的匹配格式见:模式匹配页面。
- targetUrlPatterns ( optional array of string )类似于documentUrlPatterns,但是您可以针对img/audio/video标签的src属性和anchor标签的href做过滤。
- enabled ( optional boolean )启用或者禁用此菜单项,启用为true,禁用为false。默认为true。
create还包含一个回调函数,在创建完菜单项后触发。如果创建过程中有错误产生,其详细信息在Chrome.extension.lastError中。
我的需求里面包含随机姓名、随机手机号、随机身份证、指定姓名、指定手机号、指定身份证。一个总菜单,带6个子菜单,而且默认我们只是在输入框右键的时候,需要弹出菜单,其他地方没啥用。
在总菜单之后,加上子菜单。
//子菜单带上
chrome.contextMenus.create({
type: 'normal',
title: '随机证件号',
id: 'randomPerson',
parentId: 'menuDemo',
contexts: ['editable'],
onclick: genericOnClick
});
出来效果是什么样子的呢?
点击子菜单之后,要将点击了哪个菜单推送到页面中去,方便页面进行操作。
sendMessage,onMessage消息传递
由于右键点击菜单逻辑是在backgroud里面实现,而具体的元素输入是在具体的tab实现。tab向background发送消息的话,就一个不需要指定。而background发送消息的话,就需要指定具体哪个tab,并且在对应的页面进行接收。
发送的话,是在右键菜单的onclick函数genericOnClick中实现。前面也不知道具体用到啥,全送过去再说。而且onclick的参数句柄上也已经给定了是哪个页面点击右键,发回去就行了。
function genericOnClick(info, tab) {
chrome.tabs.sendMessage(tab.id, {'tab':tab, 'info': info });
}
然后就是在具体的content.js中接收消息,加一个监听。拿到具体的内容进行打印就行了。
chrome.extension.onMessage.addListener(function(request, _, response) {
console.log(request)
});
元素绑定
对应的事件传递到当前的话,就可以生成对应的随机值,然后输入页面就可以了。不过由于时间短暂,所以没找到回传具体右键点击了什么元素,只能在页面进行注入,右键的时候,指定下具体点击的是哪个元素。目前插件只需要input,所以给所有的页面的input绑定事件。
var mockContent = null
var inputs = document.getElementsByTagName('input')
for(var i=0; i< inputs.length; i++){
inputs[i].addEventListener('contextmenu',function(){
mockContent = this
})
}
当点击回调事件回来之后,就知道具体右击的是什么元素,就可以直接将对应元素还值就是了。
输入事件
前面元素绑定,加值之后,就是直接mockContent.value = 值就是了。但是我们后台用的是vue写的,直接操作dom上的value值,不能引起对应的双向绑定生效,页面元素校验审核也不通过。这时候就需要手动触发下对应的input事件。就变成了下文。随机生成姓名,手机号,身份证不在本文讨论范围内。自行翻阅之前文章内容。
mockContent.value = value
mockContent.dispatchEvent(new Event('input'))
插件存储storage
在配置文件里面声明权限
有时候,其实我们希望录入的内容是固定的,比如手机号码。随机填写别人的也可以,但是你的系统如果同时还给别人发送验证码啊,消息通知之类的就不好了。这时候其实配置一下指定内容既可,这时候就用到的配置页面,一般配置信息都存储在storage。最重要的是,放在此处的内容是全局的。
你直接使用chrome.storage进行操作就行了。插件的存储分为local和sync两种,sync的配置可以跟着你的谷歌帐号同步的。自己也用不到,就先用本地的好了。内容也很简单。
//写入
chrome.storage.local.set({name:'name',age:19},_=>{
})
//读取,格式一样,属性后面的值是默认值。
chrome.storage.local.get({name:'name',age:19},items=>{
console.log(items.name, items.age)
})
注意,读取和写入都是异步操作。
通知 notifications
保存成功要消息提醒一下,在配置文件里面声明权限,直接用就是了,也很简单。
chrome.notifications.create(null, {
type: 'basic',
iconUrl: '../image/icon-48.png',
title: '保存成功',
message: '配置已经生效,请继续使用!'
});
当然样式可以很丰富,具体看你自己的需要。
文末
只要用chrome,基本上都会用插件的。开发满足自己需求的插件,提高效率,堪称神器。
文中提到的小插件已经放在了github上,大神看看笑话就得了,单纯自用。 MockInput
另外,还有批量生成模拟信息的页面 模拟个人信息测试用