前者要革命?看我在js里写SQL

 

于日新月异的前端领域受到,前端工程师能召开的作业越多,自从nodejs出现后,前端越来越有革了传统后端命的趋向,本文就还上一刀片,详细解读如何在js代码中实践正式的SQL语句

缘何而在js里描写SQL?

就业务复杂度的提高,前端页面可能出现局部数码逻辑复杂的页面,传统的js逻辑处理起来比较复杂,我们先行押片独例证:

图片 1

本多规格多库存商品界面,难点在颜色分类、尺码、价格、库存、限购数量以及对应之图形显示中有复杂的逻辑关系,用户展开不同之选项时,js要由此数扑朔迷离的询问才会算是有结果

图片 2

遵地区联动查询界面,难点在:

  1. 什么当地头存储地区数据,显然每次拉接口是不具体的,如果存储在storage里,每次用时,需要出像样JSON.parse类的字符串转化为数组或对象的过程,这个操作以数据量大的时,会招致页面卡顿,性能极差
  2. 三级地区联动查询复杂,如果要是自一个县级地域查询到所属的城与省区,逻辑会比较复杂

面两独例,如果因此传统js逻辑来写,大家头脑中一定已经规划好了算法,免不了用forEach、filter、some、find等各种ES678新措施,笔者开始也是为此了各种酷炫的新办法勾勒出来发现产生有限只问题:

  1. 描绘了事后逻辑很复杂,似乎没100行代码实现无了(当然发大神比较自己活好)
  2. 哪怕写了平充分堆注释,同事等看起或一头雾水(因为逻辑确实十分复杂。。。)

作者做了一段时间php开发(还召开了PM、UI、QA等)忽然想能不能够就此SQL的方法贯彻为?经过一番研究,笔者写了这么一个仓房:

Database.js

Database.js基于Web SQL Database,那么Web SQL Database又是啥?

Web SQL Database是WHATWG(Web
超文本以技术工作组,HTML5草案提出方)在2008 年 1
月提出的第一客正经草案,但没有包含在 HTML 5
规范中,它是一个独立的科班,它引入了同一套使用 SQL 操作客户端数据库的
API。由于提出时间较早,尽管 W3C 官方在 2011 年 11 月声称已经不再维护
Web SQL Database 规范,但这些 API
已经为普遍的实现在了不同之浏览器里,尤其是手机端浏览器。

相当情况 图片 3

Web SQL Database 和 Indexed Database有何区别?

Indexed Database 更仿佛于 NoSQL 的款式来操作数据库 , 其中最为着重的凡
Indexed Database 不使用 SQL 作为查询语言。

作者为贯彻在js里面写SQL的需求,果断采取了前者作为底层技术。

Web SQL Database 三只基本措施:

  • openDatabase:这个法以现有数据库或新建数据库来创造数据库对象
  • transaction:这个艺术允许我们根据气象决定工作提交或回滚
  • executeSql:这个方法用于实施SQL 查询

代码示例:

1 var db = openDatabase('testDB', '1.0', 'Test DB', 2 * 1024 * 1024);
2     var msg;
3     db.transaction(function (context) {
4        context.executeSql('CREATE TABLE IF NOT EXISTS testTable (id unique, name)');
5        context.executeSql('INSERT INTO testTable (id, name) VALUES (0, "Byron")');
6        context.executeSql('INSERT INTO testTable (id, name) VALUES (1, "Casper")');
7        context.executeSql('INSERT INTO testTable (id, name) VALUES (2, "Frank")');
8      });

 

于尚未SQL经验的前端同学来讲,上面代码看起肯定有些陌生,也不顶友好,于是Database.js诞生了:

作者为工作中的一个急需举例: 逛游戏业务列表页淘菜单是一个三级联动菜单,每个菜单变动都见面潜移默化其他菜单数据,如图:

图片 4

原始JSON数据结构

图片 5

