vue-electron

先来讲一个 vue-electron 的报错

C:\Users\user\Desktop\dome\my-im\node_modules\_electron-localshortcut@3.2.0@electron-localshortcut\index.js:20
                } catch {
  SyntaxError: Unexpected token {
      at createScript (vm.js:80:10)
      at Object.runInThisContext (vm.js:139:10)
      at Module._compile (module.js:606:28)
      at Object.Module._extensions..js (module.js:653:10)
      at Module.load (module.js:561:32)
      at tryModuleLoad (module.js:504:12)
      at Function.Module._load (module.js:496:3)
      at Module.require (module.js:586:17)
      at require (internal/module.js:11:18)
      at eval (webpack:///external_%22electron-localshortcut%22?:1:18)
//这个错误是由于electron-localshortcut 升级致使的,降级到electron-localshortcut@3.0.0便可 
复制代码

前言注意

<!-- 一、组件内,打开外部连接 -->
<script> this.$electron.shell.openExternal(link) </script>
<!-- 引入CSS -->
<style> @import url('https://www.baidu.com/index.css') </style>
复制代码

全局安装

npm install -g electron

npm install -g electron-forge
复制代码

建立 项目

electron-forge init my-app
复制代码

运行 项目

npm start
复制代码

结合vue建立项目

vue cerate app
vue add vue-cli-plugin-electron-builder

//启动
yarn electron:serve
//打包
yarn electron:build
复制代码

主进程

import { app, BrowserWindow, Menu} from 'electron'

/** * Set `__static` path to static files in production * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html */
if (process.env.NODE_ENV !== 'development') {
  global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}

let mainWindow
const winURL = process.env.NODE_ENV === 'development'
  ? `http://localhost:9080`
  : `file://${__dirname}/index.html`

function createWindow () {
  /** * Initial window options */
  mainWindow = new BrowserWindow({
    height: 763,
    useContentSize: true,
    fullscreenable: true,  //是否容许全屏
    width: 1200,
    frame: true,   //是否显示 菜单栏
    center: true ,  //是否在屏幕中间显示
    title: '云笔记',
    titleBarStyle: 'hidden',
    webPreferences: {
      backgroundThrottling: false // 当页面被置于非激活窗口的时候是否中止动画和计时器
    }
    
  })

  mainWindow.loadURL(winURL)

  mainWindow.on('closed', () => {
    mainWindow = null
  })

  // 开启渲染进程中的调试模式
  mainWindow.webContents.openDevTools()
}
// 当electron完成初始化后触发
app.on('ready', createWindow)


//全部窗口都关闭的时候触发,在windows和linux里,全部窗口都退出的时候一般是应用退出的时候
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

//
app.on('activate', () => {
  if (mainWindow === null) {
    createWindow()
  }
})

复制代码

小试牛刀——读取本地文件

const fs = require('fs')
export default {
    methods:{
        btn:function(){
            //这里的路径 为根路径
            fs.readFile('package.json',(err,data)=>{
                console.log(data)   
                this.$refs.texts.innerHTML=data
            })
        }
    }
}
复制代码

开启初始化的调试模式

// 开启渲染进程中的调试模式
  mainWindow.webContents.openDevTools()
复制代码

拖拽

<div v-on:drop.prevent="drop" v-on:dragenter="dragenter" v-on:dragover="dragenter" v-on:dragleave="dragenter" class="box" id="box" >
</div>
   
<script> const fs = require('fs') export default { methods:{ dragenter:function(){ return false; }, drop:function(e){ console.log(e) } } } </script>
复制代码

隐藏菜单

//隐藏 顶部 菜单
  mainWindow.setMenu(null)
复制代码

去掉顶部 最大化、最下化

mainWindow = new BrowserWindow({
    height: 763,
    useContentSize: true,
    fullscreen: false,  //是否容许全屏
    width: 1200,
    frame: false,   //是否显示 菜单栏 最大化、最小化
    center: true ,  //是否在屏幕中间显示
    title: '云笔记',
    titleBarStyle: 'hidden',
    webPreferences: {
      backgroundThrottling: false // 当页面被置于非激活窗口的时候是否中止动画和计时器
    }
    
  })
复制代码

能够拖动 的CSS

.box{
	webkit-app-region: drag
}
复制代码

自定义 最小化、最大化、关闭

min:function(){
           this.$electron.ipcRenderer.send('window-min') 

        /*** * 获取mainWindow(既:win) BrowserWindow.getFocusedWindow() * 在主进程 执行操做 * var {ipcMain,BrowserWindow} = require('election') * ipcMain.on('window-min',()=>{ * 最大化 win.maximize() * 最小化 win.minimize() * 恢复 win.restore() * 关闭 win.close() * * 最大化 和 恢复原状的判断 * if(win.isMaximized()){ * win.restore() //还原 * }else{ * win.maximize() //最大化 * } * * }) * * */   
        },
        max:function(){
             this.$electron.ipcRenderer.send('window-max') 
        },
        close:function(){
             this.$electron.ipcRenderer.send('window-close') 
        }
复制代码

注册全局快捷键

const {app,globalShortcut,BrowserWindow} = require('electron')
let win=BrowserWindow.getFocusedWindow();

app.on('ready',function(){
    // 注册快捷键
    globalShortcut.register('ctrl+e',function(){
       // win.hide();
       console.log('123')
    })
    // 检测注册是否成功
    let glos=globalShortcut.isRegistered('ctrl+e')
    console.log(glos)
})

app.on('will-quit',function(){
    // 取消 全局快捷键
    globalShortcut.unregister('ctrl+e')
})
复制代码

注册剪切板

// 复制
clipboard.writeText('机器码')
复制代码

webview

//和应用运行的是不一样的进程,无渲染进程
<webview src='http://www.baidu.com'></webview>
复制代码

通知 window.Notification

//通知 采用的是H5的 通知API

// 通知
let options={
    title: '通知',
    body: '你有新短消息,请注意查收',
    // icon: path.join('../static/imgs/app2.ico')
}

let defaults=window.Notification.permission
// "denied" --- 为用户点击了禁用(拒绝打开推送功能)

// "default" ----推送功能默认关闭

// "granted" ----推送功能为开启状态(用户点击容许后的状态)


console.log(defaults)


var myNotification= new Notification(options.title,options);

myNotification.onclick=function(){
    console.log('点击了')
}

let bons =document.getElementById('bons')
//点击之后 发布通知
bons.onclick=function(){
    console.log('123')
    let myNotifications= new window.Notification(options.title,options);
    console.log(myNotifications)
    //点击通知栏的事件
        myNotifications.onclick=function(){
            console.log('点击了')
        }
}


// 监听 网络变化,最好在APP.vue 的mounted函数中
window.addEventListener('online',function(){
    console.log('有网络')
})
window.addEventListener("offline",function(){
    console.log('网络断开')
})

复制代码

实践

<body>
		<button id="btn">按钮</button>
	</body>

<script> let btn=document.getElementById('btn') let options={ title: '通知', body: '你有新短消息,请注意查收' } btn.onclick=function(){ //console.log('123') let notifications=null if (!window.Notification) { alert("浏览器不支持通知!"); } if(window.Notification.permission != 'granted'){ window.Notification.requestPermission(function(stauts){ console.log(stauts) if(stauts=='granted'){ notifications=new window.Notification(options.title,options); }else{ alert('您为容许开启消息通知,将接收不到 本站的消息推送') } }) } notifications=new window.Notification(options.title,options); //推送窗口 关闭时 notifications.onclose=function(){ } //推送窗口显示时 notifications.onshow=function(){ } } </script>
复制代码

dialog 窗口提示和打开、保存文件

<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击l</button>
        <webview id="webs" src='http://www.bbaidu.com'></webview>

        <button v-on:click="btna">错误提示</button>
        <button v-on:click="btnb">选择提示</button>
        <button v-on:click="btnc">打开文件</button>
        <button v-on:click="btnd">另存为</button>
    </div>
</template>

<script> //  const {shell,ipcRenderer,remote} = require('electron') export default { methods:{ btn:function(){ console.log('123') shell.openExternal('https://www.baidu.com/') }, btna:function(){ remote.dialog.showErrorBox('错误提示','错误了') }, btnb:function(){ remote.dialog.showMessageBox({ title: '提示信息', message: '内容', type: 'info', buttons: ['肯定','取消'] },function(index){ //index 为buttons的索引 console.log(index) }) }, btnc:function(){ //打开文件 remote.dialog.showOpenDialog({ properties:['openFile'] },function(data){ //可使用 node.js读取文件内容 console.log(data) }) /*** * properties: openFile 只容许选择文件 * openDirectory 只容许选择文件夹 * * * */ }, btnd:function(){ //保存文件 remote.dialog.showSaveDialog({ title: 'save file', //保存窗口的 title defaultPath: 'abs.gif',//默认路径 filters:[ { name: 'Images', extensions:['jpg','png','gif'] }, { name: 'Movies', extensions:['mkv','avi','mp4'] }, { name: 'Custom File Type', extensions:['as'] }, { name: 'All Files', extensions:['*'] } ] },function(data){ //保存之后,返回保存路径,可是 没有真正保存文件,须要node.js保存文件 console.log(data) }) } }, mounted:function(){ console.log('hhahha') ipcRenderer.on('webs',function(event,data){ // 在软件内部 打开外部网页 let webs=document.getElementById('webs') webs.src=data }) } } </script>
复制代码

shell模块

//在外部浏览器打开链接地址,也能够打开本地目录
<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击l</button>
    </div>
</template>

<script>

// 
const {shell} = require('electron')

export default {
    methods:{
        btn:function(){
            console.log('123')  //打开外部浏览器
            this.$electron.shell.openExternal('https://www.baidu.com/')
            
        }
    }
}
</script>
复制代码

在页面嵌套页面,相似iframe

<webview src='https://www.baidu.com/'></webview>
复制代码

主进程:ipcMain,渲染进程:ipcRenderer 通信

/** * 一、ipcMain :在主进程中使用,他处理从渲染进程发送出来的异步消息,和同步消息 * 固然也有可能处理从主进程向渲染进程发送消息 * 二、ipcRenderer: 使用它提供的一些方法从渲染进程 发送同步或异步消息到主进程, * 也能够接收主进程的回复消息 */ 
//主进程主动给渲染进程广播数据
var win= BrowserWindow.getFocusedWindow()
win.webContents.send('opens',data)
复制代码

渲染进程 向主进程 发送数据

// 渲染进程
<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击</button>
    </div>
</template>

<script> const fs = require('fs') // 让渲染进程 给主进程发消息 const {ipcRenderer} = require('electron') export default { methods:{ btn:function(){ // console.log('123') //渲染进程给主进程广播数据 ipcRenderer.send('sendM','this is home') } } } </script>

<scripr>
//  主进程
import { ipcMain} from 'electron'

ipcMain.on('sendM',function(event,data){
    console.log(data)
})
/*  在下面生命周期中执行
* 当electron完成初始化后触发
*   app.on('ready', createWindow)
*/
</scripr>
复制代码

渲染进程 向主进程 发送数据,并返回处理结果给渲染进程

<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击</button>
    </div>
</template>

<script> const fs = require('fs') // 让渲染进程 给主进程发消息,主进程 返回处理结果给渲染 const {ipcRenderer} = require('electron') export default { methods:{ btn:function(){ // console.log('123') //渲染进程给主进程广播数据 ipcRenderer.send('sendM','this is home') } }, mounted:function(){ ipcRenderer.on('replay',(event,data)=>{ console.log(data) }) } } </script>

<!-- 主进程 -->
<script> import { ipcMain} from 'electron' //接收 渲染进程数据,而且返回处理数据 ipcMain.on('sendM',function(event,data){ //console.log(data) // 返回处理结果 event.sender.send('replay','ok hello') }) </script>
复制代码

同步广播

<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击</button>
    </div>
</template>

<script> const fs = require('fs') // 让渲染进程 给主进程发消息,主进程 返回处理结果给渲染 const {ipcRenderer} = require('electron') export default { methods:{ btn:function(){ // console.log('123') //渲染进程给主进程广播数据(同步模式) let src=ipcRenderer.sendSync('sendM','this is home') console.log(src) } }, mounted:function(){ } } </script>

<!-- 主进程 -->
<script> import { ipcMain} from 'electron' //接收 渲染进程数据,而且返回处理数据(同步) ipcMain.on('sendM',function(event,data){ //console.log(data) // 返回处理结果 event.returnValue='this is sync main' }) </script>
复制代码

实例

// 在渲染进程,通信到主进程 打开新窗口
import { ipcMain, BrowserWindow} from 'electron'
var win;

//接收 渲染进程数据,而且返回处理数据
ipcMain.on('sendM',function(event,data){
    //console.log(data)
    // 返回处理结果
   // event.returnValue='this is sync main'

    win= new BrowserWindow({
        width:300,
        height: 400
    })
    win.loadURL('https://www.baidu.com/')
    win.webContents.openDevTools()
    win.on('closed',()=>{
        win=null
    })
})
复制代码

渲染进程 与 渲染进程 单项通信

/* * 一、首先 第一个渲染进程 发送数据 到主进程, * 二、主进程 保存 第一个渲染进程,并打开新的渲染进程 * 三、 传递数据 和 第一个 渲染进程 到新的渲染进程 * 四、 新的 渲染进程 拿到 第一个 渲染进程 后 发送数据 给第一个渲染进程 * */


// 首先 接收到 前一个页面传递的数据,并打开新的 页面,再把数据发送到 新页面

import { ipcMain, BrowserWindow} from 'electron'
var win;

//接收 渲染进程数据,而且返回处理数据
ipcMain.on('sendM',function(event,data){
    //console.log(data)
    // 返回处理结果
   // event.returnValue='this is sync main'

    win= new BrowserWindow({
        width:300,
        height: 400
    })
    win.loadURL('https://www.baidu.com/')
    win.webContents.openDevTools()
    
    //在页面渲染完成之后传递数据
    win.webContents.on('did-finish-load',function(){
        win.webContents.send('Load','ha ha hehe')
    })

    win.on('closed',()=>{
        win=null
    })
})
复制代码
//新页面接收数据
 ipcRenderer.on('Load',function(event,data){
                console.log(data)
    })
复制代码

渲染进程 与渲染 进程 相互通信

ipcMain.on('sendM',function(event,data){
    // 保存 发送数据的窗口
    var winId = BrowserWindow.getFocusedWindow().id

    win= new BrowserWindow({
        width:300,
        height: 400
    })
    win.loadURL('https://www.baidu.com/')
    win.webContents.openDevTools()

    //在页面渲染完成之后传递数据, 并把 winId 传递过去
    win.webContents.on('did-finish-load',function(){
        win.webContents.send('Load','ha ha hehe',winId)
    })

    win.on('closed',()=>{
        win=null
    })
})
复制代码
const fs = require('fs')

// 让渲染进程 给主进程发消息,主进程 返回处理结果给渲染
const {ipcRenderer} = require('electron')
const BrowserWindow =require('electron').remote.BrowserWindow
export default {
  
    mounted:function(evemt,data,winId){
        // 获取上一个窗口的winId
         let firstWinid=  BrowserWindow.fromId(winId)
        // 向上一个窗口发送消息
        firstWinid.webContents.send('toIndex', 'this is news');
    }
}
复制代码

Tray 模块

let {app,Menu,Tray,shell,ipcMain,BrowserWindow} = require('electron');
// 托盘图标设置
// console.log(__dirname)
var iconTray=new Tray(path.join(__dirname,'../static/imgs/app2.png'));

// 绑定托盘的右键菜单
var tpl=[
    {
        label: '设置',
        click:function(){
            console.log('123')
        }
    },
    {
        label: '退出',
        click:function(){
            console.log('123')
        }
    }
]

let rightIcon=Menu.buildFromTemplate(tpl)

iconTray.setContextMenu(rightIcon)

// 托盘图标 提示文字
iconTray.setToolTip('云应用')

// 点击关闭按钮,让应该保存在托盘里,双击托盘,打开应用
let win=BrowserWindow.getFocusedWindow();
// console.log(win)

win.on('close',(e)=>{
    /**** * 如 是点击 托盘的 退出,须要直接退出, * win.isFocused() //判断窗口 当前是否激活显示 * */
    if(!win.isFocused()){
       win=null
    }else{
         // 阻止窗口关闭
         e.preventDefault();
         // 隐藏窗口
         win.hide();
    }
    
})

// 双击 托盘图标 打开窗口
iconTray.on('double-click',function(){
    win.show()
})


// 闪烁图标
/*** * 定时器 设置图标 * iconTray.setImage(path.join(__dirname,'../static/imgs/app1.png')) * */
复制代码

在渲染进程 打开 另一个 渲染进程,remote模块

/** *渲染进程,没法直接调用主进程中的模块, *可是咱们能够经过 electron中的remove模块,间接的调用主进程中的模块 */
//监听渲染进程的 某个点击事件
let BrowserWindow = require('electron').remote.BrowserWindow

let win=null
	win=new BrowserWindow({
    		height: 763,
    		useContentSize: true,
    		fullscreen: true,  //是否容许全屏
    		width: 1200,
    		frame: true,   //是否显示 菜单栏
    		center: true ,  //是否在屏幕中间显示
    		title: '云笔记',
    		titleBarStyle: 'hidden',
		    autoHideMenuBar : true,  //隐藏菜单
    		webPreferences: {
      			backgroundThrottling: false // 当页面被置于非激活窗口的时候是否中止动画和计时器
    		}    
  })
//加载页面
let winURL=path.join("file:",__dirname,'news.html')
mainWindow.loadURL(winURL)

//关闭页面
mainWindow.on('closed'.()=>{
	win=null
})
复制代码

自定义 顶部菜单 menu 模块,在主进程

menus.js
import { Menu} from 'electron'

//定义菜单
let template=[
    {
      label: '文件',  //主菜单
      submenu:[       //子菜单
        {
          label: '新建窗口',
          click:function(){  //绑定事件
              console.log('新建窗口')
          },
          accelerator: 'ctrl+n'  //绑定快捷键,PS : 必须 单引号
        },
        {
          type: 'separator'   //分割线
        },
        {
          label: '打开文件',
          accelerator: 'ctrl+x',
          click:()=>{
            console.log('打开文件')
          }
        }
      ]
    },
    {
      label: '编辑',
      submenu:[
        {
          role: 'cut',  //绑定角色(内置)
          label: '剪切'
        },
        {
          rele: 'copy', //绑定角色
          label: '复制'
        }
      ]
    }
  ]


  //注册菜单
  let m= Menu.buildFromTemplate(template)
  //挂载菜单
  Menu.setApplicationMenu(m)


//须要在主进程中执行
// 当electron完成初始化后触发
app.on('ready', {
	//建立菜单
  	require('./menu')
})
复制代码

自定义 顶部菜单 menu模块,在渲染进程中

const {Menu} = require('electron').remote;

//定义菜单
let template=[
    {
      label: '文件',  //主菜单
      submenu:[       //子菜单
        {
          label: '新建窗口',
          click:function(){  //绑定事件
              console.log('新建窗口')
          },
          accelerator: 'ctrl+n'  //绑定快捷键,PS : 必须 单引号
        },
        {
          type: 'separator'   //分割线
        },
        {
          label: '打开文件',
          accelerator: 'ctrl+x',
          click:()=>{
            console.log('打开文件')
          }
        }
      ]
    },
    {
      label: '编辑',
      submenu:[
        {
          role: 'cut',  //绑定角色(内置)
          label: '剪切'
        },
        {
          rele: 'copy', //绑定角色
          label: '复制'
        }
      ]
    }
  ]


  //注册菜单
  let m= Menu.buildFromTemplate(template)
  //挂载菜单
  Menu.setApplicationMenu(m)


//在须要 引入菜单的 渲染进程中 执行 便可
复制代码

渲染进程的 右键菜单

const remote= require('electron').remote;
const Menu = remote.Menu
//定义菜单
let template=[
    {
      label: '文件',  //主菜单
      submenu:[       //子菜单
        {
          label: '新建窗口',
          click:function(){  //绑定事件
              console.log('新建窗口')
          },
          accelerator: 'ctrl+n'  //绑定快捷键,PS : 必须 单引号
        },
        {
          type: 'separator'   //分割线
        },
        {
          label: '打开文件',
          accelerator: 'ctrl+x',
          click:()=>{
            console.log('打开文件')
          }
        }
      ]
    },
    {
      label: '编辑',
      submenu:[
        {
          role: 'cut',  //绑定角色(内置)
          label: '剪切'
        },
        {
          rele: 'copy', //绑定角色
          label: '复制'
        }
      ]
    }
  ]


  //注册菜单
  let m= Menu.buildFromTemplate(template)
  //挂载菜单
  Menu.setApplicationMenu(m)

  
// 右键菜单
window.addEventListener('contextmenu',function(e){
    e.preventDefault()
    m.popup({
        window:remote.getCurrentWindow()
    })
},false)

//remote.getCurrentWindow()//表示获取当前窗口

复制代码

主进程 右键菜单

//渲染进程 给主进程广播事件
window.addEventListener('contextmenu',(e)=>{
    <!--this.$electron.ipcRenderder.emit('contextmenu')-->
    //给主进程广播事件
    this.$electron.ipcRenderer.send('contextmenu');
},false)

//主进程 
//新建 menu.js
const { Menu, ipcMain, BrowserWindow } = require('electron');
//右键菜单
const contextMenuTemplate=[
    {
        label: '复制',
        role: 'copy'
    },
    {
        label: '粘贴',
        role: 'paste'
    },
    {
        type: "separstor" //分割线
    },
    {
        label: '其余功能',
        click:()=>{
            console.log('自定义功能')
        }
    }
]
//建立菜单
const contextMenu = Menu.buildFromTemplate(contextMenuTemplate)

//监听渲染进程contextmenu事件,显示菜单
ipcMain.on('contextmenu',function(){
    //获取当前窗口
    contextMenu.popup(BrowserWindow.getFocusedWindow())
})

//在主进程引入menu.js (ready函数内)
require('./menu.js')
复制代码

点击菜单栏 在 软件内部 或者 外部默认浏览器 打开网页

import { Menu,shell,BrowserWindow} from 'electron'
//定义菜单
let template=[
    {
      label: '加载网页',
      submenu: [
        {
          label: '优酷',
          click: function(){
            // 在 默认浏览器 打开
            shell.openExternal('http://www.baidu.com')
          }
        },
        {
          type: 'separator'
        },
        {
          label: '百度',
          click: function(){

            let win= BrowserWindow.getFocusedWindow();
			//通知 渲染进程 在软件内 打开特定网页
                win.webContents.send('webs','http://www.youku.com')
                
          }
        }
      ]
    },
    {
      label: '帮助',
      submenu: [
        {
          label:'关于咱们',
          click:function(){

          }
         
        }
      ]
    }
  ]
复制代码
<template>
<!-- 云笔记 主页 -->
    <div class="notebook">
        <button v-on:click="btn">点击l</button>
        <webview id="webs" src='http://www.baidu.com'></webview>
    </div>
</template>

<script> const {shell,ipcRenderer} = require('electron') export default { methods:{ btn:function(){ console.log('123') //在外部 默认浏览器 打开特定网页 shell.openExternal('https://www.baidu.com/') } }, mounted:function(){ ipcRenderer.on('webs',function(event,data){ // 在软件内部 打开外部网页 let webs=document.getElementById('webs') webs.src=data }) } } </script>
复制代码
本站公众号
   欢迎关注本站公众号,获取更多信息