Posted in

用 electron 写个浏览器给自己玩 – 掘金_AI阅读总结 — 包阅AI

包阅导读总结

1. `Electron`、`浏览器`、`功能`、`组装`、`下载拦截`

2. 作者基于 Electron 和 WebView 写了一个给自己玩的浏览器,介绍了下载拦截、页面搜索等功能的实现,还提到了当前标签页打开、标签页切换、地址栏等功能,最后给出了安装包地址。

3.

– 下载拦截功能

– 可监听 BrowserWindow 的页面下载事件,将下载状态传给渲染线程,实现类似浏览器的下载器功能。

– 页面搜索功能

– WebView 内置搜索功能,只需处理弹出搜索框的 UI 及相关操作。

– 当前标签页打开功能

– 强制所有标签在当前标签覆盖,通过相关代码处理窗口打开方式。

– 标签页切换功能

– 借助 Vue-router 实现 CSS 的显示隐藏来切换标签页。

– 地址栏功能

– 支持多种输入方式,包括直接访问链接、打开收藏网站和关键字搜索,有优先级设定。

– 桌面图标任意位置拖动

– 设定中间区域固定大小解决拖动问题,给出相关代码。

– 安装包地址

– github.com/jddk/aweb-b…

– 官网 aweb123.com 可进微软商店下载,mac 版本因文件大暂未上传。

思维导图:

文章地址:https://juejin.cn/post/7395389351641612300

文章来源:juejin.cn

作者:九段刀客

发布时间:2024/7/25 20:56

语言:中文

总字数:1414字

预计阅读时间:6分钟

评分:90分

标签:Electron,Webview,JavaScript,浏览器开发,下载拦截


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

浏览器这种东西工程量很唬人,但是有了electron+webview我们就相当于只需要干组装的活就可以了,而且产品目标就是给自己玩,成品的效果image.png😄本来想写成专业的技术博客,但是发现大家好像对那种密密麻麻,全是代码的技术博客不感兴趣,我就挑重点来写吧。image.png

下载拦截功能

image.png

下载逻辑如果不做拦截处理的话,默认就是我们平常写web那种弹窗的方式,既然是浏览器肯定不能是那样的。electron中可以监听BrowserWindow的页面下载事件,并把拿到的下载状态传给渲染线程,实现类似浏览器的下载器功能。

 global.WIN.webContents.session.on('will-download', (evt, item) => {        item.on('updated', (evt, state) => {              }) })

页面搜索功能

当时做这个功能的时候我就觉得完了,这个玩意看起来太麻烦了,还要有一个的功能这不是头皮发麻啊。

image.png查资料和文档发现这个居然是webview内置的功能,瞬间压力小了很多,我们只需要出来ctrl+f的时候把搜索框弹出来这个UI就可以了,关键字变色和下一个都是内部已经实现好了的。

function toSearch() {  let timer  return () => {    if (timer) {      clearTimeout(timer)    }    timer = setTimeout(() => {      if (keyword.value) {        webviewRef.value.findInPage(keyword.value, { findNext: true })      } else {        webviewRef.value.stopFindInPage('clearSelection')      }    }, 200)  }}  function closeSearch() {  showSearch.value = false  webviewRef.value.stopFindInPage('clearSelection')}function installFindPage(webview) {  webviewRef.value = webview  webviewRef.value.addEventListener('found-in-page', (e) => {    current.value = e.result.activeMatchOrdinal    total.value = e.result.matches  })}

当前标签页打开功能

就是因为chrome和edge这些浏览器每次使用的时候开非常多的标签,挤在一起,所以我想这个浏览器不能主动开标签,打开了一个标签后强制所有的标签都在当前标签覆盖。

app.on('web-contents-created', (event, contents) => {  contents.setWindowOpenHandler((info) => {    global.WIN?.webContents.send('webview-url-is-change')    if (info.disposition === 'new-window') {      return { action: 'allow' }    } else {      global.WIN?.webContents.send('webview-open-url', info.url)      return { action: 'deny' }    }  })})

渲染线程监听到webview-open-url后也就是tart=”_blank”的情况,强制覆盖当前不打开新窗口

