ES6(六)用Class + Promise封装一下Web SQL

简介: 用Class + Promise封装一下Web SQL

Web SQL



首先呢,HTML5已经放弃了 Web SQL,这里做这个封装,主要是为了练手,另外是为了做在线演示。


后端一般都采用关系型数据库,有些关于sql语句的在线演示就需要弄个后端,但是成本比较高,那么如果能够用前端的websql模仿一下,是不是可以呢?


因为都是用sql语句,基础的操作方式还是相同的,介绍一下原理没啥问题,所以呢,并不是真的要在项目里面使用,对于websql目前初步的感受来说,挺麻烦的。。。


打开数据库



要说webSQL还真是简单,或者说是简陋,就是开库,事务,提交SQL语句,然后就没了,剩下的自由发挥吧。


那么还是简单的封装一下。


/**
 * webSQL 的封装,基于 promise 便于操作
 * * 建立数据库
 * * 封装sql实现增删改查
 */
export default class webSQLHelp {
  constructor (dbName, ver, description) { // constructor是一个构造方法,用来接收参数
    this.dbName = dbName // this代表的是实例对象
    this.ver = ver
    this.description = description
    this.db = window.openDatabase(this.dbName, this.ver, this.description, 2 * 1024 * 1024)
  }
  /**
   * 打开指定的webSQL数据库
   * @returns 数据库的实例
   */
  openDb () {
    return this.db
  }
  ...
}
复制代码


先体验一下ES6 的 class(不是TS的),果然和 function 没啥大的区别,初始化传入参数打开数据库,备用。 好像把数据库名称记录下来似乎也没啥大用。


建立表



然后用建表语句建立表,看了一下资料,似乎也不用设置字段的类型,那么就简单一点,根据对象的属性来建立一个表。


