先说下我决定用sqlite的条件:

主要是流程处理,需要在无网络的情况下实现,数据量多的时候用h5的缓存完全不够,在看了文档之后选择使用SQLite ,早起在mui的时候使用的indexDB;

因为在社区也没收到具体的,所以写下记录下也和小伙伴分享下,有啥问题可以互相交流下。

该文档中用到的两个点 (SQLite 和vue中的mixin)

我这有两个环境,我先说一个简单;

主页菜单进去 到列表界面 从该步骤开始缓存本地数据;

从列表点击进入到详情,并在详情操作。有网络正常,无网络时存入表中,当切换到有网情况后,进行提交;

使用SQLite时需要先开权限,在配置文件中,如下图

SQLite官方demo ; 在hbuilderX 下新建demo pages/API/sqlite/sqlite 下官方提供的sqlite使用。为了使用方便,我把需要的单独提出来;

该出贴出function 代码,不做具体说明;

function openComDB(name, path, callback) {

plus.sqlite.openDatabase({

name: name,

path: path,

success: function(e) {

// plus.nativeUI.alert('打开数据库成功');

callback(e)

},

fail: function(e) {

// plus.nativeUI.alert("打开数据库失败");

callback(e);

}

})

}

function executeSQL(name, sql, callback) {

plus.sqlite.selectSql({

name: name,

sql: sql,

success: function(e) {

// console.log("查询数据库:" + name + ",表:" + sql + ";的");

// console.log(JSON.stringify(e));

callback(e);

},

fail: function(e) {

console.log("查询数据库失败:" + JSON.stringify(e));

callback(e);

}

})

}

export{

openComDB,

executeSQL

}

该出 进入正题;

在需要用到的vue文件下,引入上方function; 路径是自己的;

import {openComDB,executeSQL,dropSQL} from '../../common/env.js'

说下简单的思路:

1.进入lists界面,先判断是否有网络,有网络正常调用,无网络时需要判断本地数据库中是否有数据,无数据则第一次进入。有数据需要调用本地数据中的数据;

ps

在有些uni使用上可能会和现在的有点出入,因为这个是早期写的NFC写入的功能,用的nvue的,还是weex的模式下。

贴上部分相关代码

created() {

this.getNetworkType(); //初始化网络当前状态;

uni.onNavigationBarButtonTap((e) => {

//该处是因为的导航栏右边加了两个筛选条件。可以忽略。 不过如果做离线需要筛选的,筛选条件等数据同样需要缓存

if (e.index == 1) {

this.pickType();

} else if (e.index == 0) {

this.pickBuild()

}

})

},

methods: {

getNetworkType() {

//获取网络信息

uni.getNetworkType({

success: res => {

this.netWork = res.networkType;

this.isOpenDB();

}

})

},

isOpenDB() {

console.log('是否打开数据库');

var isOpen = plus.sqlite.isOpenDatabase({

name: 'nfc', //数据库的名字

path: '_doc/nfcList.db' //地址

});

console.log(!isOpen);

if (!isOpen) {

console.log('Unoepned:' + isOpen);

// plus.nativeUI.alert('Unopened!');

this.openDB(); //打開DB

} else {

// plus.nativeUI.alert('Opened!');

this.isNet();

// this.getLocalType();

}

},

openDB() {

//SQLite

openComDB('nfc', '_doc/nfcList.db', res => {

console.log('打开数据库');

this.isNet();

});

},

isNet(){

//网络问题;

if (this.netWork == 'wifi' || this.netWork == '4g') {

//在有网络情况下,会先情况之前的表,为了防止没有及时更新到数据。update我是嫌麻烦,没这样写。就这样暴力写了。

console.log('wifi || 4g ');

this.dropTable("pointLists");

this.dropTable("codeTypeTable");

this.dropTable("codeTable");

this.dropTable("statusTable")

//删了之后创建表

this.createCodeTable();

this.createCodeTypeTable();

this.createBuildTable();

this.createLists();

this.createUpateStatus(); // 离线时更新

//然后把数据插入进去

this.getTabType(); //初始化格式

this.getPonitType(); //获取code。默认值

this.getCodeType(); // 类型下的选择项;

this.getBuilds(); // 获取建筑物数据

} else {

//无网络时;

console.log('初始化无网络');

this.getTabType(); //初始化格式

this.locCodeTypeItem();

this.selBuildFun();

}

//上面贴的drop,create,insert 我会在下面贴出部分代码。不会全部贴.SQL语句不会的建议百度找文档多看下,无非就是增删改查

},

}

整个代码贴上太长了,我还是分段写吧;

本身就是个带tab类型的列表。延用nvue 的 weex的形式,未改成uniapp形式,如需参照此处tab,需要看之前的官方demo。 建议用官方新的uniapp模式,我是懒得改。

