美文网首页Vue.js开发技巧ES6的基础知识前端
ES6(六)用Class + Promise封装一下Web SQ

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

作者: 自然框架 | 来源:发表于2021-03-19 17:49 被阅读0次

    Web SQL

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

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

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

    打开数据库

    要说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实在太不放心了,维护起来也感觉忒麻烦。

    对了,还得写个删除表和库的函数,F12也没有个删除的功能。

    相关文章

      网友评论

        本文标题:ES6(六)用Class + Promise封装一下Web SQ

        本文链接:https://www.haomeiwen.com/subject/nrfbcltx.html