ipcRenderer.on('webview-open-url', (event, url) => {  try {    let reg = /http|https/g    if (webviewRef.value && reg.test(url)) {      webviewRef.value.src = url    }  } catch (err) {    console.log(err)  }})

标签页切换功能

这里的切换是css的显示隐藏,借助了vue-routerimage.png

这里我们看dom就能清晰的看出来。

image.png

地址栏功能

地址栏支持输入url直接访问链接、支持关键字直接打开收藏的网站、还支持关键字搜索。优先级1打开收藏的网页 2访问网站 3关键字搜索

function toSearch(keyword) {    if (`${keyword}`.length === 0) {      return false    }        if (`${keyword}`.length < 20) {      let item = null      const list = [...deskList.value, ...ALL_DATA]      for (let i = 0; i < list.length; i++) {        if (          list[i].title.toUpperCase().search(keyword.toUpperCase()) !== -1 &&          list[i].type !== 'mini-component'        ) {          item = list[i]          break        }      }      if (item) {        goApp(item)        return false      }    }        let url    if (isUrl(keyword)) {      if (!/^https?:\/\//i.test(keyword)) {        url = 'http://' + keyword      } else {        url = keyword      }      goAppNewTab(url)      return false    } else {            let searchEngine = localStorage.getItem('searchEngine')      searchEngine = searchEngine || CONFIG.searchEngine      url = searchEngine + keyword      if (!router.hasRoute('search')) {        router.addRoute({          name: 'search',          path: '/search',          meta: {            title: '搜索',            color: 'var(--app-icon-bg)',            icon: 'search.svg',            size: 1          },          component: WebView        })        keepAliveInclude.value.push('search')      }      router.push({        path: '/search',        query: { url }      })      setTimeout(() => {        Bus.$emit('toSearch', url)      }, 20)    }  }

桌面图标任意位置拖动

这个问题困扰了我很久,因为它不像电脑桌面大小是固定的,浏览器可以全屏也可以小窗口,如果最开始是大窗口然后拖成小窗口,那么图标就看不到了。后来想到我干脆给个中间区域固定大小,就可以解决这个问题了。因为固定大小出来起来就方便多了。这个桌面是上下两层

//背景格子    <div v-show="typeActive === 'me'" class="bg-boxs">      <div        v-for="(item, i) in 224"  //这里有点不讲究了直接写死了        :key="item"        class="bg-box"        @dragenter="enter($event, { x: (i % 14) + 1, y: Math.floor(i / 14) + 1 })"        @dragover="over($event)"        @dragleave="leave($event)"        @drop="drop($event)"      ></div>    </div> // 桌面层 // ...
import { ref, computed } from 'vue'import useDesk from '@/store/deskList'import { storeToRefs } from 'pinia'export default function useDrag() {  const dragging = ref(null)  const currentTarget = ref()  const desk = useDesk()  const { deskList } = storeToRefs(desk)  const { setDeskList, updateDeskData } = desk  function start(e, item) {    e.target.classList.add('dragging')    e.dataTransfer.effectAllowed = 'move'    dragging.value = item    currentTarget.value = e    console.log('开始')  }  let timer2  function end(e) {    dragging.value = null    e.target.classList.remove('dragging')    setDeskList(deskList.value)    if (timer2) {      clearTimeout(timer2)    }    timer2 = setTimeout(() => {      updateDeskData()    }, 2000)  }  function over(e) {    e.preventDefault()  }  let timer  function enter(e, item) {    e.dataTransfer.effectAllowed = 'move'    if (timer) {      clearTimeout(timer)    }    timer = setTimeout(() => {      if (item?.x) {        dragging.value.x = item.x        dragging.value.y = item.y      }    }, 100)  }  function leave(e) {}  function drop(e) {    e.preventDefault()  }  return { start, end, over, enter, leave, drop }}

image.png

image.png

东西太多了就先介绍这些了

安装包地址

github.com/jddk/aweb-b…

也可以到官网后aweb123.com 如何进入微软商店下载,mac版本因为文件大于100mb没有传上去所以暂时还用不了。