哪位大神有spring boot vueboot+vue+idea开发工具的教程呢

spring boot + vue + element-ui全栈开发入门——基于Electron桌面应用开发_码神岛
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 项目名称
vue init simulatedgreg/electron-vue admin
这里的项目名称是“admin”&
如果没有安装vue脚手架,请查看《》&
&然后运行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
二、代码编写
&参照《》安装所需的依赖
cnpm install --save element-ui
cnpm install --save-dev node-sass
cnpm install --save-dev sass-loadercnpm install --save font-awesome
&参照《》的代码如下:
入口文件:
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 */
components: {
template: '&App/&'
}).$mount('#app')
其中&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&
&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 v-else class="system-name"&{{systemName}}&/span&
&/el-header&
&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-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&
&el-col :span="6"&&span class="el-dropdown-link userinfo-inner"&你好:{{userName}}&/span&&/el-col&
&/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&
let data = () =& {
collapsed: false,
systemName: '后台管理',
userName: '系统管理员',
menuHeight: '100%',
let initMenu = function() {
for (let i in this.$router.options.routes) {
let root = this.$router.options.routes[i]
if (root.hidden)
let children = []
for (let j in root.children) {
let item = root.children[j]
if (item.hidden)
children.push(item)
if (children.length & 1)
this.menus.push(root)
root.children = children
let initHeight = function() {
this.menuHeight = (document.documentElement.clientHeight - 60) + 'px'
export default {
data: data,
methods: {
//初始化高度
initHeight
mounted: function() {
this.initHeight()
window.addEventListener('resize', this.initHeight)
this.initMenu()
&style scoped="scoped"
lang="scss"&
$width: 100%;
$height: 100%;
$background-color: #09345f;
$header-color: #
$header-height: 60
.container {
position: absolute;
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;
width: $width;
height: $height;
.menu-button {
width: 14px;
cursor: pointer;
.userinfo-inner {
cursor: pointer;
.el-menu {
height: $height;
background-color: $background-color;
color: $header-color;
text-align: center;
line-height: $header-height;
padding: 0;
.header-title {
text-align: left;
padding: 0 20px;
.system-name {
font-size: large;
font-weight: bold;
会员数据列表页面:
&template&
&!--工具条--&
&el-col :span="24" class="toolbar" style="padding-bottom: 0"&
&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-table :data="rows" style="width: 100%;overflow:" :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&
&/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:"&
&/el-pagination&
&!--对话框--&
&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&
&/el-dialog&
&/section&
&/template&
const rules = {
required: true,
message: '请输入姓名',
trigger: 'blur'
required: true,
message: '请选择性别',
trigger: 'change'
let data = () =& {
//每页数量
//查询条件
filters: {},
//页面数据
//页面载入状态
pageLoading: false,
//列表高度
clientHeight: '100%',
//表单数据
//验证规则
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)
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
this.$message({
type: 'success',
message: '删除成功!'
this.page = 1
this.getRows()
}).catch(e =& this.pageLoading = false)
}).catch(e =& {})
let getRows = function() {
if (this.pageLoading)
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)
//总数赋值
this.total = res.data.total
this.page++;
//页面元素赋值
this.rows = res.data.rows
}).catch(e =& this.pageLoading = false)
let handleSubmit = function() {
if (this.formLoading)
this.$refs.form.validate(valid =& {
if (!valid)
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'
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,
//获取分页
//初始化高度
initHeight,
//提交数据
handleSubmit
mounted: function() {
window.addEventListener('resize', this.initHeight)
this.initHeight()
this.getRows()
&style scoped&
Member.vue
结构如下图所示:
还有,在运行之前,我们需求修改src/main/index.js的配置:
function createWindow() {
* Initial window options
mainWindow = new BrowserWindow({
height: 563,
useContentSize: true,
width: 1000,
webPreferences: {
webSecurity: false
其目的是为了实现js跨域。
运行之前项目的后端项目《》:
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/ 欢迎转载,但须保留版权懂的人自然会懂,不懂的人也无需懂。考研中...投稿:9粉丝:109分享--dynmicweibozoneqqbaidu将视频贴到博客或论坛视频地址复制嵌入代码复制微信扫一扫分享收藏0硬币--稍后看马克一下~用手机看转移阵地~用或其他应用扫描二维码手机下视频请使用扫码若未安装客户端,可直接扫此码下载应用看过该视频的还喜欢正在加载...miniOFFSpringboot+vue 实现简单前后端分离 - 简书
Springboot+vue 实现简单前后端分离
1.vue 环境搭建与项目创建
vue2.0 推荐开发环境
安装完node.js后打开cmd小黑窗安装淘宝镜像,用cnpm代替npm,依赖全 速度快
npm install -g cnpm --registry=https://registry.npm.taobao.org
安装webpack
cnpm install webpack -g
安装vue脚手架
npm install vue-cli -g
测试是否安装成功
在硬盘上找一个文件夹放工程用的,在终端中进入该目录
cd 目录路径
根据模板创建项目
vue init webpack vueDemo
安装项目依赖
cnpm install
创建完成后的样子
cnpm run dev
帅气界面 默认80端口 没有 go to XXX 链接
2.vue设置路由
如果创建好的vue项目里没有 vue-router 路由依赖需要自行添加,我的创建项目时添加过了,所以省略
cnpm install vue-router --save
用 Vue.js + vue-router 创建单页应用,是非常简单的。使用 Vue.js ,我们已经可以通过组合组件来组成应用程序,当你要把 vue-router 添加进来,我们需要做的是,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们
新创建vue项目时,会有设置好的主页面和vue组件,为了方便我直接在原有的上面修改
修改组件 添加其他页面的路径 App.vue修改后
&h1&Hello App!&/h1&
&!-- 使用 router-link 组件来导航. --&
&!-- 通过传入 `to` 属性指定链接. --&
&!-- &router-link& 默认会被渲染成一个 `&a&` 标签 --&
&router-link to="/"&Go to 首页&/router-link&
&router-link to="/foo"&Go to Foo&/router-link&
&router-link to="/bar"&Go to Bar&/router-link&
&!-- 路由出口 --&
&!-- 路由匹配到的组件将渲染在这里 --&
&router-view/&
设置路由 配置路径对应加载vue组件 src/router/index.js修改后
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Foo from '@/components/Foo'
import Bar from '@/components/Bar'
Vue.use(Router)
export default new Router({
path: '/',
name: 'HelloWorld',
component: HelloWorld
path: '/foo',
name: 'Foo',
component: Foo
path: '/bar',
name: 'Bar',
component: Bar
新建 Foo.vue和Bar.vue 为了在路由地址改变后 加载后显示相应的元素
先不贴代码 后面会贴
vue 渲染视图 main.js 修改后
import Vue from 'vue'
import App from './App'
//引入组件
import Foo from './components/Foo'
import Bar from './components/Bar'
import router from './router'
//引入resource
import VueResource from 'vue-resource'
//引入jQuery
import $ from 'jquery'
Vue.use(VueResource);
Vue.config.productionTip = false
/* eslint-disable no-new */
el: '#app',
render: h =& h(App)
3.vue与后台交互 vue-resource jquery 涉及到的问题跨域
如果没有resource
jquery 依赖 需先添加
cnpm install vue-resource --save
jquery 设置全局
cnpm install jquery --save
在build文件夹下的webpack.base.conf.js文件中添加:var webpack = require("webpack")
// 增加一个plugins
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js'),
new webpack.ProvidePlugin({
jQuery: "jquery",
$: "jquery"
跨域相关 jsonp vue设置proxyTable
jsonp 没有在本地测试 用的 豆瓣公共接口
前面提到的Foo.vue
&template&
&div id="foo"&
&li v-for="article in articles"&
{{article.title}}
&/template&
export default {
name: 'Foo',
articles: []
mounted: function() {
this.$http.jsonp('https://api.douban.com/v2/movie/top250?count=10', {}, {
headers: {
emulateJSON: true
}).then(function(response) {
// 这里是处理正确的回调
this.articles = response.data.subjects
// this.articles = response.data["subjects"] 也可以
}, function(response) {
// 这里是处理错误的回调
console.log(response)
vue设置proxyTable config/index,js修改, 前面提到的Bar.vue ,SpringBoot Controller
proxyTable: {
target: 'http://localhost:8080',
changeOrigin:true,
pathRewrite: {
'^/api': ''
通过ajax请求
export default {
name: 'Bar',
mounted: function() {
var _self=
url:"/api/article/get/"+"123",
url:"/api/courseOrder/search",
type:"get",
dataType: "JSON",
async : false,
success:function(result){
_self.user =
error:function(jqXHR, textStatus, errorThrown){
console.log("请求失败");
/*弹出jqXHR对象的信息*/
console.log(jqXHR.responseText);
console.log(jqXHR.status);
console.log(jqXHR.readyState);
console.log(jqXHR.statusText);
/*弹出其他两个参数的信息*/
console.log(textStatus);
console.log(errorThrown);
通过 resource 请求
export default {
name: 'Bar',
mounted: function() {
this.$http.get('/api/article/get/'+'123', {}, {
this.$http.get('/api/courseOrder/search', {}, {
headers: {
emulateJSON: true
}).then(function(response) {
// 这里是处理正确的回调
this.user = response.data
// this.articles = response.data["subjects"] 也可以
}, function(response) {
// 这里是处理错误的回调
console.log(response)
controller
package com.smallcode.springbootvuewsample.
import org.springframework.web.bind.annotation.GetM
import org.springframework.web.bind.annotation.PathV
import org.springframework.web.bind.annotation.RestC
import java.util.HashM
import java.util.M
@RestController
public class ArticleController {
@GetMapping("/article/get/{id}")
public Map get(@PathVariable int id) {
Map&String, Object& map = new HashMap&&();
map.put("id", id);
map.put("name", "test");
map.put("desc", "testDesc");
vue修改端口号 修改 config/index.js port:8081
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8081, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
DIY 一个自己的音乐播放器 - 前端 - 掘金前言:在最近的一个外包项目中包联盟(PC端)中使用到了video,遇到了好多坑。突发奇想来踩一踩audio的坑?,果然一入深似海,?下面将分享我的DIY之路-Vue音乐播放器。注:本项目为开源项目,不能用于商业应用,仅供学习。...
(译) 使用 Vue.js 和 Axios 从第三方 API 获取数据 — SitePoint - 前端 - 掘金更多的往往不是,建立你的JavaScript应用程序时,你会想把数据从远程源或消耗一个[ API ](https:/ /恩。维基百科。org /维基/ appl...
低仿饿了么 H5 - 纯前端 Vue 版 + 手把手教学 - 前端 - 掘金低仿饿了么H5-纯前端Vue版+手把手教学 这是一个低仿饿了么H5的纯前端练手,数据是伪造的,写的比较粗糙,写这个的目的是为了加深一下熟练度,半年前看到别人写的仿cnodejs网站,我也用vue1仿...
Vue.js 自定义指令的用法与实例 - 前端 - 掘金市面上大多数关于Vue.js自定义指令的文章都在讲语法,很少讲实际的应用场景和用例,以致于即便明白了怎么写,也不知道怎么用。本文不讲语法,就讲自定义指令的用法。 自定义指令是用来操作DOM的。尽管Vue推崇数据驱动视图...
javascript 正则表达式总结 - 前端 - 掘金为什么要使用正则表达式 正则表达式通过由普通字符和特殊字符组成的文字模板完成对字符串的校验,搜索,替换。在javascript中类似这样 ... 平时自己项目中用到的 CSS - 掘金css有些属性容易忘记,半天不写就...
虽然这本《简单的逻辑》挺薄的,来回翻了两遍,可是作业还是写不出来,我的逻辑力真是……(面壁思过去) 这两天都在看同学的作业,很有启发。 R选自原书 10 三段论 三段论这种论证形式反映了人类思维的习惯性运作,即通过观点的联系可以推导出结论。像我们讨论过的简单论证模式一样,在...
首先要在mongodb的官方网站上下载对应系统的mongodb 然后点击安装,这里一定要记住自己的安装路径。 安装好了过后就通过cmd命令行工具进入到安装目录中的bin目录下 1:然后开始启动:mongod --dbpath=D:\mongodb\db 出现错误: 2:然后...
这两天进厂车辆比较多 对组里的每一辆车 都要过手仔细检查 避免客户过年回家车出问题 影响回家过年 总结 服务好每一位客户 检查好每一辆车 杜绝给公司造成损失和不良影响
前天晚上放学,大女儿吴思莹和我分享,郭子铭同学利用学习之余开了一家超市,同学们可以在他那里购买学习用品(购买等于用自己不需要的东西置换),买5个东西就可以办理VIP,于是吴思莹用一支不用的圆珠笔,一个不用的涂改带,换了一个她喜欢的涂改带,结果郭子铭又送了他一支圆珠笔。 郭子...
故有思心照有曦 踏望江水落朝篱 千古恨忘幽兰怨 何待君期美人依

我要回帖

更多关于 springboot vuejs 的文章

 

随机推荐