当前位置: 主页 > 数据库

数据库存储html代码-python 数据转html库

发布时间:2023-02-09 10:22   浏览次数:次   作者:佚名

IndexedDB 是一种 API,用于在客户端存储大量结构化数据,并在这些数据上使用索引进行高性能检索。 尽管 DOM 存储对于存储少量数据非常有用,但它无法存储大量结构化数据。 IndexedDB 提供了这样的解决方案。

IndexedDB 为同步和异步访问提供单独的 API。 同步 API 仅供 Web Workers 在内部使用,但尚未被任何浏览器实现。 Web Worker 内部和外部都可以使用异步 API。 所以现在能用的基本都是异步API,因为在h5手机项目中使用了indexedDB来存储app相关的数据,所以写一些例子供参考:

1.异步API

首先了解什么是异步API:异步API方法被调用后会立即返回,不会阻塞调用线程。 要异步访问数据库,需要调用window对象的indexedDB属性的open()方法。 该方法返回一个IDBRequest对象(IDBOpenDBRequest); 异步操作通过触发 IDBRequest 对象上的事件与调用程序通信。 IDBOpenDBRequest 接口定义了几个重要的属性:

数据库调用成功、失败、升级的方法可以通过不同的回调函数来实现。 让我们从打开数据库开始。

2.创建(打开)数据库

在最简单的例子中,创建一个数据库至少需要两个参数:数据库名称和数据库版本。 为了方便起见,我们创建一个简单的数据库管理类:

class DBmanager {
    //数据库管理类的构造函数,包含两个构造参数,数据库名称和数据库版本,数据库版本如果不指定默认为1;
    constructor(DBname, DBversion) {
        this.DBname = DBname;
        this.DBversion = DBversion || 1;
        this.currentDB = null; //当前数据库
    }
    //打开(没有创建过则创建)数据库的方法
    openDB() {
        //调用API打开数据库
        var request = window.indexedDB.open(this.DBname, this.DBversion);
        //打开数据库失败的回调
        request.onerror = function (e) {
            console.log(e.currentTarget.error.message);
        }.bind(this);
        //打开数据库成功的回调
        request.onsuccess = function (e) {
            this.currentDB = e.target.result;
            console.log(this.currentDB.name + ' database is already opened!');
        }.bind(this);
        //数据库升级的回调
        request.onupgradeneeded = function (e) {
            console.log('database version is already upgrade to '+this.DBversion);
        }.bind(this);
    }
}

onupgradeneeded 回调将在两种情况下被调用:

当数据库首次创建时数据库版本发生变化

在调用onupgradeneeded的时候,onupgradeneeded会在onsuccess和onerror之前执行,因为打开数据库的时候,先检查是否有版本变化,如果有版本变化,先升级数据库再打开,这样我们就可以实现数据库onupgradeneeded 中的升级方法。

为了看到具体的执行效果,我们来运行一下:

window.onload = function () {
    var db = new DBmanager('testDB', 1);
    db.openDB();
}

在chromium浏览器中运行,按F12,可以看到APPlication选项下的indexedDB中多了一​​个新创建的数据库“testDB”,version为1,log为建库成功时回调打印的日志打开,说明建库成功。 打开:

这里写图片描述

3.关闭并删除数据库

关闭数据库可以直接调用数据库对象的close方法。 我们在DBmanager中添加一个成员函数:

//关闭数据库的方法
closeDB() {
    this.currentDB.close();
    console.log(this.currentDB.name + ' database is already closed!');
}

要删除数据库,请使用 indexedDB 对象的 deleteDatabase 方法。 我们在DBmanager中添加一个成员函数:

//删除数据库的方法
deleteDB() {
    window.indexedDB.deleteDatabase(this.DBname);
    console.log(this.DBname + ' database is already deleted!');
}

由于是异步API,不保证在调用closeDB方法时一定会通过openDB获取到DB对象,所以我们这里使用setTimeout进行延时,保证获取到DB对象后关闭数据库。

window.onload = function () {
    var db = new DBmanager('testDB', 1);
    db.openDB();
    setTimeout(function () {
        db.closeDB();
        db.deleteDB();
    }, 500);
}

运行后在控制台可以看到输出日志

