Chrome插件開發(fā)簡要指南

2022-05-24 09:37 更新

Chrome是個(gè)非常牛逼的瀏覽器,速度快,界面清爽,對(duì)開發(fā)人員友好。而且提供了種類齊全且高質(zhì)的插件。今天我們就來簡單聊一聊如何開發(fā)chrome插件。

基本知識(shí)

在具體的開發(fā)之前,我們先來科普一些基礎(chǔ)知識(shí)。

現(xiàn)階段的chrome的應(yīng)用商店中,將插件(這里說的插件指代chrome應(yīng)用的所有分類,下文亦同)分為如下幾種,包括應(yīng)用、游戲擴(kuò)展程序、主題背景。而且插件的種類多種多樣,保羅萬象,基本上都能找到你想要的功能的插件。

文件結(jié)構(gòu)

在應(yīng)用商店中下載下來的插件基本上都是以.crx為文件后綴,該文件其實(shí)就是一個(gè)壓縮包,包括插件所需要的html、css、javascript、圖片資源等等文件。

下圖是FEHelper的插件包解壓后的文件,

其中,

  • manifest.json是整個(gè)插件的功能及文件配置清單,非常重要。
  • static目錄是放置整個(gè)插件的靜態(tài)資源文件的,包括css、js、圖片等等資源
  • template目錄是放置整個(gè)插件的功能頁面模板的。
  • _locales目錄是放置整個(gè)插件的國際化語言腳本的。

一般來說,清單文件manifest.json文件是必須的,且必須放在插件開發(fā)目錄的根目錄上。其他的目錄都可以自定義。

這個(gè)插件安裝好的用戶界面如下圖,

圖中的每一個(gè)鏈接都是一個(gè)功能項(xiàng),點(diǎn)擊后將會(huì)打開一個(gè)chrome-extension下的頁面,url類似這樣,

chrome-extension://pkgccpejnmalmdinmhkkfafefagiiiad/template/fehelper_endecode.html

而這些頁面其實(shí)就是我們之前看到的template中的模板文件。

manifest.json文件

清單文件的作用是提供插件的各種信息,例如插件能夠做的事情,以及插件的文件配置等等信息。下面是一個(gè)清單文件的示例,

{
  "name": "我的擴(kuò)展程序",
  "version": "2.1",
  "manifest_version": 2,
  "description": "從Google獲得信息。",
  "icons": {
    "128": "icon_128.png"
  },
  "background": {
    "persistent": false,
    "scripts": ["bg.js"]
  },
  "permissions": ["http://*.google.com/", "https://*.google.com/"],
  "browser_action": {
    "default_title": "",
    "default_icon": "icon_19.png",
    "default_popup": "popup.html"
  }
}

mianfest.json文件每個(gè)字段都有其特殊的含義。

兩種用戶界面

chrome插件一般有兩種用戶界面,一種是瀏覽器按鈕,一種是頁面地址欄按鈕。前者稱之為Browser Actions,后者被稱之為Page Actions

這是page actions:


這是browser actions:



Page ActionsBrowser Actions 的區(qū)別就是 Page Actions 并不是在每個(gè)頁面上都是有用的,它必須在特定的頁面中插件功能才能使用。

這兩種用戶面界面分別對(duì)應(yīng)manifest.json中的browser_actionpage_action字段。

彈出窗口和后臺(tái)頁面

彈出窗口一般用于插件和用戶的交互,而后臺(tái)頁面一般用于插件本身做一些額外的事情。比如有時(shí)候,插件需要聯(lián)網(wǎng)進(jìn)行數(shù)據(jù)同步等操作,這種操作用戶是無感知的,所有就要求插件需要有一個(gè)后臺(tái)頁面來運(yùn)行這部分的邏輯。

其實(shí)后臺(tái)頁面還可以分為持久運(yùn)行的后端頁面和事件頁面,這里對(duì)這兩者就不多做說明了,更多的內(nèi)容可以參閱具體的文檔。

其他

chrome插件的相關(guān)知識(shí),遠(yuǎn)遠(yuǎn)不止上面介紹的幾點(diǎn),比如郵件菜單、插件與瀏覽器之間的交互、內(nèi)容安全(CSP)、消息傳遞、國際化、部署與托管等等方面,由于篇幅原因,這里將不會(huì)作過多的描述。

自己做一個(gè)

有了上面的基礎(chǔ)知識(shí)之后,我們就可以嘗試自己來做一個(gè)chrome插件玩玩了。

首先我們新建一個(gè)文件夾叫做todo-plugin,作為插件開發(fā)的工作目錄,然后在目錄中新建清單文件,manifest.json文件內(nèi)容如下,

{
    "name": "todo-plugin",
    "version": "0.9.0",
    "manifest_version": 2,
    "description": "chrome plugin demo",
    "browser_action": {
        "default_icon": "icon.png",
        "default_title": "Todo List",
        "default_popup": "popup.html"
    }
}

在清單文件中,我們定義了插件的名稱、版本、描述,插件的瀏覽器按鈕行為以及插件所需要注入的腳本文件。按鈕行為中還包括了默認(rèn)的按鈕圖標(biāo)、按鈕標(biāo)題(鼠標(biāo)懸停時(shí)顯示)以及默認(rèn)的彈出框popup.html