//初始化

getTabType() {

//初始化列表;

let ary = [];

for (let i = 0; i < this.tabBars.length; i++) {

let aryItem = {

loadingText: "",

data: [],

pageNum: 1

}

ary.push(aryItem);

}

this.newsitems = ary;

if(this.netWork == "wifi" || this.netWork == "4g"){

this.getPointList() //默认加载未处理; 有网络下,正常调用接口

}else{

this.selPointList() //无网络下调用数据库表中的数据;

}

},

再有网络调用接口时需要将 数据insert到创建的数据表中;

创建数据库中的表

我的思路是整个app为一个数据库,有各种不同的表。 目前只有nfc中用到了,所以数据库的name 就取名 nfc 了,未进行修改;

现在正儿八经的创建表;

用简单的建筑信息为例;根据自己需要的进行创建表;

createBuildTable() {

//创建建筑物类型表;

var sqlTable = 'create table if not exists buildTable("id" INT(10) NOT NULL UNIQUE,"name" CHAR,"gridCode" CHAR)'

executeSQL('nfc', sqlTable, res => {})

},

在有网调用接口时,insert 表;需要与上方创建的完全对应,最后一个不加 “,” 只有不对应就会报错

insertBuildCode() {

for (var i = 0; i < this.builds.length; i++) {

var sqlInsert = "insert into buildTable values('";

sqlInsert += this.builds[i].id + "','";

sqlInsert += this.builds[i].name + "','";

sqlInsert += this.builds[i].gridCode + "'";

sqlInsert += ')';

executeSQL('nfc', sqlInsert, res => {

})

}

this.getLocBuilds() //插入成功后,就可以查看结果。此处用到就直接赋值,没用到,或者别处用到,就在别处调用

},

getLocBuilds() {

executeSQL('nfc', 'select * from buildTable', res => {

console.log("建筑物查询结果");

this.builds = res;

this.selBuildFun()

})

},

查看就这样,就写个简单的例子。列表数据比较多。就不放上。如果详情的数据是通过detailById 接口调用,list表的需要将详情的数据加进去。

当整个数据存上后,就是点击list跳转到detail界面。

detail正常的vue文件。

有网络时正常查看,进行提交操作。

无网络时,查看本地数据库的表。

所有创建和插入都是在list进行的,detail.vue中 进行 查看,和更改,如果需要删除 也可。 (因为在list就很有可能是无网络的情况,所以所有的数据都在列表获取到了)

list ---> detail

可以带id ,也可以带json、建议带唯一的id就可以了,可以在detail select 出需要的数据;

我这里是觉着数据已经在list存上了,detail不如直接使用,不管用网络无网络,本身做提交,后台也不会不停的改数据。

比较严谨的可以有网络时候调用详情接口,无网络时在本地查。

查询代码上面贴了列子此处就不放上了。

简单说一下离线提交。会用到VUE的mixin。

离线提交的思路 。在list的时候需要创建 提交的 表 locSubTable(随便起的名字方便后面提到) ,并在最后 加上 flag 字段 (这个自己随意) 类型INT 。因为没有布尔。所以在插入的时候需要用flag 0,1 进行判断是否需要缓存提交。

0 为 false 1 为 true ;

在detail 内,若 是离线时进行提交,在 locSubTable 进行insert 。最后flag 插入 为 0 ;

在无网络切换至 wifi/4g下,查询 locSubTable 表 where flag = 0 的数据。 返回的 res.length = 0 的时候,无离线提交。

ren.length 有数据需要循环提交。接口提交成功之后需要。update locSubTable 中的 flag = 1 。表示缓存的数据已经被成功提交掉。

还需要更新下list 表的数据,将状态从 未处理 update 为 已处理 (此处更改是因为我的列表是tab类型。流程处理后的状态需要及时更新掉。)

写之前是打算贴代码的,写上之后发现不知道从哪里下手贴,只能说下处理的思路。

后面简单说下mixin的使用。是为了在全局监听网络变化,并能在app下进行离线提交。

在社区找到了uniapp是可以支持的。不过好像用的也不多。(此处该贴上官方链接,找到补上)

因为监听网络切换的时候,界面不会只停留在当前页。但是每个页面都写上也太多了,后来在vue的文档中找到了mixin 混入

《当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项 》

在写的时候也发现的一些坑,会一起记录下。(如果写完发现太多了那我就是被疫情在家憋惨了,憋成了话痨,尴尬)

再common中新建 mixin.js ; mixin的基础使用,可以在vue官方文档查找。

