我们有一些需求可能是需要进行内网开发或者只能内网访问,如果用其他的东西可能有点麻烦,他还不能像electron一样可以通过一些按钮(操作)去控制服务器的开关,就比较麻烦;如果我们使用electron去开发的话,就能避免这些苦恼(尤其是前端开发者)而且electron是有node环境的哦!
需求分析
- 如果我们在同一个网络下,是可以通过ip进行访问的
- electron是拥有node环境功能的
- sqlite可以将数据保存在本地(嫁接到electron上)
技术栈
- electron
- sqlite3
- vue2
- 会一些基础的node语法
- 会一些简单的sql语法(增删改查)
核心代码
const os = require('os');
const http = require('http')
let server
var querystring = require("querystring");
// 开启局域网接口
function openServer() {
// 防止重复开启
closeServer()
// 获取本机的局域网IP和自定义端口
let SERVER_PORT = 8888
let SERVER_IP = getServerIp()
server = http.createServer()
server.on('request', (req, res) => {
// 防止跨域
res.writeHead(200, { "Content-Type": "application/json;charset=utf-8", "access-control-allow-origin": "*" })
let param = null; // 监听传递的值
req.on("data", function (postDataChunk) {
param = querystring.parse(postDataChunk.toString());
console.log(param);
});
// 监听 接口
req.on('end',()=>{
if (req.method === 'POST' && req.url === '/') {
let context = {
code: 200,
param,
data: { type: 'Hello World!' }
}
res.end(JSON.stringify(context))
}
})
})
// 返回端口开启结果
return new Promise((resolve, reject) => {
server.listen(SERVER_PORT, SERVER_IP, () => {
// 服务器正确开启
resolve({
code: 200,
data: `http://${SERVER_IP}:${SERVER_PORT}`,
msg: `服务器开启成功,服务器地址: http://${SERVER_IP}:${SERVER_PORT}`
})
})
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
// 服务器端口已经被使用
reject({
code: 404,
data: `端口:${SERVER_PORT}被占用,请更换占用端口`,
msg: `端口:${SERVER_PORT}被占用,请更换占用端口`
})
}
})
})
}
// 关闭server
function closeServer() {
server && server.removeAllListeners();
server && server.close(() => {
console.log("服务接口关闭");
});
}
// 获取本机的局域网IP
function getServerIp() {
let interfaces = os.networkInterfaces();
for (let devName in interfaces) {
let iface = interfaces[devName];
for (let i = 0; i < iface.length; i++) {
let alias = iface[i];
if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
return alias.address;
}
}
}
}
export {
openServer,
closeServer
}
引入使用
在点击开启的时候,去调用封装的函数即可;启动成功以后根据自己返回的状态,然后我们根据返回的ip地址在浏览器查看是否成功即可(postman也可以)。
<template>
<div id="app">
<router-view/>
<button @click="start">开启</button>
<p>{{ serverUrl }}</p>
</div>
</template>
<script>
// import { ipcRenderer } from "electron";
import { openServer, closeServer } from '@/utils/server';
export default {
name: "HomeView",
data(){
return {
serverUrl:''
}
},
components: {},
methods: {
start() {
openServer().then(res=>{
this.serverUrl = res;
})
}
},
mounted() {}
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
</style>
node接口传递的值(POST)
引入querystring模块,然后通过req去监听data的值,并将其Buffer类型的数据转为JSON字符串,最后通过querystring将其转为对象即可
- req.on监听data数据(buffer数据)
- 将buffer转为json字符串
- 然后解析为对象(querystring)
var querystring = require("querystring");
server.on('request', (req, res) => {
// 防止跨域
res.writeHead(200, { "Content-Type": "application/json;charset=utf-8", "access-control-allow-origin": "*" })
let param = null;
// 监听参数
req.on("data", function (postDataChunk) {
param = querystring.parse(postDataChunk.toString());
console.log(param);
});
// 监听接口
req.on('end',()=>{
if (req.method === 'POST' && req.url === '/') {
let context = {
code: 200,
param,
data: { type: 'Hello World!' }
}
res.end(JSON.stringify(context))
}
})
})
安装以及使用sqlite3
如果大家需要了解sqlite3的使用以及安装的话可以去查看这个文章 electron 中使用本地数据库;这篇文章会将所有的过程都会教给大家,以及怎么使用等等。
yarn add sqlite3
请求本地数据sql
这个接口用到的sql语句都是比较基础的,大家简单看一下基本上就能写出来了,如果你没接触过的话,建议你去看看这个文章electron 中使用本地数据库
- count(*) total 是去查看总的数据条数
- 然后有一个分页写法,本来分页的数据是传递进来的(page,pageSize),我没有去做个;你们如果在开发的时候是需要去做这一步的。
- 最后就是将成功的数据返回回去就行了,可以根据你自己的需要返回不同的状态以及文本提示
getTest() {
const page = 1, pageSize = 10 ;
let db = sqliteDb();
// 获取total语法
let totalSql = `select count(*) total from test`;
let total = 0;
return new Promise((resolve, reject) => {
// 统计总数
db.all(totalSql, (err, totalData) => {
if (err) { reject({ code: 200, msg: err, data: '总计条数错误' }) };
total = totalData[0].total;
});
// 实现分页语法
let sql = `select * from test`;
sql += ` limit ${(page - 1) * pageSize},${pageSize}`;
db.all(sql, (error, data) => {
if (error) {
reject({ code: 400, msg: error });
} else {
resolve({ code: 200, msg: '成功', data });
}
});
})
}
接收消息以后请求本地数据库
我这儿只是简单的写了一部分,大家在这儿的时候需要去监听以防止错误;大家在工作的时候尽量多封装,我这儿也是分开封装的;大家可以根据自己的情况进行封装;避免文件很乱,自己都找不到的情况
- 监听请求GET的url:'/'
- 请求本地数据库
- 将数据库数据返回
request.on('end',async ()=>{
if (request.method === 'GET' && request.url === '/') {
let context = {
code: 200,
param,
data: { type: 'Hello World!' }
}
const res = await sqliteApi.getTest();
console.log(res);
context.id = res.data;
restore.end(JSON.stringify(context))
}
})
以上所搭建的项目是比较简单的那种,也可以理解为一个demo(但是功能是全的);小伙伴们可以根据自己的需要然后进行一些修改以及封装一类的。
如果大家喜欢这一期的内容,就点个赞吧!
往期文章