4.对象存储

在关系型数据库中,我们以表的形式存储数据,但indexedDB中并没有表的概念,而是对象存储。 一个数据库中可以有多个object store,一个object store相当于一张表,可以存储多种数据类型,每种数据类型对应一个Key值。 我们可以指定一个字段作为Key值,或者自动生成Key值,或者指定。 例如,在下面的例子中,我们在onupgradeneed 中新建一个名为“students”的对象存储,并指定“id”作为键值。

request.onupgradeneeded = function (e) {
    console.log('database version is already upgrade to '+this.DBversion);
    this.currentDB = e.target.result;
    if(!this.currentDB.objectStoreNames.contains('students')){
        //指定一个键为主键
        this.currentDB.createObjectStore('students',{keyPath:"id"});
        //指定为主键自增模式
        //db.createObjectStore('students',{autoIncrement: true});
    }
}.bind(this);

5.交易

关系数据库中也有事务的概念,但是这里的事务和关系数据库中的事务不一样。 在indexedDB中,在对数据库中的数据进行增删改查之前,需要先启动一个事务。 在事务中,指定需要操作的那些对象存储。 获取到对应的对象库后,我们就可以对获取到的对象库进行操作了。 这里我们在DBmanager中添加一个成员函数,根据object store的名称启动一个事务,并获取对应的object store:

//根据storeName获取对应store的方法
getStoreByName(storeName){
    var transaction = this.currentDB.transaction(storeName,'readwrite');
    return transaction.objectStore(storeName);
}

其中,交易有三种模式:

只读:只读,不能修改数据库数据,可并发读写:可进行readwrite,读写操作 版本变更:verionchange

6.添加数据

我们在调用createObjectStore方法时创建了一个名为students的对象存储,并指定主键为id。 现在我们可以向商店添加数据,我们准备一些数据:

//名为students的ObjectStore

html文本编辑内容存储到数据库_python 数据转html库_数据库存储html代码

const datas=[{ id:11, name:"zhangsan", age:24 },{ id:12, name:"lisi", age:30 },{ id:13, name:"wangwu", age:26 },{ id:14, name:"zhaoliu", age:26 }];

然后我们添加一个用于向DBmanager添加数据的成员函数:

//添加数据的方法
addData(storeName,data){
    var store = this.getStoreByName(storeName);
    for(var i = 0; i<data.length ; i++){
        store.add(data[i]);
    }
}

转移:

window.onload = function () {
    var db = new DBmanager('testDB', 2);
    db.openDB();
    setTimeout(function () {
        db.addData('students',datas);
        db.closeDB();
    }, 500);
}

打开chromium浏览器,我们可以看到我们在indexedDB中添加的数据:

这里写图片描述

7.删除数据

删除一条数据:

//删除一条数据(根据主键key(id))
deleteDataByKey(storeName,key){
    var store = this.getStoreByName(storeName);
    store.delete(key);
}

删除所有数据:

//删除整个ObjectStore的数据
deleteAllData(storeName){
    var store = this.getStoreByName(storeName);
    store.clear();
}

是否删除成功可以运行后在chromium浏览器中验证

8.更新数据

这里写一个根据key值更新age值的方法供参考:

//根据键值修改数据
updateDataByKey(storeName,key,age){
    var store = this.getStoreByName(storeName);
    var request = store.get(key);
    request.onsuccess = function (e) {
        var student = e.target.result;
        student.age = age;
        store.put(student);
    }
}

转移:

window.onload = function () {
    var db = new DBmanager('testDB', 1);
    db.openDB();
    setTimeout(function () {
        db.updateDataByKey('students',11,25);
        db.closeDB();
    }, 500);
}

这样,store store id为11的数据对应的age值就变成了25。

9.查找数据

根据id值查询对应的姓名和年龄:

//根据键值查询数据
getDataByKey(storeName,key){
    var store = this.getStoreByName(storeName);
    var request = store.get(key);
    request.onsuccess = function (e) {
        var student = e.target.result;
        console.log('key is '+key+',name:'+student.name+',age:'+student.age);
    }
}

10.索引