/**
   * 创建表
   * @param { string } tableName 表名
   * @param { object } columns 表的对象,比如{name:'jyk', age: 12}
   * @returns 成功或者失败
   */
  createTable (tableName, columns) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称,不设置类型了。
      const cols = []
      for (const key in columns) {
        cols.push(key)
      }
      const sql = `CREATE TABLE IF NOT EXISTS ${tableName}
        (ID INTEGER PRIMARY KEY ASC, ${cols.join(',')} )`
      console.log('createSQL:', sql)
      // 调用事务,建立表
      this.db.transaction((tx) => {
        tx.executeSql(sql, [], (tx, results) => {
          console.log(tx, results)
          resolve(results)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


用 Promise 代替回调的方式。传入表名和对象,然后创建建表的SQL,提交建表搞定。


这里想实现 那种 表名.insert()的形式,但是水平有限,没弄出来。


添加数据



/**
   * 插入数据
   * @param { string } tableName 表名
   * @param { object } object 保存的对象
   * @returns 新增的ID值
   */
  insert (tableName, object) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称
      const colNames = []
      // 记录字段对应的值
      const colValues = []
      // 记录字段对应的占位符合
      const cols = []
      // 变量对象,记录 key和 value
      for (const key in object) {
        colNames.push(key)
        // colValues.push('"' + object[key] + '"')
        colValues.push(object[key])
        cols.push('?')
      }
      const sql = `INSERT INTO ${tableName}
        ( ${colNames.join(',')} ) VALUES ( ${cols.join(',')} )`
      console.log('insertSQL:', sql)
      this.db.transaction((tx) => {
        tx.executeSql(sql, colValues, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者
          resolve(results.insertId)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


还是传入表名和对象,然后生成 insert 的SQL语句,提交添加搞定。


修改数据



/**
   * 修改数据
   * @param { String } tableName 表名
   * @param { Object } object 要修改的对象值
   * @param { Number } idValue 修改依据,id 的值
   * @returns 修改影响的行数
   */
  update (tableName, object, idValue) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称
      const colNames = []
      // 记录字段对应的值
      const colValues = []
      // 变量对象,记录 key和 value
      for (const key in object) {
        colNames.push(key + '=? ')
        colValues.push(object[key])
      }
      // 加入查询条件
      colValues.push(idValue)
      const sql = `UPDATE ${tableName} SET ${colNames.join(',')} WHERE id=?`
      console.log('updateSQL:', sql)
      console.log('updateSQL2:', colValues)
      this.db.transaction((tx) => {
        tx.executeSql(sql, colValues, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rowsAffected)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


一样,改改SQL就好。另外需要加一个where 的条件,否则就都删掉了。


删除数据



/**
   * 删除一条记录
   * @param { String } tableName 表名
   * @param { Number } idValue 删除依据
   * @returns 删除状态
   */
  delete (tableName, idValue) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      const sql = `DELETE FROM ${tableName} WHERE id=?`
      console.log('deleteSQL:', sql)
      this.db.transaction((tx) => {
        tx.executeSql(sql, [idValue], (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rowsAffected)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


这个最简单了,delete一下就好。


查询数据



/**
   * 查询数据
   * @param { string } tableName 要查询的表名
   * @param { object } showCols 显示字段
   * @param { object } query 查询条件
   * @returns 查询结果,数组形式
   */
  select (tableName, showCols, query) {
    this.findKind = {
      // 字符串
      401: ' {col} = ? ',
      402: ' {col} <> ? ',
      403: ' {col} like ? ',
      404: ' {col} not like ? ',
      405: ' {col} like ? ', // 起始于
      406: ' {col} like ? ', // 结束于
      // 数字
      411: ' {col} = ? ',
      412: ' {col} <> ? ',
      413: ' {col} > ? ',
      414: ' {col} >= ? ',
      415: ' {col} < ? ',
      416: ' {col} <= ? ',
      417: ' {col} between ? and ? ',
      // 日期
      421: ' {col} = ? ',
      422: ' {col} <> ? ',
      423: ' {col} > ? ',
      424: ' {col} >= ? ',
      425: ' {col} < ? ',
      426: ' {col} <= ? ',
      427: ' {col} between ? and ? ',
      // 范围
      441: ' {col} in (?)'
    }
    const promise = new Promise((resolve, reject) => {
      const _whereCol = []
      const _whereValue = []
      for (const key in query) {
        const val = query[key]
        _whereCol.push(this.findKind[val[0]].replace('{col}', key))
        switch (val[0]) {
          case 403: // like
          case 404: // not like
            _whereValue.push('%' + val[1] + '%')
            break
          case 405: // like a%
            _whereValue.push(val[1] + '%')
            break
          case 406: // like %a
            _whereValue.push('%' + val[1])
            break
          case 417: // between 数字
          case 427: // between 日期
            _whereValue.push(...val[1])
            break
          case 441: // in
            _whereCol[_whereCol.length - 1] =
              _whereCol[_whereCol.length - 1]
                .replace('?', val[1].map(a => '?').join(','))
            _whereValue.push(...val[1])
            break
          default:
            _whereValue.push(val[1])
            break
        }
      }
      if (_whereCol.length === 0) {
        _whereCol.push(' 1=1 ')
      }
      const sql = `SELECT * FROM ${tableName} WHERE ${_whereCol.join(' and ')}`
      console.log('selectSQL1:', sql)
      console.log('selectSQL2:', _whereValue)
      this.db.transaction((tx) => {
        tx.executeSql(sql, _whereValue, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rows)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


好吧,其实主要就是为了这个查询,这不在做查询控件么,演示的时候,还是有个数据变化来得更生动一些,但是有没钱弄后端服务器。于是就用websql代替一下吧。


这里设置了一个查询结构,这个 select 就是把这个查询结构解析成SQL语句,然后交给数据库执行,看看查询效果。


使用方法



在vue环境下使用


import WebSqlHelp from '@/store-nf/websql-help.js'
export default {
  name: 'websql',
  components: {
  },
  setup (props, ctx) {
    const help = new WebSqlHelp('db-findtest', '1.0', '演示一下查询控件')
    console.log(help)
    const person = {
      name: 'jyk',
      age: 18,
      brithday: '1970-1-1',
      aa: {
        a1: 'a111',
        a2: 'a222'
      }
    }
    const sqlCreate = () => {
      // 依据 person 建立一个表
      help.createTable('person3', person).then(() => {
        // 往表里面加数据
        help.insert('person3', person).then((id) => {
          console.log('newId', id)
        })
      })
    }
    const zsgc = () => {
      // 修改指定的数据
      person.age = 111
      help.update('person3', person, 3).then((id) => {
        console.log('updateId', id)
      })
      // 删除指定的数据
      help.delete('person3', 4).then((id) => {
        console.log('deleteId', id)
      })
    }
    const dataList = reactive([])
    const sqlSelect = () => {
      // 查询数据
      help.select('person3', {}, {
        // id: [401, 2]
      }).then((data) => {
        console.log('select:', data)
        dataList.length = 0
        dataList.push(...data)
      })
    }
    return {
      sqlCreate,
      sqlSelect,
      dataList
    }
  }
}
复制代码


  • 嵌套对象


默认只支持单层属性,套娃是不支持的,直会存入 “[object Object]” 这个东东。 这里只是简单的演示,就不做转换了。


  • 多表关联


没考虑那么复杂,因为没打算演示这些复杂的操作,头疼。就简单粗暴的演示一下单表查询就好。 同理,分组统计这类的也不考虑。


总结



发现好多小问题,前端嘛,还是用 indexedDB 的好,用webSQL实在太不放心了,维护起来也感觉忒麻烦。


可以删除表,但是听说不能删除数据库?那难道只能等360清理?


相关文章
|
1月前
|
前端开发 JavaScript 测试技术
ES6:什么是Promise?
ES6:什么是Promise?
15 0
|
2月前
|
前端开发 小程序 JavaScript
es6读书笔记(五)Promise
es6读书笔记(五)Promise
|
4月前
|
XML 编解码 前端开发
【web组件库系列】封装自己的字体图标库
【web组件库系列】封装自己的字体图标库
59 0
|
10天前
|
JavaScript 前端开发
【Web 前端】 jQuery 里的 ID 选择器和 class 选择器有何不同?
【5月更文挑战第1天】【Web 前端】 jQuery 里的 ID 选择器和 class 选择器有何不同?
|
12天前
|
前端开发 JavaScript
ES6:Promise使用方法解析大全
ES6:Promise使用方法解析大全
|
23天前
|
SQL 安全 Go
如何在 Python 中进行 Web 应用程序的安全性管理,例如防止 SQL 注入?
在Python Web开发中,确保应用安全至关重要,主要防范SQL注入、XSS和CSRF攻击。措施包括:使用参数化查询或ORM防止SQL注入;过滤与转义用户输入抵御XSS;添加CSRF令牌抵挡CSRF;启用HTTPS保障数据传输安全;实现强身份验证和授权系统;智能处理错误信息;定期更新及审计以修复漏洞;严格输入验证;并培训开发者提升安全意识。持续关注和改进是保证安全的关键。
20 0
|
1月前
|
SQL 安全 PHP
CTF--Web安全--SQL注入之Post-Union注入
CTF--Web安全--SQL注入之Post-Union注入
|
2月前
|
SQL 安全 数据库
在Python Web开发过程中:安全性与编码规范,如何确保用户输入数据的安全性,避免SQL注入?
防止 SQL 注入的关键措施包括使用参数化查询、验证清理用户输入、预处理语句、避免动态 SQL、实施访问控制、保持安全编码习惯和定期审计。结合使用 WAF 和安全框架可增强防护。开发人员的安全意识同样重要。
19 2
|
2月前
|
SQL 安全 测试技术
如何在 Python 中进行 Web 应用程序的安全性管理,例如防止 SQL 注入?
如何在 Python 中进行 Web 应用程序的安全性管理,例如防止 SQL 注入?
18 0
|
3月前
|
SQL 开发框架 .NET
ASP.NET Web——GridView完整增删改查示例(全篇幅包含sql脚本)大二结业考试必备技能
ASP.NET Web——GridView完整增删改查示例(全篇幅包含sql脚本)大二结业考试必备技能
37 0