得看到是3级嵌套结构,笔者处理成了扁平化的数据结构(过程略),并分别存入三只数据库,分别存储游戏名称、游戏平台、商品种类,如下图:

图片 6

举例来说游戏名称数据结构如下图:

图片 7

透过chrome控制台Application面板可以直接看看数据库,结构、数据清晰可见

核心代码如下:

 1   /**
 2        * 打开数据库
 3        * @returns {Promise.<void>}
 4        */
 5       openDataBase(){
 6         //打开数据库,没有则创建
 7         db.openDatabase('GameMenu',1,'zzOpenGameMenu').then(res=>{
 8           //检测数据库是否存在
 9           db.isExists('game').then(res=>{
10             //数据库已经存在,直接使用,将数据交付给页面UI组件
11             this.setSelectData()
12           }).catch(e=>{
13             //数据库不存在,请求接口并处理数据,然后存入数据库
14             this.getData()
15           })
16         }).catch(e=>{
17           console.err(e)
18         })
19       },
20      /**
21        * 获取分类数据并存储到数据库
22        * @returns {Promise.<void>}
23        */
24       async getData(){
25         //接口请求数据并处理成三个扁平数组
26         let data =  await this.getMenuData()
27         for(let i in data){
28           //创建表并存储数据
29           db.create(i,data[i])
30         }
31         //将数据交付给页面UI组件
32         this.setSelectData()
33       },

 

当任意菜单选择改变时,三列数据以再查询,核心代码如下:

 1 /**
 2        * 重新查询数据
 3        * @param data 点击菜单携带的数据
 4        * @param index 点击菜单的序号
 5        * @param all 三个菜单当前选中数据
 6        */
 7       async onSelect(data,index,all){
 8         let target = [],condition = {}
 9         //业务逻辑:处理查询条件
10         if(all['0'] && all['0']['name']!=defaultData[0].default.name)condition['gameName'] = all['0']['name']
11         if(all['1'] && all['1']['name']!=defaultData[1].default.name)condition['platName'] = all['1']['name']
12         if(all['2'] && all['2']['name']!=defaultData[2].default.name)condition['typeName'] = all['2']['name']
13 
14         //创建三个查询任务
15         let tasks = ['game','plat','type'].map((v,k)=>{
16             //使用db.select方法查询
17             return db.select(v,this.formatCondition(v,condition),'name,value','rowid desc','name').then((res)=>{
18               target.push({
19                 options:res.data,
20                 defaultOption:defaultData[k].default,
21                 clickHandle:this.onSelect
22               })
23             })
24         })
25         //执行查询
26         await Promise.all(tasks)
27         //将数据交付给联动菜单组件使用
28         this.selectData = target
29       }

 

上述代码即可完成联动菜单所欲之数管理工作,看起是未是较明晰?


使用Database.js的优势

1.将数据结构化存储于Storage中,避免了因为文件形式存入Storage或cookie中另行分析的特性消耗流程。

2.以复杂数据清晰的在前者进行管理以及应用,代码逻辑又清楚,数据查询更简洁!

Database.js使用文档

openDatabase

  • 效果:打开数据库,不有则创造
  • 语法:openDatabase(dbName,dbVersion,dbDescription,dbSize,callback)
  • 参数:
    • dbName:数据库名
    • dbVersion:数据库版本(打开都是数据库时,版本号必须同,否则会报错)
    • dbDescription:数据库描述
    • dbSize:数据库预设大小,默认1M
    • callback:回调函数

query

  • 职能:执行sql语句,支持多表查询
  • 语法:query(sqlStr,args = [],callback,errorCallback)
  • 参数:
    • sqlStr:sql语句
    • args(Array):传入的多少,替换sql中的?符号
    • callback:成功回调
    • errorCallback:失败回调
  • 示例:

    1   //插入数据
    2   db.query('INSERT INTO testTable(id,title) VALUES (?,?)',[1,'这是title'])
    3 
    4   //多表查询
    5  db.query('select game.*,plat.* from game left join plat on game.name = plat.gameName')
    

     