以上介绍了indexedDB的基本使用。 接下来介绍indexedDB的索引。 索引的优点是可以快速定位数据,提高查找速度。indexedDB中有两种索引,一种是自增的int值,由indexedDB自己定义; 另一个是keyPath,这个是我们自己指定的,下面重点介绍keyPath索引的使用

11.索引

可以在创建object store的时候指定索引,使用object store的createIndex创建索引,有三个参数

例子:我们为name和age这两个属性创建对应的索引,onupgradeneeded可以这样写:

request.onupgradeneeded = function (e) {

数据库存储html代码_html文本编辑内容存储到数据库_python 数据转html库

console.log('database version is already upgrade to '+this.DBversion); this.currentDB = e.target.result; if(!this.currentDB.objectStoreNames.contains('students')){ //指定一个键为主键 var store = this.currentDB.createObjectStore('students',{keyPath:"id"}); //指定为主键自增模式 //db.createObjectStore('students',{autoIncrement: true}); store.createIndex('nameIndex','name',{unique:true}); store.createIndex('ageIndex','age',{unique:false}); } }.bind(this);

索引建立成功后,可以在chromium中看到对应的索引:

这里写图片描述

12.根据索引查询数据

//根据索引查询数据
getDataByIndex(storeName,indexName,index){
    var store = this.getStoreByName(storeName);
    var indexStore = store.index(indexName);
    var request = indexStore.get(index);
    request.onsuccess = function (e) {
        var student = e.target.result;
        console.log('index is '+index+',id:'+student.id+',age:'+student.age);
    }
}

比如我们要查询nameIndex为zhangsan的数据:

db.getDataByIndex('students','nameIndex','zhangsan');

13.游标游标

indexedDB中索引和游标的使用密不可分。 如果查询结果是多条数据,我们可以使用游标来遍历查询结果:

//通过游标获取所有数据
fetchStoreByCurser(storeName) {
    var store = this.getStoreByName(storeName);
    var request = store.openCursor();
    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            var currentStudent = cursor.value;
            console.log('currentStudent:' + currentStudent.name);
            //curson.contine()会使游标下移,直至没有数据则返回undefined
            cursor.continue();
        }
    }
}

14.游标与索引联合查询

//通过游标和index查询
getMultipleData(storeName, indexName, age) {
    var store = this.getStoreByName(storeName);
    var indexStore = store.index(indexName);
    var request = indexStore.openCursor(IDBKeyRange.only(age));
    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            var student = cursor.value;
            console.log(student.name);
            cursor.continue();
        }
    };
}

比如我们要查询年龄为26岁的所有数据:

db.getMultipleData('students', 'ageIndex', 26);

15.指定光标范围

index.openCursor()/index.openKeyCursor() 方法在不传参的情况下会获取对象存储的所有记录。 像上面的例子,我们可以过滤搜索

可以使用key range来限制游标中值的范围,将其作为第一个参数传递给openCursor()或openKeyCursor()

例如:

//指定游标范围查询
getDataBetweenTwoData(storeName,indexName,start,end,isStartOpen,isEndOpen) {
    var store = this.getStoreByName(storeName);
    var indexStore = store.index(indexName);
    //true是不包括,false是包括
    var request = indexStore.openCursor(IDBKeyRange.bound(start, end, isStartOpen, isEndOpen));
    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            var student = cursor.value;
            console.log(student.name);
            cursor.continue();
        }
    }
}

比如查询年龄在24到30之间的所有数据,包括24,不包括30,可以这样查:

db.getDataBetweenTwoData('students','ageIndex',24,30,false,true);

16.获取商店中存储条目的总数

getStoreDataCount(storeName) {
    var store = this.getStoreByName(storeName);
    var req = store.count();
    req.onsuccess = function (e) {
        console.log(e.target.result);
    }
}

17、获取店铺中满足多个条件的条目总数

数据库存储html代码_html文本编辑内容存储到数据库_python 数据转html库

多条件前提下的查询,首先要有多条件查询的索引。 由于数据有限,我们会创建一个由name和age组成的多条件索引,在onupgradeneeded中,为'students:创建一个索引:

store.createIndex('myIndex',['name','age'],{unique:false});

然后我们写一个函数:

//获取store中满足多个条件的条目的总数
getDataCountByMultiCondition(storeName,indexName,condition) {
    var store = this.getStoreByName(storeName)
    var indexStore = store.index(indexName);
    var request = indexStore.openCursor(IDBKeyRange.only(condition));
    request.onsuccess = function (e) {
        var cursor = e.target.result;
        if (cursor) {
            var student = cursor.value;
            console.log(student.id);
            cursor.continue();
        }
    }
}

然后查询名为“lisi”且年龄为30的所有数据:

db.getDataCountByMultiCondition('students','myIndex',['lisi',30]);

18.如何获取返回值

在上面的例子中,我们获取到的数据在函数中是用到用日志打印出结果的,但是在实际中,我们需要获取到其他地方的查询结果数据库存储html代码,但是在请求的回调中,我们无法得到结果直接作为函数返回值返回给函数调用者,这里也使用callback来传递获取的值。 例如,我们重写获取商店存储商品总数的方法:

//获取某个store中存储条目的总数
fetchStoreDataCount(storeName,callback) {
    var count = 0;
    var store = this.getStoreByName(storeName);
    var req = store.count();
    req.onsuccess = function (e) {
        count = e.target.result;
        callback(count);
    }
}

其中callback是一个回调函数,我们用callback传递返回值:

db.fetchStoreDataCount('students',function (count) {
    console.log(count);
});

这样数据库存储html代码,我们就可以使用回调来传递任何查询得到的值。 你可以尝试用这个方法把上面查询到的所有数据都传过去。 你只需要在调用的地方实现回调函数即可。

19.其他

可能有同学注意到,在openDB的方法中,在请求的onsuccess、onerror、onupgradeneeded之后添加了.bind(this)。 原因如下:

因为我是用ES6中的类来实现整个DBmanager的,但是js中的this和java中的this并不完全一样,指的是当前对象,比如这里:request的onsuccess,onerror和onupgradeneeded回调函数这里不指的是DBmanager对象,但是为了请求,所以为了改变DBmanager要改变onsuccess中的成员变量的值,指向DBmanager的this值被绑定到onsuccess。

另外,在DBmanager的实现过程中,为了方便,没有使用get和set方法来获取和设置成员变量的值,很多地方需要进一步改进。 这里只是给大家一个简单的参考。 欢迎批评指正。

20.源代码

