vue-cli@3 + electron开发一款本地小说阅读器(一)
vue-cli@3 + electron开发一款本地小说阅读器(二)
vue-cli@3 + electron开发一款本地小说阅读器(三)
vue-cli@3 + electron开发一款本地小说阅读器(四)
vue-cli@3 + electron开发一款本地小说阅读器(五)
一、关于上一篇遗留下来的中文乱码的问题
1、用到iconv-lite
npm i iconv-lite -s -d
2、关于报错_webpack_require()的解决方法
到node_modules中找到iconv-lite文件夹,lib文件夹,打开index.js,最下方有两个require的后一个参数括号去掉,如下:
var nodeVer = typeof process !== 'undefined' && process.versions && process.versions.node;
if (nodeVer) {
// Load streaming support in Node v0.10+
var nodeVerArr = nodeVer.split(".").map(Number);
if (nodeVerArr[0] > 0 || nodeVerArr[1] >= 10) {
require("./streams");//修改这个
}
// Load Node primitive extensions.
require("./extend-node");//修改这个
}
if ("Ā" != "\u0100") {
console.error("iconv-lite warning: javascript files use encoding different from utf-8. See https://github.com/ashtuchkin/iconv-lite/wiki/Javascript-source-file-encodings for more info.");
}
3、编写判断编码和转码的js:getTxt.js
判断编码的方法,我这里返回的是需要解码用的格式
/*
* 传入txt路径,返回解码的格式
* */
judgeCode(path) {
return new Promise(function (resolve, reject) {
fs.readFile(path, function (err, buffer) {
if (err) {
reject(err)
}
let type;
if (buffer[0] == 0xff && buffer[1] == 0xfe) {
type = 'utf16'
} else if (buffer[0] == 0xfe && buffer[1] == 0xff) {
type = 'utf16'
} else if (buffer[0] == 0xef && buffer[1] == 0xbb) {
type = 'utf8'
} else {
type = 'GBK'
}
resolve(type)
})
})
},
然后,根据得到的需要转码的编码利用iconv进行转码并得到数据就可以了
//转换编码
iconv(type, buf) {
return iconv.decode(buf, type)
},
//获取内容
getTxt(path) {
let _that = this;
return this.judgeCode(path).then(function (type) {
let buf = fs.readFileSync(path);
let str = _that.iconv(type, buf)
return str;
})
},
经过测试:txt的四种编码:ansi、unicode、unicodebigendian以及常用的gbk、gb2312都没有问题。
二、关于打包后不能用的说明
我们之前是手动创建的两个json文件,一个用来放book列表,一个用来放标签。打包后文件都会被放到asar中,默认该文件只能读,不能写。当然还有其他一些问题。。。
怎么办?
这里我们需要用到数据库,可能也有其他的解决办法,不过没有时间试验,我们还是用数据库吧。
数据库的选择有两个:NeDB和SQlite,都是嵌入式数据库。NeDB又称为node嵌入式数据库,感兴趣的可以自行了解。我要用的是SQlite,好处嘛也自行百度。
SQlite是用c语言写的,如果直接引用到Electron项目中需要用C语言进行编译后才可以正常使用,关于如何编译,大家可以看苏南大叔的文档,我觉得已经算是最新的文档了。其实现在安装没有这么麻烦了
注意几点:
1、Python 2.7(版本是2.7)
2、手动下载vs_BuildTools
安装node.js生成工具,不用下其他的C语言开发环境了,网速慢的话要累死
![](https://img.haomeiwen.com/i4542659/4d50f15dc453a0cd.png)
3、
npm install windows-build-tools -g
安装这个用管理员安装,如果报错powershell.exe 这种错误就把powershell的路径放到path系统环境变量里去4、electron的版本改到5.0.6
5、linux系统需要安装g++
大概就这些,然后
npm i sqlite3 -s -d
就ok了,会自动编译好,如果有问题,可以找我
三、用数据库代替我们的json文件
control.js
const path = require('path')
const sqlite = require('sqlite3').verbose()
const db = new sqlite.Database(path.join(__static, '../db.db'));
在new的时候他会判断,如果存在就打开,如果不存在就创建数据库。
1、创建两个表,还是在control.js中,创建一个方法
//初始化,不存在就创建两个表
init() {
db.serialize(function () {
db.run("CREATE TABLE IF NOT EXISTS BOOKLIST(\n" +
" id INT PRIMARY KEY NOT NULL,\n" +
" bookName TEXT NOT NULL,\n" +
" size INT NOT NULL,\n" +
" tab TEXT,\n" +
" src TEXT\n" +
");")
db.run("CREATE TABLE IF NOT EXISTS TABS(\n" +
" TABNAME TEXT\n" +
")")
});
},
2、插入数据的方法
control.js
create(e) {
let sql = "INSERT INTO BOOKLIST VALUES('" + e.id + "','" + e.bookName + "', '" + e.size + "', '" + e.tab + "', '" + e.src + "' );";
// let query = "INSERT INTO BOOKLIST VALUES (7, 'James', 24, 'Houston', 10000.00 );"
return new Promise(function (resolve, reject) {
db.run(sql, (err,) => {
if (err) reject(err)
else {
// resolve("插入成功!")
store.commit("add")
}
})
}
)
},
3、其他方法:
删除一条book信息的方法、上传txt时判断有没有重复的方法、获取数据库中所有book列表信息的方法、根据标签获取book列表信息的方法、添加标签时判断标签重复的方法、新增标签的方法、获取所有标签的方法、修改标签名的方法、删除标签的方法。大致就这些方法,把这些方法全部封装到control.js文件中,方便我们后面调用。
因为篇幅原因,后续源码放到公众号,欢迎批评指正,我也是萌新!
4、假如数据库的都弄好了,剩下的就是操作数据,更新数据的问题了,主要说点技巧性的
我们引用了数据库后,会发现如果数据库信息发生变化,主要是增加或删除后,如何监听数据变化并及时的渲染到前端上?
我的解决思路是通过vuex来实现,然后当数据库发生改变时,改变vuex的状态,页面层可以用watch来监听vuex的状态,如果发生改变就调用数据库重新获取数据,更新到data。
举例:
1、安装vuex
2、在src下新建一个文件夹store,然后新建一个index.js文件,内容:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
count: 0
},
mutations:{
add(state){
state.count = state.count + 1
},
del(state){
state.count = state.count - 1
}
}
})
export default store
注意区分大小写,否则会报错。
解释:初始化一个count,默认为0,然后有两个方法,一个+1,一个-1。(其实写一个方法就行,只要保证状态发生改变就行了)
3、vue全局注册,到main.js中
import Vue from 'vue'
import App from './App.vue'
import './assets/plugins/element.js'
import store from './store/index'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
4、数据库中调用store方法,到control.js中,引入我们刚才写的index文件
import store from '../../store/index'
我们一开始写的create的方法
//插入一条book信息
create(e) {
let sql = "INSERT INTO BOOKLIST VALUES('" + e.id + "','" + e.bookName + "', '" + e.size + "', '" + e.tab + "', '" + e.src + "' );";
// let query = "INSERT INTO BOOKLIST VALUES (7, 'James', 24, 'Houston', 10000.00 );"
return new Promise(function (resolve, reject) {
db.run(sql, (err,) => {
if (err) reject(err)
else {
// resolve("插入成功!")
store.commit("add")
}
})
}
)
},
其中:store.commit('add')就是改变状态用的
5、页面中监听,利用watch进行监听,如果改变值了,就执行方法
watch: {
'$store.state.count': function () {
let _that = this
Control.getAll().then(function (e) {
_that.tableData = e;
})
Control.getAllTabs().then(function (e) {
_that.tabList = e;
})
}
},
5、其他注意的问题
1、不要用alert,用alert后再弹出input输入框会发生input框不能输入的问题。
2、element-ui的Message失效的话,单独引用
import {Message} from 'element-ui';
调用
Message.error({
message: '请选择TXT文件'
})
三、效果展示
![](https://img.haomeiwen.com/i4542659/29a511ec6d057cac.gif)
![](https://img.haomeiwen.com/i4542659/37823628d5a12cb4.gif)
![](https://img.haomeiwen.com/i4542659/cfdb5710490da313.gif)
结束语
大致的功能实现了,还有一些功能待优化,源码后续会放到微信号里,欢迎大佬指正。
有问题欢迎微信留言,一起交流
![](https://img.haomeiwen.com/i4542659/820b0cab9e48461f.jpg)
网友评论