isExists

  • 成效:检测表是否留存
  • 语法:isExists(tableName)
  • 参数:
    • tableName:表名

createTable

  • 成效:创建同张表
  • 语法:createTable(tableName,fields)
  • 参数:
    • tableName:表名
    • fields:表结构(需点名字段类型)
  • 示例:

    1   db.createTable('testTable',{
    2       name:'varchar(200)',
    3       price:'int(100)'
    4   })
    

     

insert

  • 功用:插入一漫漫或多修数
  • 语法:insert(tableName,data)
  • 参数:
    • tableName:表名
    • data(Object or Array):插入的多寡,多久数请求传入数组类型
  • 示例: javascript //插入单条 db.insert('testTable',{ name:'商品1', price:10 }) //插入多条 db.insert('testTable',[ {name:'商品1',price:10}, {name:'商品2',price:20}, {name:'商品3',price:30}, ])

以数据存入数据库的例行流程是优先createTable,然后再insert,如果你认为这样麻烦,可以试试一下create方法:

create

  • 效益:直接创造数据库并存入数据
  • 瞩目:类库会根据传入的数据类型自动安装数据库的字段类型,这样好挂大多数要求,但倘若你的数目被,同一个字段中发生差的数据类型,有或无克匹配,建议要采取正规流程手动设置类型
  • 语法:create(tableName,data)
  • 参数:
    • tableName:表名
    • data(Object or Array):插入的数据,多久数请求传入数组类型
  • 示例:

    1   //直接创建表并存储
    2   db.create('testTable',[
    3     {name:'商品1',price:10},
    4     {name:'商品2',price:20},
    5     {name:'商品3',price:30},
    6   ])
    

     

delete

  • 功用:删除数据
  • 语法:delete(tableName,condition)
  • 参数:
    • tableName:表名
    • condition(String or Obejct):查询条件
  • 示例:

    1 //删除一长数
    2 db.delete(‘testTable’,{name:’商品1′})

 

关于condition: 1、传入array形式时,默认查询条件连接方式是AND,如果要为此OR等措施,可以于condition中传出logic设定,例如{logic:’OR’} 2、如果查询条件来AND、OR等多计,建议下string方式传入

select

  • 作用:查询数据
  • 留意:如果欲差不多表查询,可参考query方法
  • 语法:select(tableName,condition = ”,fields = ‘*’,order = ”,group
    = ”,limit = ”)
  • 参数:
    • tableName:表名
    • condition(String or Obejct):查询条件
    • fields(String or Array):返回字段,默认*,支持distinct
    • order(String or Array):排序规则
    • group(String or Array):分组规则
    • limit(String or Array):分页规则
  • 示例:

    1 //查询name=商品1的数据,并按照price倒序
    2   db.select('testTable',{
    3         name:'商品1'
    4     },'*','price desc')
    5 
    6   //查询价格大于0的商品,并用distinct关键字去重
    7   db.select('testTable',{
    8         price:'>0'
    9     },'distinct name,pirce','price desc')
    

     

**update**
- 功能:更新数据
- 语法:update(tableName,data,condition = '')
- 参数:
    - tableName:表名
    - data(String or Obejct):更改数据
    - condition(String or Obejct):查询条件
- 示例:

1       //将商品1的价格改为99
2       db.update('testTable',{
3             price:99
4         },{
5             name:'商品1'
6         })

 

truncate

  • 功能:清空表
  • 语法:truncate(tableName)
  • 参数:
    • tableName:表名

drop

  • 功能:删除表
  • 语法:drop(tableName)
  • 参数:
    • tableName:表名

什么采取Database.js

Github地址:https://github.com/zhangsuoyong/Database.js

若是你产生再好的想法,欢迎和己交流,个人微信号:king109400214

重复多前端非常文章,请关注我司公众号“大转转FE”

 

如你喜欢我们的文章,关注我们的大众号与我们彼此吧。

图片 8

网站地图xml地图