注意:新版的chrome插件開發(fā)需要在清單文件中制定mainfest_version為2。

這里的彈出框其實(shí)就是我們這個(gè)插件與用戶交互的主要界面,它其實(shí)就是一個(gè)html頁面。不過這個(gè)popup.html文件并不需要<html></html><body></body>、<head></head>這樣的標(biāo)簽。popup.html文件內(nèi)容如下,

<style>
    body {
        width: 150px;
    }
    #add-new-item {
        cursor: pointer;
        color: #CCC;
    }
    .hide {
        display: none;
    }
    .show {
        display: block;
    }
    .item {
        cursor: pointer;
        margin: 5px 0;
    }
    .item input {
        display: inline-block;
        width: 12px;
        height: 12px;
    }
    input {
        width: 120px;
    }
</style>
<div id="add-new-item">添加新項(xiàng)</div>
<div id="add-new-item-input" class="hide">
    <input type="text" id="new-item-title" placeholder="添加新任務(wù)"/>
</div>
<div id="item-list"></div>
<script type="text/javascript" src="main.js"></script>

這個(gè)html文件其實(shí)很簡單(chrome插件的html頁面往往都非常簡單,都是一些列表的展示,輕量的輸入控件等等),而且為了簡便,我把彈出窗的樣式直接寫在html中了。

最后一行我們使用外鏈的方式加載了popup頁面的交互邏輯。main.js內(nèi)容也很簡單,如下,

(function () {
    var $ = function (id) {
        return document.getElementById(id);
    };
    var Tasks = {
        show: function (obj) {
            obj.className = '';
            return this;
        },
        hide: function (obj) {
            obj.className = 'hide';
            return this;
        },
        $addNewItem: $('add-new-item'),
        $addNewItemInput: $('add-new-item-input'),
        $itemList: $('item-list'),
        $newItemTitle: $('new-item-title'),
        init: function () {
            //打開添加文本框
            Tasks.$addNewItem.addEventListener('click', function () {
                Tasks.show(Tasks.$addNewItemInput).hide(Tasks.$addNewItem);
                Tasks.$newItemTitle.focus();
            }, true);
            //回車添加任務(wù)
            Tasks.$newItemTitle.addEventListener('keyup', function (ev) {
                var ev = ev || window.event;
                if (ev.keyCode == 13) {
                    //TODO:寫入本地?cái)?shù)據(jù)
                    var task = Tasks.$newItemTitle.value;
                    Tasks.AppendHtml(task);
                    Tasks.$newItemTitle.value = '';
                    Tasks.hide(Tasks.$addNewItemInput).show(Tasks.$addNewItem);
                }
                ev.preventDefault();
            }, true);
            //取消添加
            Tasks.$newItemTitle.addEventListener('blur', function () {
                Tasks.$newItemTitle.value = '';
                Tasks.hide(Tasks.$addNewItemInput).show(Tasks.$addNewItem);
            }, true);
            //TODO 初始化數(shù)據(jù),加載本地?cái)?shù)據(jù),生成html
        },
        //增加
        Add: function () {
            //TODO
        },
        //修改
        Edit: function () {
            //TODO
        },
        //刪除
        Del: function () {
            //TODO
        },
        AppendHtml: function (title) {
            var oDiv = document.createElement('div');
            oDiv.className = 'item item-todo';
            var oInput = document.createElement('input');
            oInput.type = 'checkbox';
            var oTitle = document.createElement('span');
            oTitle.innerHTML = title;
            oDiv.appendChild(oInput);
            oDiv.appendChild(oTitle);
            Tasks.$itemList.appendChild(oDiv);
            oDiv.addEventListener('click', function () {
                //TODO
            }, true);
        },
        RemoveHtml: function () {
            //TODO
        }
    }
    Tasks.init();
})();

在這段js中,我們聲明了一個(gè)Tasks對(duì)象,這個(gè)對(duì)象包括了一系列的功能方法,當(dāng)然有部分未實(shí)現(xiàn),不過核心功能都實(shí)現(xiàn)了。在Tasks.init方法中,我們給一個(gè)操作實(shí)體(一個(gè)div元素)注冊(cè)了點(diǎn)擊事件,當(dāng)觸發(fā)點(diǎn)擊事件時(shí),我們將會(huì)展示一個(gè)輸入框讓用戶輸入任務(wù)描述,通過回車鍵來添加用戶剛輸入的任務(wù)。好了,這就是todo-plugin插件的基本功能。下面是本插件的效果預(yù)覽,

小結(jié)

好了,至此我們總算完成一個(gè)簡陋的chrome插件的開發(fā)了。功能雖然簡陋,但是基本上所有的chrome插件開發(fā)都是遵循這條路。本文示例的代碼中有許多的TODO,其實(shí)我們可以將這個(gè)todo插件做的更加復(fù)雜,比如可以采用localstorage來存儲(chǔ)數(shù)據(jù),甚至可以使用網(wǎng)絡(luò)來存儲(chǔ)數(shù)據(jù)。至于更多的內(nèi)容,本文就不再作過多的闡述了,因?yàn)楸疚漠吘故?strong>簡要指南嘛

參考鏈接


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)