前言


  Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。 Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。

Electron于2013年作为构建Github上可编程的文本编辑器Atom的框架而被开发出来。这两个项目在2014春季开源。

目前它已成为开源开发者、初创企业和老牌公司常用的开发工具。 看看谁在使用Electron 。

继续往下阅读可以了解Electron的贡献者们和已经发布的版本,或者直接阅读快速开始指引来开始用Electron来构建应用。

(摘抄至electronjs.org)

一、初始化项目


运行,vue init simulatedgreg/electron-vue 项目名称

vue init simulatedgreg/electron-vue admin

  

这里的项目名称是“admin”

如果没有安装vue脚手架,请查看《spring boot + vue + element-ui全栈开发入门——windows开发环境》

一路回车

然后运行npm install来安装依赖,运行方式和之前一样。

如果遇到run dev或者run build的时候出错,可能是因为国内的网络下载“electron-v1.8.3-win32-x64.zip”出错,这时,你需要设置npm的代理:

npm config set proxy http://服务器IP或域名:端口号
npm config set https-proxy http://服务器IP或域名:端口号

  

如果需要用户名密码:

npm config set proxy http://用户名:密码@服务器IP或域名:端口号
npm config set https-proxy http://用户名:密码@服务器IP或域名:端口号

  

设置回原库

npm config set registry http://registry.npmjs.org

也可以使用yarn。

npm install -g yarn

  

安装依赖、开发模式运行和编程的命令分别是:

yarn install
yarn run dev
yarn run build

  

项目构建完毕后,结构如下图所示:

和之前项目区别是,main是用于桌面程序的代码,render是用于渲染的代码。我们只需要在render文件夹里写代码就可以。

开发模式运行:

npm run dev

  

二、代码编写


参照《spring boot + vue + element-ui全栈开发入门——集成element-ui》安装所需的依赖

cnpm install --save element-ui
cnpm install --save-dev node-sass
cnpm install --save-dev sass-loadercnpm install --save font-awesome

  

参照《spring boot + vue + element-ui全栈开发入门——前端列表页面开发》的代码如下:

入口文件:

import Vue from 'vue'
import axios from 'axios'import App from './App'
import router from './router'
import store from './store'if (!process.env.IS_WEB) Vue.use(require('vue-electron'))Vue.http = Vue.prototype.$http = axios
axios.defaults.baseURL = 'http://localhost:18080'Vue.config.productionTip = falseimport 'font-awesome/css/font-awesome.min.css'import ElementUI from 'element-ui'
//原始风格
// import 'element-ui/lib/theme-chalk/index.css'
//自定义风格
import './assets/theme/element-#09345f/index.css'
Vue.use(ElementUI)/* eslint-disable no-new */
new Vue({components: {App},router,store,template: '<App/>'
}).$mount('#app')

main.js

其中 axios.defaults.baseURL = 'http://localhost:18080' 是设置后端项目URL,而这可以根据具体情况写到配置文件中,开发环境调用开发环境的配置,生产环境调用生产环境配置。

路由文件:

import Vue from 'vue'
import Router from 'vue-router'Vue.use(Router)import Main from '@/pages/Main'
import Dashboard from '@/pages/Dashboard'import Member from '@/pages/Member'// let routes = [
//   {//     path: '/',
//     name: 'landing-page',
//     component: require('@/components/LandingPage').default
//   },
//   {//     path: '*',
//     redirect: '/'
//   }
// ]

let routes = [{path: '/',component: Main,hidden: true,children: [{path: '/',component: Dashboard,name: '首页'}]
}]routes.push({path: '/member',name: '会员管理',component: Main,iconCls: 'fa fa-user-circle-o',children: [{path: '/member/data',component: Member,name: '会员信息管理'}]
})const router = new Router({routes: routes
})export default router

router/index.js

主页面:

