写了一个Chrome扩展,方便查看NBA赛况
前言
最近写了个Chrome扩展,在这里和大家分享一下。
我们小组日常工作用的检查工具就是一个Chrome扩展程序,可以看看这篇文章,里面有一些介绍:chrome工具优化的学习小结...当然我写的这个比较简单,没那么多复杂的功能。这个其实和我们平常写web页面差不多,所以我们前端可以写,于是我也来试试这个东西~
先来看看效果图:
默认展示当天的赛况
还有相邻两天的赛况
目录结构
├── css
│ ├── index.css
│ ├── boostrap.min.css
├── img
│ ├── icon-128.png
│ ├── icon-48.png
│ └── icon.png
├── js
│ ├── lib
│ │ └── jqurey.min.js
│ │ └── boostrap.min.js
│ └── index.js
├── manifest.json
└── popup.html
manifest.json
入口文件,每个Chrome
插件都必须包含一个manifest.json
文件,其中必须包含name
、version
和manifest_version
属性
{
"name": "NBA Plugin",
"version": "1.0",
"description": "A Chrome extension for checking nba match",
"browser_action": {
"default_icon": "img/icon.png" ,
"default_title": "NBA",
"default_popup": "popup.html"
},
"icons": {
"16": "img/icon.png",
"48": "img/icon-48.png",
"128": "img/icon-128.png"
},
"permissions": [
"http://*/*",
"https://*/*"
],
"manifest_version": 2
}
属性说明:
manifest_version
:此键指定此扩展使用的manifest.json
的版本,目前必须是2version
:插件版本号name
:插件名称description
:插件描述icons
:插件图标,Chrome
扩展程序页显示browser_action
:指定插件在Chrome
工具栏中的显示信息default_icon
:图标default_title
:标题default_popup
:弹出页
permissions
:权限
注意:如果我们需要向服务器请求数据,就需要在permissions
中添加请求数据的接口,否则会报跨域请求的限制。但是如果需要向多个接口请求数据,建议直接按我的方式书写匹配规则,这样不管多少接口都适用。
此外,还有其他的一些配置,暂时没用到。
popup.html
这个就是安装扩展之后,点击浏览器右上角小icon出现的弹出页。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>NBA</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<div class="container">
<ul id="myTab" class="nav nav-tabs">
<li><a href="#content1" class="tab yesterday" data-toggle="tab"></a></li>
<li class="active"><a href="#content2" class="tab today" data-toggle="tab"></a></li>
<li><a href="#content3" class="tab tomorrow" data-toggle="tab"></a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade" id="content1">
<table>
</table>
</div>
<div class="tab-pane fade in active" id="content2">
<table>
</table>
</div>
<div class="tab-pane fade" id="content3">
<table>
</table>
</div>
</div>
<div class="bottomlink">
<div class="left"></div>
<div class="right dropup">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
按球队查看赛程
<span class="caret"></span>
</button>
<ul class="dropdown-menu"></ul>
</div>
</div>
</div>
<script type="text/javascript" src="js/lib/jquery.min.js"></script>
<script type="text/javascript" src="js/lib/bootstrap.min.js"></script>
<script type="text/javascript" src="js/index.js"></script>
</body>
</html>
index.js
我在这里拿到了一个NBA数据的接口:http://op.juhe.cn/onebox/basketball/nba?key=c763e527b86addb9e21d455e4c467879
,其中这个KEY需要申请一下。PS:这个接口有个别字段还有点问题,url不对,比如点湖人队,查看赛程,跳去了http://kbs.sports.qq.com/kbsweb/teams.htm?tid=13,其实正确应该是http://kbs.sports.qq.com/kbsweb/teams.htm?tid=13&cid=100000
class NbaMatch {
static getData() {
$.ajax({
type: "GET",
url: "http://op.juhe.cn/onebox/basketball/nba?key=c763e527b86addb9e21d455e4c467879",
success: function(data) {
let result = data.result;
let listHtml = [];
let arr = [];
let dataList = result.list;
for (let i = 0, len = dataList.length; i < len; i++) {
$('.tab').eq(i).html(dataList[i].title)
for (let j = 0, len = dataList[i].tr.length; j < len; j++) {
arr[i] = dataList[i].tr[j];
let status = arr[i].status; //比赛状态:0未开赛、1直播中、2已结束
let statusText;
switch (status) {
case '0':
statusText = '未开赛';
break;
case '1':
statusText = '直播中';
break;
case '2':
statusText = '已结束';
break;
default:
statusText = '未知';
}
//每天的比赛列表分别存入数组
listHtml[i] = `<tr>
<td class="status${status}">${statusText}</td>
<td>${arr[i].time}</td>
<td width="64"><a href="${arr[i].player1url}" target='_blank'>${arr[i].player1}</a></td>
<td><img src="${arr[i].player1logo}" alt="logo" /></td>
<td>${arr[i].score}</td>
<td><img src="${arr[i].player2logo}" alt="logo" /></td>
<td width="64"><a href="${arr[i].player2url}" target='_blank'>${arr[i].player2}</td>
<td><a href="${arr[i].link1url}" target="_blank">${arr[i].link1text}</a></td>
<td class="ds"><a href="${arr[i].link2url}" target="_blank">${arr[i].link2text}</a></td>
</tr>`;
$('table').eq(i).append(listHtml[i]);
}
}
$('.ds a').each(function() {
$(this).click(() => {
let a = $(this).attr('href');
if (a == '' || a == 'javascript:;') {
$(this).attr('href', 'javascript:;')
alert('暂无数据');
}
})
})
// 常规赛赛程,球队排名,球员排名,社区讨论
let bottomlink = dataList[0].bottomlink;
let blHtml = '';
for (let i = 0, len = bottomlink.length; i < len; i++) {
blHtml += `<a href="${bottomlink[i].url}" target="_blank">${bottomlink[i].text}</a>`
}
$('.bottomlink .left').append(blHtml);
//球队下拉列表
let teammatch = result.teammatch;
let tmHtml = '';
for (let i = 0, len = teammatch.length; i < len; i++) {
tmHtml += `<li><a href="${teammatch[i].url}" target="_blank">
${teammatch[i].name}</a></li>`;
}
$('.dropdown-menu').append(tmHtml);
}
})
}
}
NbaMatch.getData();
安装本扩展
我把这个放在GitHub上了,有兴趣的可以体验一下。这里说下如何安装:
在Chrome浏览器地址栏打开chrome://extensions/ ,(其他浏览器就不是这个地址了,如QQ浏览器,360浏览器之类的,反正找到安装扩展的地方即可)
把这个文件夹拖拽到上面
然后就OK了。
可能有个别浏览器不能这样拖拽安装,还可以点这里安装的。
遇到的问题
1、在开发的过程中,可能会用到Chrome的一些API(不过我这里的这个小应用还暂时用不上),比如你想获取当前页面的url,像平常这样写window.location.href
是获取不到的,需要这样写:
chrome.tabs.query({active:true, currentWindow:true}, function(tab){
var curUrl = tab[0].url; //获取当前页面的url
//dosomething
});
然后还需要在manifest.json
配置文件中声明 "tabs" 权限
"permissions": [
"tabs"
]
2、引用资源文件不能直接用外链,要写相对路径,引用项目目录下的资源。这个是出于安全的考虑,不允许那样做。当然,它还是给我们留了后路。举个例子:如果想引用这个外部脚本
<script type="text/javascript" src="https://cdn.staticfile.org/jquery/3.1.1/jquery.min.js"></script>
可以在manifest.json文件这样配置一下:
"content_security_policy": "script-src 'self' https://cdn.staticfile.org; object-src 'self'"
这个也仅限于HTTPS的资源,通过将HTTPS源的脚本加入白名单来放宽“只加载本地脚本”的策略。
3、unsafe-inline报错:
Refused to execute JavaScript URL because it violates the following Content
Security Policy directive: "script-src 'self' blob: filesystem: chrome-extension-resource:".
Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to
enable inline execution.
虽然我知道写inline javascript会报这个错,就是说在html内不能像这样加js,比如这样:
<button onclick=""></button>
解决方法也简单,js不要写在HTML内,写在js文件呗。但我没想到在动态添加的Dom节点上绑定事件后也出现了这个问题,比如我这样写
$('.ds a').each(function() {
$(this).click(() => {
let a = $(this).attr('href');
if (a == '' || a == 'javascript:;') {
$(this).attr('href', 'javascript:;')
alert('未开赛,暂无数据');
}
})
})
我尝试过去掉click事件,只是改变属性,然后点击之后还是会报这个错。暂时没找到解决方法...
4、如果你是用jQuery的Ajax方法获取非本域的数据,不要加上dataType:"jsonp"
,否则会报错。jsonp
并不是通过XMLHttpRequest
实现的Ajax请求的,它是通过script标签实现跨域的,那么这样src填的就是绝对路径了,上面第2点说了一般是不可以直接引用外部资源的。其实manifest.json
文件已经声明了permissions
权限,获取了跨域请求许可,已经可以进行跨域请求的了,所以没必要写上dataType:"jsonp"
。
5、Chrome浏览器安装之后,会出现这个问题,然后每次启动后都要点一下取消,非常烦人。
这个也是Chrome的一个保护机制,提醒用户这样安装有风险,扩展应该来源于Chrome Web Store。但是有些时候我们开发的工具只是个人使用,就没发布到商店去。想解决掉这个的问题,还是有办法的。
简单地说就是在这里拿到这个ID(注意这个ID不是固定不变的) ,然后添加扩展程序白名单。网上有很多文章有介绍,这里就不描述了。比如这篇:屏蔽Google Chrome安装第三方插件之后反复提示“请停用以开发者模式运行的扩展程序”
我下面补充一点,是关于安装方式的,由于这个原因chrome浏览器下就不能按照上面那种方式安装了。要点打包扩展程序这里:
然后在和扩展程序文件夹同级目录下会生成一个crx和pem文件。
把生成的crx文件拖拽安装,然后到了这一步:
可能第一次还要点一下“已启用”,到这如无意外就正常了。
手机阅读请扫描下方二维码:
12345678
1
1
1
1
1
1
1
1
1
1
1
1
1
1
12345678
12345678
12345678
12345678
12345678
12345678
12345678
1
1
1
1
555
1
1
555
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1