鼠標右擊網頁會彈出默認的瀏覽器菜單,可是不少時候咱們須要自定義右鍵菜單(好比:在線文檔編輯器、定製視頻播放器等)。今天咱們就來快速實現一個自定義右鍵菜單。git
預覽:github
contextmenu
事件監聽首先,咱們須要禁用瀏覽器彈出默認菜單的行爲,經過阻止 contextMenu 事件的默認行爲,並同時觸發自定義菜單的顯示:瀏覽器
document.addEventListener("contextmenu", (e) => { e.preventDefault(); showMenu(e); });
一個頁面中菜單應該只有一個實例,因此咱們運用單例模式去建立菜單,典型的單例構造器能夠實現爲:app
const ContextMenu = function (options) { // 惟一實例 let instance; // 建立實例方法 function createMenu() { // todo } return { // 獲取實例的惟一方式 getInstance: function () { if (!instance) { instance = createMenu(); } return instance; }, }; };
即實現上面的 createMenu
方法。編輯器
菜單的具體配置經過 options
傳入,options
的結構定義爲:ide
options: { menus: [{ name: string, // 菜單名稱 onClick: Function // 菜單點擊回調 }] }
經過遍歷 options.menus
生成菜單列表,並掛載到 body
中,並最終返回菜單的實例:spa
function createMenu() { const ul = document.createElement("ul"); ul.classList.add("custom-context-menu"); const { menus } = options; if (menus && menus.length > 0) { for (let menu of menus) { const li = document.createElement("li"); li.textContent = menu.name; li.onclick = menu.onClick; ul.appendChild(li); } } const body = document.querySelector("body"); body.appendChild(ul); return ul; }
建立菜單的主要邏輯就完成了。code
接下來向 ContextMenu
中傳入 options
以初始化單例構造器:視頻
const menuSinglton = ContextMenu({ menus: [ { name: "custom menu 1", onClick: function (e) { console.log("menu1 clicked"); }, }, { name: "custom menu 2", onClick: function (e) { console.log("menu2 clicked"); }, }, { name: "custom menu 3", onClick: function (e) { console.log("menu3 clicked"); }, }, ], });
初始化完成後,即可以經過 menuSinglton.getInstance()
獲取菜單實例了。blog
當咱們右擊頁面時,獲取到鼠標的座標,設置菜單爲固定定位(position: fixed
),並將其左上角位置設置爲鼠標座標,以實現菜單在鼠標點擊位置的彈出:
function showMenu(e) { const menus = menuSinglton.getInstance(); menus.style.top = `${e.clientY}px`; menus.style.left = `${e.clientX}px`; menus.style.display = "block"; }
最後,當咱們點擊頁面中的其餘區域時須要將菜單隱藏:
function hideMenu(e) { const menus = menuSinglton.getInstance(); menus.style.display = "none"; } document.addEventListener("click", hideMenu);
大功告成!!
本文Demo參考:Codepen Trick by Day (2020-07-05) Custom Context Menus
天天一個小技巧,量變引發質變,但願你和我一塊兒天天多學一點,讓技術有趣一點。全部示例將會彙總到個人 tricks-by-day github項目中,歡迎你們蒞臨指導 😊