我是靠谱客的博主 大方菠萝,这篇文章主要介绍spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发,现在分享给大家,希望可以做个参考。

 前言


 

  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 项目名称

复制代码
1
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的代理:

复制代码
1
2
npm config set proxy http://服务器IP或域名:端口号 npm config set https-proxy http://服务器IP或域名:端口号

  

如果需要用户名密码:

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

  

设置回原库

复制代码
1
npm config set registry http://registry.npmjs.org

 

也可以使用yarn。

复制代码
1
npm install -g yarn

  

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

复制代码
1
2
3
yarn install yarn run dev yarn run build

  

 

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

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

 

开发模式运行:

复制代码
1
npm run dev

  

 

 

二、代码编写


 

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

 

复制代码
1
2
3
cnpm install --save element-ui cnpm install --save-dev node-sass cnpm install --save-dev sass-loader
cnpm install --save font-awesome

  

 

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

 

入口文件:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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 = false import '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,而这可以根据具体情况写到配置文件中,开发环境调用开发环境的配置,生产环境调用生产环境配置。

 

路由文件:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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

 

 主页面:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
<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) continue let children = [] for (let j in root.children) { let item = root.children[j] if (item.hidden) continue children.push(item) } if (children.length < 1) continue this.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

 

会员数据列表页面:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
<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-button size="mini" type="primary" @click="handleEdit(scope.$index, scope.row)"><i class="el-icon-edit"></i>编辑</el-button> <el-button size="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 = 1 this.formVisible = true } let handleEdit = function(index, row) { this.form = Object.assign({}, row) this.formVisible = true } let handleDelete = function(index, row) { if (this.pageLoading) return this.$confirm('此操作将永久删除该数据, 是否继续?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { this.pageLoading = true this.$http.get('/member/remove/' + row.id).then(res => { this.pageLoading = false if (!res.data.success) { this.$message({ type: 'error', message: res.data.message }) return } this.$message({ type: 'success', message: '删除成功!' }) this.page = 1 this.getRows() }).catch(e => this.pageLoading = false) }).catch(e => {}) } let getRows = function() { if (this.pageLoading) return this.pageLoading = true let params = { page: this.page, size: this.size, query: this.filters.query } //调用post请求 this.$http.post('/member/loadPage', params).then(res => { this.pageLoading = false if (!res.data || !res.data.rows) return //总数赋值 this.total = res.data.total this.page++; //页面元素赋值 this.rows = res.data.rows }).catch(e => this.pageLoading = false) } let handleSubmit = function() { if (this.formLoading) return this.$refs.form.validate(valid => { if (!valid) return this.formLoading = true //调用http协议 this.$http.post('/member/save', this.form).then(res => { this.formLoading = false if (!res.data.success) { this.$message({ showClose: true, message: res.data.message, type: 'error' }); return } this.$message({ type: 'success', message: '保存成功!' }) //重新载入数据 this.page = 1 this.getRows() this.formVisible = false }).catch(e => this.formLoading = false) }) } let handleQuery = function() { this.page = 1 this.getRows() } let handleCurrentChange = function(val) { this.page = val this.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的配置:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
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后端开发》:

复制代码
1
2
mvn package java -jar target/demo.jar

  

 

运行项目,效果如下:

 

 

 

二、生成安装包


 

复制代码
1
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,任何平台的前端都不怕”。

 

 返回目录

 

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


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

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

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

最后

以上就是大方菠萝最近收集整理的关于spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发的全部内容,更多相关spring内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部