<template>
<section><el-container class="container"><!--左边--><el-aside :width="collapsed? '75px' : '280px' "><el-container><el-header><span class="menu-button" v-if="collapsed" @click.prevent="collapsed=!collapsed"><i class="fa fa-align-justify"></i></span><span v-else class="system-name">{{systemName}}</span></el-header><el-main><el-menu :default-active="$route.path" :collapse="collapsed" :style="{'height':menuHeight}"><template v-for="(item,index) in menus"><el-submenu :index="index+''" v-if="!item.leaf"><template slot="title"><i :class="item.iconCls"></i><span v-if="!collapsed">{{item.name}}</span></template><el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" @click="$router.push(child.path)">{{child.name}}</el-menu-item></el-submenu><el-menu-item v-if="item.leaf&&item.children.length>0" :index="item.children[0].path"><i :class="item.iconCls"></i>{{item.children[0].name}}</el-menu-item></template></el-menu></el-main></el-container></el-aside><!--内容--><el-container><!--页眉--><el-header class="header"><el-row><el-col :span="18" class="header-title"><span v-if="collapsed" class="system-name">{{systemName}}</span><span v-else class="menu-button" @click.prevent="collapsed=!collapsed"><i class="fa fa-align-justify"></i></span></el-col><el-col :span="6"><span class="el-dropdown-link userinfo-inner">你好:{{userName}}</span></el-col></el-row></el-header><!--中间--><el-main class="main"><transition name="fade" mode="out-in"><router-view></router-view></transition></el-main></el-container></el-container>
</section>
</template><script>
let data = () => {return {collapsed: false,systemName: '后台管理',userName: '系统管理员',menuHeight: '100%',menus: []}
}let initMenu = function() {for (let i in this.$router.options.routes) {let root = this.$router.options.routes[i]if (root.hidden)continuelet children = []for (let j in root.children) {let item = root.children[j]if (item.hidden)continuechildren.push(item)}if (children.length < 1)continuethis.menus.push(root)root.children = children}
}let initHeight = function() {this.menuHeight = (document.documentElement.clientHeight - 60) + 'px'
}export default {data: data,methods: {initMenu,//初始化高度
    initHeight},mounted: function() {this.initHeight()window.addEventListener('resize', this.initHeight)this.initMenu()}
}
</script><style scoped="scoped"lang="scss">
$width: 100%;
$height: 100%;
$background-color: #09345f;
$header-color: #fff;
$header-height: 60px;.container {position: absolute;top: 0;bottom: 0;width: 100%;.el-aside {.el-header {line-height: $header-height;background-color: $background-color;color: $header-color;text-align: center;}.el-container {height: $height;.el-main {padding: 0;}}}.main {width: $width;height: $height;}.menu-button {width: 14px;cursor: pointer;}.userinfo-inner {cursor: pointer;}.el-menu {height: $height;}.header {background-color: $background-color;color: $header-color;text-align: center;line-height: $header-height;padding: 0;.header-title {text-align: left;span {padding: 0 20px;}}}.system-name {font-size: large;font-weight: bold;}
}
</style>

Main.vue

会员数据列表页面:

<template>
<section><!--工具条--><el-col :span="24" class="toolbar" style="padding-bottom: 0px;"><el-form :inline="true" :model="filters"><el-form-item><el-input v-model="filters.query" placeholder="姓名/手机号等条件" /></el-form-item><el-form-item><el-button type="primary" v-on:click="handleQuery" icon="el-icon-search">查询</el-button></el-form-item><el-form-item><el-button type="primary" v-on:click="handleAdd" icon="el-icon-plus">添加</el-button></el-form-item></el-form></el-col><el-table :data="rows" style="width: 100%;overflow: auto;" :height="clientHeight" stripe border highlight-current-row v-loading="pageLoading"><el-table-column label="注册日期" width="180"><template slot-scope="scope"><i class="el-icon-time"></i><span style="margin-left: 10px">{{ scope.row.date }}</span></template></el-table-column><el-table-column label="姓名" width="180" :show-overflow-tooltip="true"><template slot-scope="scope"><el-popover trigger="hover" placement="top"><p>姓名: {{ scope.row.name }}</p><p>住址: {{ scope.row.address }}</p><div slot="reference" class="name-wrapper"><el-tag size="medium">{{ scope.row.name }}</el-tag></div></el-popover></template></el-table-column><el-table-column prop="sex" label="性别" width="100" align="center" :show-overflow-tooltip="true"><template slot-scope="scope">{{scope.row.sex===1?'男':'女'}}</template></el-table-column><el-table-column label="操作"><template slot-scope="scope"><el-buttonsize="mini"type="primary"@click="handleEdit(scope.$index, scope.row)"><i class="el-icon-edit"></i>编辑</el-button><el-buttonsize="mini"type="danger"@click="handleDelete(scope.$index, scope.row)"><i class="el-icon-delete"></i>删除</el-button></template></el-table-column></el-table><!--底部--><el-col :span="24" class="toolbar"><el-pagination layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="20" :total="total" style="float:right;"></el-pagination></el-col><!--对话框--><el-dialog :title="form && form.id ? '编辑' : '新增' " :visible.sync="formVisible" :close-on-click-modal="false"><el-form :model="form" label-width="100px" :rules="rules" ref="form"><el-form-item label="姓名" prop="name"><el-input v-model="form.name" /></el-form-item><el-form-item label="性别" prop="sex"><el-radio-group v-model="form.sex"><el-radio :label="1">男</el-radio><el-radio :label="2">女</el-radio></el-radio-group></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click.native="formVisible = false">取消</el-button><el-button type="primary" @click.native="handleSubmit" :loading="formLoading">提交</el-button></div></el-dialog></section>
</template><script>
const rules = {name: [{required: true,message: '请输入姓名',trigger: 'blur'}],sex: [{required: true,message: '请选择性别',trigger: 'change'}]
}let data = () => {return {//页码
    page: 1,//每页数量
    size: 20,//总数
    total: 0,//查询条件
    filters: {},//页面数据
    rows: [],//页面载入状态
    pageLoading: false,//列表高度
    clientHeight: '100%',//表单数据
    form: {},//验证规则
    rules: rules,//对话框隐藏状态
    formVisible: false,//表单提交状态
    formLoading: false}
}let handleAdd = function() {this.form = {}this.form.sex = 1this.formVisible = true
}let handleEdit = function(index, row) {this.form = Object.assign({}, row)this.formVisible = true
}let handleDelete = function(index, row) {if (this.pageLoading)returnthis.$confirm('此操作将永久删除该数据, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {this.pageLoading = truethis.$http.get('/member/remove/' + row.id).then(res => {this.pageLoading = falseif (!res.data.success) {this.$message({type: 'error',message: res.data.message})return}this.$message({type: 'success',message: '删除成功!'})this.page = 1this.getRows()}).catch(e => this.pageLoading = false)}).catch(e => {})
}let getRows = function() {if (this.pageLoading)returnthis.pageLoading = truelet params = {page: this.page,size: this.size,query: this.filters.query}//调用post请求this.$http.post('/member/loadPage', params).then(res => {this.pageLoading = falseif (!res.data || !res.data.rows)return//总数赋值this.total = res.data.totalthis.page++;//页面元素赋值this.rows = res.data.rows}).catch(e => this.pageLoading = false)
}let handleSubmit = function() {if (this.formLoading)returnthis.$refs.form.validate(valid => {if (!valid)returnthis.formLoading = true//调用http协议this.$http.post('/member/save', this.form).then(res => {this.formLoading = falseif (!res.data.success) {this.$message({showClose: true,message: res.data.message,type: 'error'});return}this.$message({type: 'success',message: '保存成功!'})//重新载入数据this.page = 1this.getRows()this.formVisible = false}).catch(e => this.formLoading = false)})
}let handleQuery = function() {this.page = 1this.getRows()
}let handleCurrentChange = function(val) {this.page = valthis.getRows()
}let initHeight = function() {this.clientHeight = (document.documentElement.clientHeight - 258) + 'px'
}export default {data: data,methods: {//查询
    handleQuery,//添加
    handleAdd,//修改
    handleEdit,//删除
    handleDelete,//页数改变
    handleCurrentChange,//获取分页
    getRows,//初始化高度
    initHeight,//提交数据
    handleSubmit},mounted: function() {window.addEventListener('resize', this.initHeight)this.initHeight()this.getRows()}
}
</script><style scoped>
</style>

Member.vue

结构如下图所示:

还有,在运行之前,我们需求修改src/main/index.js的配置:

function createWindow() {/*** Initial window options*/mainWindow = new BrowserWindow({height: 563,useContentSize: true,width: 1000,webPreferences: {webSecurity: false}})

其目的是为了实现js跨域。

运行之前项目的后端项目《spring boot + vue + element-ui全栈开发入门——spring boot后端开发》:

mvn package
java -jar target/demo.jar

  

运行项目,效果如下:

二、生成安装包


npm run build

  

如提示缺少vue组建,是因为registry的问题,因为国内taobao镜像没有Electron的依赖环境。所以需要设置回默认的 registry,并使用设置proxy的方式下载依赖环境。

如果提示“icon source "build/icons/icon.ico" not found”

就把“icons”加到build目录下,下载icons请点击链接,根据具体情况修改icons。

生成好后,出现“admin Setup 0.0.0.exe”的文件,即安装程序。

我运用这个安装程序后,打开刚刚开发好的程序,效果如图所示:

发现,虽然只用到了一些前端技术,但已经能够开发出桌面应用了。小时候,老师说:“学好数理化,走遍天下都不怕”。而现在是:“学会了node,任何平台的前端都不怕”。

返回目录

代码下载地址 : https://github.com/carter659/electron-vue-example.git

如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。

有可能就是你的一点打赏会让我的博客写的更好:)

作者:刘冬.NET 博客地址:http://www.cnblogs.com/GoodHelper/ 欢迎转载,但须保留版权

spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发相关推荐

  1. Spring Boot Vue Element入门实战(完结)

    最近给朋友做一个大学运动会管理系统,用作教学案例,正好自己也在自学VUE,决定用spring boot vue做一个简单的系统.vue这个前端框架很火,他和传统的Jquery 编程思路完全不一样,Jq ...

  2. 在线相册 ,图片上传, 基于 Spring boot vuejs element ui mysql 的项目

    最近想学关于vuejs 和 element ui ,趁着工作之余开发了一个在线相册的项目,功能有 注册,登录,预览,各种中心,图片上传,我的资源,图片编辑等,,在此做一个分享吧. Git 地址 :ht ...

  3. Spring Boot Vue Element入门实战(四)主页面开发

    本博客属作者原创,未经允许禁止转载,请尊重原创!如有问题请联系QQ509961766 (一)页面布局 页面布局分为3个部分: 顶部导航:系统logo,登录信息,退出按钮等 左侧菜单:显示系统菜单 右侧 ...

  4. Spring Boot Vue Element入门实战(五)封装axios

    本博客属作者原创,未经允许禁止转载,请尊重原创!如有问题请联系QQ509961766 (一)关于Axios Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get.pos ...

  5. Spring Boot Vue Element入门实战(十)Vue生命周期

    本博客属作者原创,未经允许禁止转载,请尊重原创!如有问题请联系QQ509961766 前面9篇文章基本上完成了vue 静态页面的入门,包括列表展示,路由动态加载菜单,echarts图表的一些使用,后面 ...

  6. spring boot + vue + element-ui全栈开发入门

    今天想弄弄element-ui  然后就在网上找了个例子 感觉还是可以用的  第一步是完成了  果断 拿过来  放到我这里这  下面直接是连接  点进去 就可以用啊 本想着不用vue   直接导入连接 ...

  7. 读书笔记《Spring Boot+Vue全栈开发实战》(下)

    本书将带你全面了解Spring Boot基础与实践,带领读者一步步进入 Spring Boot 的世界. 前言 第九章 Spring Boot缓存 第十章 Spring Boot安全管理 第十一章 S ...

  8. 《Spring Boot+Vue全栈开发实战》读书笔记

    写在前面 嗯,回家处理一些事,所以离职了,之前的公司用开源技术封装了一套自己的低代码平台,所以之前学的spring Boot之类的东西都忘了很多,蹭回家的闲暇时间复习下. 笔记整体以 Spring B ...

  9. Spring Boot+Vue全栈开发实战——花了一个礼拜读懂了这本书

    很幸运能够阅读王松老师的<Spring Boot+Vue全栈开发实战>这本书!之前也看过Spring Boot与Vue的相关知识,自己也会使用了Spring Boot+Vue进行开发项目. ...

最新文章

  1. Xamarin中VS无法连接Mac系统的解决办法
  2. B - Labyrinth Gym - 102798B
  3. quartz.net隔一天执行一次_你知多少年的轮回,中秋和国庆在同一天吗?喜相逢必备“蟹”逅礼...
  4. 容器编排技术 -- Kubernetes kubectl create service externalname 命令详解
  5. elk,centos7,filebeat,elasticsearch-head集成搭建
  6. 2021-09-01175. 组合两个表 SQL
  7. Crontab 实例
  8. (时间表达式)定时任务Quartz 之 cron表达式及在线生成器
  9. 技术分析是我的唯一信仰
  10. 软件 可靠性测试项目有哪些,可靠性测试
  11. 软件项目量化管理(CMMI高成熟度)实践经验谈——之概述篇
  12. 怎么挑小红书koc?什么是小红书koc
  13. PHP的页面布局怎样设计
  14. java程序设计实验报告代写_代写file I/O作业、代写java Scanner I/O程序、代写java编程作业、代做java实验报告...
  15. 个人自我介绍PPT模板推荐
  16. 锚定品质,金科走出清晰的“产品主义”路径
  17. MVC设计模式及Sprint MVC设计模式
  18. tiktok设备注册+xg xk xl xa签名
  19. 【Redis】Redis入门篇(1)
  20. 【微信群助手机器人】好不好用?可以实现哪些功能?

热门文章

  1. java css是什么_Java 之 CSS
  2. 创建了联合索引还用在单个字段上创建索引吗_数据库 索引并不是万能的
  3. android 融云会话列表,为什么切换账号之后会话列表不刷新,还显示上一个帐号的内容?...
  4. redhat linux创建磁盘分区,redhat6.4 挂载硬盘,创建新分区,删除分区
  5. 大朗机器人餐厅在哪里_东莞餐厅惊现机器人服务员 平均每个10万元
  6. RecyclerView的优化:RecycledViewPool
  7. Spring常见注解
  8. Android快速阅读依赖的代码,Java Android快速阅读完整文件
  9. 的电路接法_放大电路的三种基本接法分享
  10. 客户端手册_山东省税务局社保费管理客户端企业缴费操作手册