稀土掘金技术社区 2024年12月05日
用electron写个浏览器给自己玩
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文分享了作者使用Electron和webview开发一个简单浏览器的经验,重点介绍了下载拦截、页面搜索、标签页管理、地址栏功能以及桌面图标拖动等功能的实现方法。作者以简洁易懂的方式描述了这些功能的原理和代码实现,并分享了项目的GitHub地址和官网,方便读者学习和参考。文章旨在帮助开发者快速了解Electron浏览器开发的基本流程,并提供一些实际应用的案例,降低学习门槛,提升开发效率。

🤔**下载拦截功能:** 通过监听BrowserWindow的页面下载事件,并把下载状态传给渲染线程,实现类似浏览器下载器的功能,避免使用弹窗方式。

🔎**页面搜索功能:** 利用webview内置的findInPage功能,简化了搜索框的开发,只需在ctrl+f时弹出来即可,关键字变色和下一个等功能都是内部实现的。

🔄**当前标签页打开功能:** 为了避免标签页过多,强制所有打开的标签页都覆盖在当前标签页上,通过监听web-contents-created事件和setWindowOpenHandler方法实现。

🗂️**标签页切换功能:** 使用CSS的显示隐藏和vue-router实现标签页的切换,DOM结构清晰易懂。

📍**地址栏功能:** 支持输入URL直接访问链接、支持关键字打开收藏网站、支持关键字搜索,并设定了优先级,优先打开收藏网页,其次访问网站,最后进行关键字搜索。

原创 九段刀客 2024-12-03 08:30 重庆

点击关注公众号,“技术干货”及时达!

点击关注公众号,“技术干货” 及时达!

浏览器这种东西工程量很唬人,但是有了electron+webview我们就相当于只需要干组装的活就可以了,而且产品目标就是给自己玩,成品的效果

?本来想写成专业的技术博客,但是发现大家好像对那种密密麻麻,全是代码的技术博客不感兴趣,我就挑重点来写吧。

下载拦截功能

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

//这个global.WIN =   global.WIN = new BrowserWindow({ ...})
 global.WIN.webContents.session.on('will-download', (evt, item) => {
 //其他逻辑
       item.on('updated', (evt, state) => {
       //实时的下载进度传递给渲染线程
       })
 })

页面搜索功能

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

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

function toSearch({
  let timer
  return () => {
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      if (keyword.value) {
        webviewRef.value.findInPage(keyword.value, { findNexttrue })
      } 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-router

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

地址栏功能

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

function toSearch(keyword{
    if (`${keyword}`.length === 0) {
      return false
    }
    // app搜索
    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',
            size1
          },
          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 }
}

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

安装包地址

https://github.com/jddk/aweb-browser.git

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

点击关注公众号,“技术干货” 及时达!

阅读原文

跳转微信打开

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Electron Webview 浏览器开发 下载拦截 页面搜索
相关文章