写了一个Chrome扩展,方便查看NBA赛况
前言
最近写了个Chrome扩展,在这里和大家分享一下。
我们小组日常工作用的检查工具就是一个Chrome扩展程序,可以看看这篇文章,里面有一些介绍:chrome工具优化的学习小结...当然我写的这个比较简单,没那么多复杂的功能。这个其实和我们平常写web页面差不多,所以我们前端可以写,于是我也来试试这个东西~
先来看看效果图:
默认展示当天的赛况
还有相邻两天的赛况
目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | ├── 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
属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | { "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出现的弹出页。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <! 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | class NbaMatch { static getData() { $.ajax({ type: "GET" , 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
是获取不到的,需要这样写:
1 2 3 4 | chrome.tabs.query({active: true , currentWindow: true }, function (tab){ var curUrl = tab[0].url; //获取当前页面的url //dosomething }); |
然后还需要在manifest.json
配置文件中声明 "tabs" 权限
1 2 3 | "permissions": [ "tabs" ] |
2、引用资源文件不能直接用外链,要写相对路径,引用项目目录下的资源。这个是出于安全的考虑,不允许那样做。当然,它还是给我们留了后路。举个例子:如果想引用这个外部脚本
1 | <script type="text/javascript" src="https://cdn.staticfile.org/jquery/3.1.1/jquery.min.js"></script> |
可以在manifest.json文件这样配置一下:
1 | "content_security_policy": "script-src 'self' https://cdn.staticfile.org; object-src 'self'" |
这个也仅限于HTTPS的资源,通过将HTTPS源的脚本加入白名单来放宽“只加载本地脚本”的策略。
3、unsafe-inline报错:
1 2 3 4 | 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,比如这样:
1 | < button onclick = "" ></ button > |
解决方法也简单,js不要写在HTML内,写在js文件呗。但我没想到在动态添加的Dom节点上绑定事件后也出现了这个问题,比如我这样写
1 2 3 4 5 6 7 8 9 | $( '.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
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
1
1