用electron写个浏览器给自己玩
浏览器这种东西工程量很唬人,但是有了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, { 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-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',
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 }
}


东西太多了就先介绍这些了
安装包地址
也可以到官网后aweb123.com 如何进入微软商店下载,mac版本因为文件大于100mb没有传上去所以暂时还用不了。
来源:juejin.cn/post/7395389351641612300