日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

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

發(fā)布時間:2025/4/16 93 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?前言


?

  Electron是由Github開發(fā),用HTML,CSS和JavaScript來構(gòu)建跨平臺桌面應(yīng)用程序的一個開源庫。 Electron通過將Chromium和Node.js合并到同一個運(yùn)行時環(huán)境中,并將其打包為Mac,Windows和Linux系統(tǒng)下的應(yīng)用來實(shí)現(xiàn)這一目的。

Electron于2013年作為構(gòu)建Github上可編程的文本編輯器Atom的框架而被開發(fā)出來。這兩個項(xiàng)目在2014春季開源。

目前它已成為開源開發(fā)者、初創(chuàng)企業(yè)和老牌公司常用的開發(fā)工具。 看看誰在使用Electron 。

繼續(xù)往下閱讀可以了解Electron的貢獻(xiàn)者們和已經(jīng)發(fā)布的版本,或者直接閱讀快速開始指引來開始用Electron來構(gòu)建應(yīng)用。

(摘抄至electronjs.org)

?

?

?

一、初始化項(xiàng)目


?

運(yùn)行,vue init simulatedgreg/electron-vue 項(xiàng)目名稱

vue init simulatedgreg/electron-vue admin

  

這里的項(xiàng)目名稱是“admin”?

如果沒有安裝vue腳手架,請查看《spring boot + vue + element-ui全棧開發(fā)入門——windows開發(fā)環(huán)境》?

?

?

?

一路回車

?

?然后運(yùn)行npm install來安裝依賴,運(yùn)行方式和之前一樣。

如果遇到run dev或者run build的時候出錯,可能是因?yàn)閲鴥?nèi)的網(wǎng)絡(luò)下載“electron-v1.8.3-win32-x64.zip”出錯,這時,你需要設(shè)置npm的代理:

npm config set proxy http://服務(wù)器IP或域名:端口號 npm config set https-proxy http://服務(wù)器IP或域名:端口號

  

如果需要用戶名密碼:

npm config set proxy http://用戶名:密碼@服務(wù)器IP或域名:端口號 npm config set https-proxy http://用戶名:密碼@服務(wù)器IP或域名:端口號

  

設(shè)置回原庫

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

?

也可以使用yarn。

npm install -g yarn

  

安裝依賴、開發(fā)模式運(yùn)行和編程的命令分別是:

yarn install yarn run dev yarn run build

  

?

項(xiàng)目構(gòu)建完畢后,結(jié)構(gòu)如下圖所示:

和之前項(xiàng)目區(qū)別是,main是用于桌面程序的代碼,render是用于渲染的代碼。我們只需要在render文件夾里寫代碼就可以。

?

開發(fā)模式運(yùn)行:

npm run dev

  

?

?

二、代碼編寫


?

?參照《spring boot + vue + element-ui全棧開發(fā)入門——集成element-ui》安裝所需的依賴

?

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全棧開發(fā)入門——前端列表頁面開發(fā)》的代碼如下:

?

入口文件:

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' //原始風(fēng)格 // import 'element-ui/lib/theme-chalk/index.css' //自定義風(fēng)格 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' 是設(shè)置后端項(xiàng)目URL,而這可以根據(jù)具體情況寫到配置文件中,開發(fā)環(huán)境調(diào)用開發(fā)環(huán)境的配置,生產(chǎn)環(huán)境調(diào)用生產(chǎn)環(huán)境配置。

?

路由文件:

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><!--內(nèi)容--><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: '系統(tǒng)管理員',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

?

會員數(shù)據(jù)列表頁面:

<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="姓名/手機(jī)號等條件" /></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,//每頁數(shù)量 size: 20,//總數(shù) total: 0,//查詢條件 filters: {},//頁面數(shù)據(jù) rows: [],//頁面載入狀態(tài) pageLoading: false,//列表高度 clientHeight: '100%',//表單數(shù)據(jù) form: {},//驗(yàn)證規(guī)則 rules: rules,//對話框隱藏狀態(tài) formVisible: false,//表單提交狀態(tài) 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('此操作將永久刪除該數(shù)據(jù), 是否繼續(xù)?', '提示', {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}//調(diào)用post請求this.$http.post('/member/loadPage', params).then(res => {this.pageLoading = falseif (!res.data || !res.data.rows)return//總數(shù)賦值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//調(diào)用http協(xié)議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: '保存成功!'})//重新載入數(shù)據(jù)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,//頁數(shù)改變 handleCurrentChange,//獲取分頁 getRows,//初始化高度 initHeight,//提交數(shù)據(jù) handleSubmit},mounted: function() {window.addEventListener('resize', this.initHeight)this.initHeight()this.getRows()} } </script><style scoped> </style> Member.vue

?

結(jié)構(gòu)如下圖所示:

?

?

還有,在運(yùn)行之前,我們需求修改src/main/index.js的配置:

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

?

其目的是為了實(shí)現(xiàn)js跨域。

?

運(yùn)行之前項(xiàng)目的后端項(xiàng)目《spring boot + vue + element-ui全棧開發(fā)入門——spring boot后端開發(fā)》:

mvn package java -jar target/demo.jar

  

?

運(yùn)行項(xiàng)目,效果如下:

?

?

?

二、生成安裝包


?

npm run build

?

  

?

如提示缺少vue組建,是因?yàn)閞egistry的問題,因?yàn)閲鴥?nèi)taobao鏡像沒有Electron的依賴環(huán)境。所以需要設(shè)置回默認(rèn)的?registry,并使用設(shè)置proxy的方式下載依賴環(huán)境。

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

就把“icons”加到build目錄下,下載icons請點(diǎn)擊鏈接,根據(jù)具體情況修改icons。

生成好后,出現(xiàn)“admin Setup 0.0.0.exe”的文件,即安裝程序。

我運(yùn)用這個安裝程序后,打開剛剛開發(fā)好的程序,效果如圖所示:

?

?

發(fā)現(xiàn),雖然只用到了一些前端技術(shù),但已經(jīng)能夠開發(fā)出桌面應(yīng)用了。小時候,老師說:“學(xué)好數(shù)理化,走遍天下都不怕”。而現(xiàn)在是:“學(xué)會了node,任何平臺的前端都不怕”。

?

?返回目錄

?

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


如果你覺得我的博客對你有幫助,可以給我點(diǎn)兒打賞,左側(cè)微信,右側(cè)支付寶。

有可能就是你的一點(diǎn)打賞會讓我的博客寫的更好:)

作者:劉冬.NET 博客地址:http://www.cnblogs.com/GoodHelper/ 歡迎轉(zhuǎn)載,但須保留版權(quán)

總結(jié)

以上是生活随笔為你收集整理的spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。