var isLoc ={

data() {

return {} // 有需要的data,也可以加上,我没有用到。

},

methoad:{

//因为需要在其他地方查数据库,所以依旧在最开始打开数据库

isOpenDB() {

console.log("mixin 中是否打开数据库");

var isOpen = plus.sqlite.isOpenDatabase({

name: 'nfc',

path: '_doc/nfcList.db'

});

console.log("数据库是否打开:" + !isOpen);

if (!isOpen) {

console.log('unopen:' + isOpen)

this.openDB()

}

},

openDB() {

openComDB('nfc', '_doc/nfcList.db', res => {

console.log("mixin:打开数据库");

this.getLocUser()

})

},

selStatusList() {

//查询是否有离线写入,未提交数据; flag == 0 false。

// console.log("切换至网络,查询是否有缓存未提交数据");

executeSQL('nfc', 'select * from statusTable where flag = 0', res => {

// console.log(res)

// console.log(res.length);

for (var i = 0; i < res.length; i++) {

this.submitPointFun(res[i].id); //返回的参数根据实际情况来的。

}

})

},

submitPointFun(curId) { // 提交巡检接口

//提交接口

getData({id: curId},data => { //填自己的接口、本身这个我封了下,按照自己的来。

urlFuc("xxxxxxxx", data, res => {

console.log("当前ID:" + curId + "提交成功");

//返回 成功后, 对列表的数据进行update 。

this.updatePointStatus(curId);

this.updatePointList(curId)

});

});

},

updatePointStatus(curId) {

// 切换至有网络后,提交成功后,更新已提交成功数据 更新巡检点状态

//修改flag = 1 - true ;

var updateSQL = 'update statusTable set flag = 1 where id = ' + curId;

executeSQL('nfc', updateSQL, res => {

console.log("更新数据");

})

},

updatePointList(curId) {

// 状态更改后,更改列表改ID的数据

var updateSQL = 'update pointLists set status = "已关联" where id = ' + curId;

console.log(updateSQL);

executeSQL('nfc', updateSQL, res => {

console.log("更新列表数据")

})

},

},

},

created() {

this.isOpenDB();

uni.onNetworkStatusChange((res) => {

//监听网络

console.log('MIXIN 下监听网络');

// console.log(res.isConnected);

// console.log(res.networkType);

if (res.networkType == 'none') {

console.log('无网络');

// that.seleceByType();

} else if (res.networkType == 'wifi' || res.networkType == '4g') {

console.log('wifi');

//切换到有网络时,需要查看是否有离线数据,并进行提交。

this.selStatusList(); //查询是否有离线数据

this.selLocTaskList();

// that.getNfCList();

}

})

}

}

export {

isLoc

}

引用

import {

isLocData

} from '../../common/mixin.js'

export default {

mixins: [isLocData],

data(){}

}

遇到的坑,

最开始想放在app.vue下的。 但是安装后会白屏。后来改到main.vue下。

这是一个比较简单的使用,后面还有一个有点复杂的使用,离线提交的时候上报多选择数据和 图片,备注等信息。 (离线图片的时候,需要注意进程关掉再开,之前的缓存图片地址就没了,会导致离线上传时图片的丢失。所以建议不要手动关掉进程,或者将图片存下来,成功后再删掉。)

之后因为图片临时缓存的问题,我在本地存了,提交成功后,删除本地存的文件。(离线中mixin.js一样)

imageList ,当前图片显示,因为会多张图上传。

var files = [];

console.log(data.length);

var that = this;

//将临时文件存为本地文件,不受进程关闭的影响

for (var i = 0; i < data.length; i++) {

uni.saveFile({

tempFilePath: data[i],

success: img => {

var savedFilePath = img.savedFilePath;

console.log(savedFilePath);

that.imageList.push(savedFilePath)

console.log("tupian ")

console.log(that.imageList)

// files.push(savedFilePath);

// console.log(files);

// console.log(JSON.stringify(files));

}

})

}

成功后记得删除本地

removeSaveFiles(filePath) {

//移除本地存储文件;

console.log("需要删除的地址")

console.log(filePath)

uni.removeSavedFile({

filePath: filePath,

complete: function(res) {

console.log(res);

}

});

},

状态也有 未处理,处理中,已结束。多个tabs。用法还是一样的。不做说明了。开始以为就一点点的。没想到会写这么多。

希望有帮助,这个sqlite 也是这次的时候使用过的,之前也没有。毕竟是个前端,搞的时候也问了后台一些思路。可能不是很完美,如果有什么好的建议也可以和我说。

补充说明

有小伙伴在指出

文档中 增删改 使用

void plus.sqlite.executeSql(options);

查询 使用

void plus.sqlite.selectSql(options);

最开始没发现,我封装的 plus.sqlite.selectSql(options); 增删改查都可以使用,也没碰到什么问题。

建议大家按照官方的来使用。

Logo

前往低代码交流专区

更多推荐