正如前文所述,Quasar 可以处理浏览器扩展程序所在的各种位置,例如新标签页、网页、开发者工具选项或弹出窗口。你不需要为每个应用单独创建一个 Quasar 应用。你可以使用路由做一些方便的工作。
¥As already discussed, Quasar can handle the various places where a browser extension can live, namely New Tab, Web Page, Dev Tools Options or Popup. You don’t need a separate Quasar App for each of these. You can do some handy work with the router.
新标签页(New Tab)
¥New Tab
这是 BEX 的默认运行方式。点击浏览器中的 BEX 图标即可访问。Quasar 应用将在新的(空白)选项卡中运行。
¥This is the default way in which a BEX will run. It is accessed by clicking on the BEX icon in your browser. The Quasar App will run in that new (blank) tab.
开发工具、选项和弹出窗口(Dev Tools, Options and Popup)
¥Dev Tools, Options and Popup
这些都遵循相同的模式,设置一个路由,并配置 manifest.json
文件,以便在尝试显示其中一种类型时查看该路由。例如:
¥These all follow the same pattern, set up a route and configure the manifest.json
file to look at that route when it’s trying to show either one of the types. For instance:
const routes = [
{ path: '/options', component: () => import('pages/OptionsPage.vue') },
{ path: '/popup', component: () => import('pages/PopupPage.vue') },
{ path: '/devtools', component: () => import('pages/DevToolsPage.vue') }
]
你可以按如下方式配置你的 manifest.json
文件,以便从该路径加载选项页面:
¥You could configure your manifest.json
file with the following so the options page is loaded from that route:
manifest v2(manifest v2)
{
"manifest_version": 2,
"options_page": "www/index.html#/options", // Options Page
"browser_action": {
"default_popup": "www/index.html#/popup" // Popup Page
},
"devtools_page": "www/index.html#/devtools", // Dev Tools
}
manifest v3(manifest v3)
{
"manifest_version": 3,
"action": {
"default_popup": "www/index.html#/popup" // Popup Page
},
"options_page": "www/index.html#/options", // Options Page
"devtools_page": "www/index.html#/devtools", // Dev Tools
}
案例研究:网页(Case study: Web Page)
¥Case study: Web Page
这就是真正的强大之处。只需一点巧思,我们就可以将 Quasar 应用注入到网页中,并将其用作覆盖层,使其看起来像是 Quasar 应用是页面体验的一部分。
¥This is where the real power comes in. With a little ingenuity we can inject our Quasar application into a web page and use it as an overlay making it seem like our Quasar App is part of the page experience.
以下是实现此目的的简要概述:
¥Here’s a brief rundown of how you could achieve this:
src-bex/my-content-script.js
这里的想法是创建一个 IFrame,并将我们的 Quasar 应用添加到其中,然后将其注入到页面中。
¥The idea here is to create an IFrame and add our Quasar app into it, then inject that into the page.
鉴于我们的 Quasar 应用可能需要占用窗口的整个高度(从而停止与底层页面的任何交互),我们有一个事件来处理设置 IFrame 高度。默认情况下,IFrame 的高度刚好足以显示 Quasar 工具栏(从而允许与页面的其余部分进行交互)。
¥Given our Quasar App might need to take the full height of the window (and thus stop any interaction with the underlying page) we have an event to handle setting the height of the IFrame. By default the IFrame height is just high enough to allow for the Quasar toolbar to show (and in turn allowing interaction with the rest of the page).
/**
* Importing the file below initializes the content script.
* * Warning:
* Do not remove the import statement below. It is required for the extension to work.
* If you don't need createBridge(), leave it as "import '#q-app/bex/content'".
*/
import { createBridge } from '#q-app/bex/content'
const bridge = createBridge({ debug: false });
/**
* When the drawer is toggled set the iFrame height to take the whole page.
* Reset when the drawer is closed.
*/
bridge.on('wb.drawer.toggle', ({ data, respond }) => {
if (data.open) {
setIFrameHeight('100%')
} else {
resetIFrameHeight()
}
respond()
})
const iFrame = document.createElement('iframe')
const defaultFrameHeight = '62px'
/**
* Set the height of our iFrame housing our BEX
* @param height
*/
function setIFrameHeight (height) {
iFrame.height = height
}
/**
* Reset the iFrame to its default height e.g The height of the top bar.
*/
function resetIFrameHeight () {
setIFrameHeight(defaultFrameHeight)
}
/**
* The code below will get everything going. Initialize the iFrame with defaults and add it to the page.
* @type {string}
*/
iFrame.id = 'bex-app-iframe'
iFrame.width = '100%'
resetIFrameHeight()
// Assign some styling so it looks seamless
Object.assign(iFrame.style, {
position: 'fixed',
top: '0',
right: '0',
bottom: '0',
left: '0',
border: '0',
zIndex: '9999999', // Make sure it's on top
overflow: 'visible'
})
;(function () {
// When the page loads, insert our browser extension app.
iFrame.src = chrome.runtime.getURL('www/index.html')
document.body.prepend(iFrame)
})()
我们可以在 Quasar 应用中随时调用此事件,只要我们知道要打开抽屉,就可以更改 IFrame 的高度,使整个绘制过程可见。
¥We can call this event from our Quasar App any time we know we’re opening the drawer and thus changing the height of the IFrame to allow the whole draw to be visible.
src-bex/assets/content.css
在文档顶部添加边距,以便 Quasar 工具栏不会与实际页面内容重叠。
¥Add a margin to the top of our document so our Quasar toolbar doesn’t overlap the actual page content.
.target-some-header-class {
margin-top: 62px;
}
Quasar App (/src)
然后,在我们的 Quasar 应用 (/src) 中,我们有一个函数可以切换抽屉菜单,并向内容脚本发送一个事件,告诉它调整 IFrame 的大小,从而使我们的整个应用可见:
¥Then in our Quasar app (/src), we have a function that toggles the drawer and sends an event to the content script telling it to resize the IFrame thus allowing our whole app to be visible:
<q-drawer :model-value="drawerIsOpen" @update:model-value="drawerToggled">
Some Content
</q-drawer>
import { useQuasar } from 'quasar'
import { ref } from 'vue'
setup () {
const $q = useQuasar()
const drawerIsOpen = ref(true)
async function drawerToggled () {
await $q.bex.send('wb.drawer.toggle', {
open: drawerIsOpen.value // So it knows to make it bigger / smaller
})
// Only set this once the promise has resolved so we can see the entire slide animation.
drawerIsOpen.value = !drawerIsOpen.value
}
return { drawerToggled }
}
现在你的 Quasar 应用已经在网页中运行。现在,你可以从 Quasar 应用触发其他事件,内容脚本可以监听这些事件并与底层页面进行交互。
¥Now you have a Quasar App running in a web page. You can now trigger other events from the Quasar App that the content script can listen to and interact with the underlying page.
警告
请务必检查你的 manifest.json 文件,尤其是对 my-content-script.js
的引用。请注意,你可以拥有多个内容脚本。每当你创建一个新的表格时,都需要在清单文件中引用它。在 /src-bex/assets
文件夹中创建的任何 css 文件也相同。
¥Be sure to check your manifest.json file, especially around the reference to my-content-script.js
. Note that you can have multiple content scripts. Whenever you create a new one, you need to reference it in the manifest file. Same for any css files created in /src-bex/assets
folder.
"content_scripts": [
{
"matches": [ "<all_urls>" ],
"css": [ "assets/content.css" ],
"js": [ "my-content-script.js" ]
}
]