indexedDB.html:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<script>
    class DBmanager {
        //数据库管理类的构造函数,包含两个构造参数,数据库名称和数据库版本,数据库版本如果不指定默认为1;
        constructor(DBname, DBversion) {
            this.DBname = DBname;
            this.DBversion = DBversion || 1;
            this.currentDB = null; //当前数据库
        }
        //打开(没有创建过则创建)数据库
        openDB() {
            //调用API打开数据库
            var request = window.indexedDB.open(this.DBname, this.DBversion);
            //打开数据库失败的回调
            request.onerror = function (e) {
                console.log(e.currentTarget.error.message);
            }.bind(this);
            //打开数据库成功的回调
            request.onsuccess = function (e) {
                this.currentDB = e.target.result;
                console.log(this.currentDB.name + ' database is already opened!');
            }.bind(this);
            //数据库升级的回调,此回调在数据库版本变化时和数据库第一次创建时执行
            request.onupgradeneeded = function (e) {
                console.log('database version is already upgrade to ' + this.DBversion);
                this.currentDB = e.target.result;
                if (!this.currentDB.objectStoreNames.contains('students')) {
                    //指定一个键为主键
                    var store = this.currentDB.createObjectStore('students', {keyPath: "id"});
                    //指定为主键自增模式
                    //db.createObjectStore('students',{autoIncrement: true});
                    store.createIndex('nameIndex', 'name', {unique: false});
                    store.createIndex('ageIndex', 'age', {unique: false});
                    store.createIndex('myIndex', ['name', 'age'], {unique: false});
                }
            }.bind(this);
        }
        //关闭数据库
        closeDB() {

html文本编辑内容存储到数据库_python 数据转html库_数据库存储html代码

this.currentDB.close(); console.log(this.currentDB.name + ' database is already closed!'); } //删除数据库 deleteDB() { window.indexedDB.deleteDatabase(this.DBname); console.log(this.DBname + ' database is already deleted!'); } //根据storeName获取对应store的方法 getStoreByName(storeName) { var transaction = this.currentDB.transaction(storeName, 'readwrite'); return transaction.objectStore(storeName); } //添加数据 addData(storeName, data) { var store = this.getStoreByName(storeName); for (var i = 0; i < data.length; i++) { store.add(data[i]); } } //根据键值修改数据 updateDataByKey(storeName, key, age) { var store = this.getStoreByName(storeName); var request = store.get(key); request.onsuccess = function (e) { var student = e.target.result; student.age = age; store.put(student); } } //根据键值查询数据 getDataByKey(storeName, key) { var store = this.getStoreByName(storeName); var request = store.get(key); request.onsuccess = function (e) { var student = e.target.result; console.log('key is ' + key + ',name:' + student.name + ',age:' + student.age); } } //根据索引查询数据 getDataByIndex(storeName, indexName, index) { var store = this.getStoreByName(storeName); var indexStore = store.index(indexName); var request = indexStore.get(index); request.onsuccess = function (e) { var student = e.target.result; console.log('index is ' + index + ',id:' + student.id + ',age:' + student.age); } } //通过游标获取所有数据 fetchStoreByCurser(storeName) { var store = this.getStoreByName(storeName); var request = store.openCursor(); request.onsuccess = function (e) { var cursor = e.target.result; if (cursor) { var currentStudent = cursor.value; console.log('currentStudent:' + currentStudent.name); //curson.contine()会使游标下移,直至没有数据则返回undefined cursor.continue(); } } } //通过游标和index查询 getMultipleData(storeName, indexName, age) { var store = this.getStoreByName(storeName); var indexStore = store.index(indexName); var request = indexStore.openCursor(IDBKeyRange.only(age)); request.onsuccess = function (e) { var cursor = e.target.result; if (cursor) { var student = cursor.value; console.log(student.name); cursor.continue(); } }; } //指定游标范围查询 getDataBetweenTwoData(storeName, indexName, start, end, isStartOpen, isEndOpen) { var store = this.getStoreByName(storeName);

数据库存储html代码_html文本编辑内容存储到数据库_python 数据转html库

var indexStore = store.index(indexName); //true是不包括,false是包括 var request = indexStore.openCursor(IDBKeyRange.bound(start, end, isStartOpen, isEndOpen)); request.onsuccess = function (e) { var cursor = e.target.result; if (cursor) { var student = cursor.value; console.log(student.name); cursor.continue(); } } } //获取某个store中存储条目的总数 getStoreDataCount(storeName) { var store = this.getStoreByName(storeName); var req = store.count(); req.onsuccess = function (e) { console.log(e.target.result); } } //获取store中满足多个条件的条目的总数 getDataCountByMultiCondition(storeName, indexName, condition) { var store = this.getStoreByName(storeName) var indexStore = store.index(indexName); var request = indexStore.openCursor(IDBKeyRange.only(condition)); request.onsuccess = function (e) { var cursor = e.target.result; if (cursor) { var student = cursor.value; console.log(student.id); cursor.continue(); } } } //获取某个store中存储条目的总数 fetchStoreDataCount(storeName, callback) { var count = 0; var store = this.getStoreByName(storeName); var req = store.count(); req.onsuccess = function (e) { count = e.target.result; callback(count); } } } //名为students的ObjectStore const datas = [{ id: 11, name: "zhangsan", age: 24 }, { id: 12, name: "lisi", age: 30 }, { id: 13, name: "wangwu", age: 26 }, { id: 14, name: "zhaoliu", age: 26 },]; window.onload = function () { var db = new DBmanager('testDB', 4); db.openDB(); setTimeout(function () { // db.getDataCountByMultiCondition('students','myIndex',['lisi',30]); // db.getDataBetweenTwoData('students','ageIndex',24,30,false,true); // db.getMultipleData('students', 'ageIndex', 26); // db.fetchStoreByCurser('students'); // db.getDataByIndex('students','nameIndex','zhangsan'); // db.addData('students',datas); // db.getDataByKey('students',11); db.fetchStoreDataCount('students', function (count) { console.log(count); }); db.closeDB(); // db.deleteDB(); }, 500); }
script> body> html>