偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

前端要革命?看我在 JS 里寫(xiě) SQL

新聞 前端
在日新月異的前端領(lǐng)域中,前端工程師能做的事情越來(lái)越多,自從nodejs出現(xiàn)后,前端越來(lái)越有革了傳統(tǒng)后端命的趨勢(shì),本文就再補(bǔ)一刀,詳細(xì)解讀如何在js代碼中執(zhí)行標(biāo)準(zhǔn)的SQL語(yǔ)句

在日新月異的前端領(lǐng)域中,前端工程師能做的事情越來(lái)越多,自從nodejs出現(xiàn)后,前端越來(lái)越有革了傳統(tǒng)后端命的趨勢(shì),本文就再補(bǔ)一刀,詳細(xì)解讀如何在js代碼中執(zhí)行標(biāo)準(zhǔn)的SQL語(yǔ)句

為什么要在JS里寫(xiě)SQL?

隨著業(yè)務(wù)復(fù)雜度的增長(zhǎng),前端頁(yè)面可能出現(xiàn)一些數(shù)據(jù)邏輯復(fù)雜的頁(yè)面,傳統(tǒng)的js邏輯處理起來(lái)比較復(fù)雜,我們先看兩個(gè)例子:

比如多規(guī)格多庫(kù)存商品界面,難點(diǎn)在于顏色分類(lèi)、尺碼、價(jià)格、庫(kù)存、限購(gòu)數(shù)量以及對(duì)應(yīng)的圖片展示之間有復(fù)雜的邏輯關(guān)系,用戶(hù)進(jìn)行不同的選擇時(shí),js要經(jīng)過(guò)多次復(fù)雜的查詢(xún)才能算出結(jié)果

比如地區(qū)聯(lián)動(dòng)查詢(xún)界面,難點(diǎn)在于:

  1. 如何在本地存儲(chǔ)地區(qū)數(shù)據(jù),顯然每次拉接口是不現(xiàn)實(shí)的,如果存儲(chǔ)在storage里,每次使用時(shí),需要有類(lèi)似JSON.parse類(lèi)的字符串轉(zhuǎn)化為數(shù)組或?qū)ο蟮倪^(guò)程,這個(gè)操作在數(shù)據(jù)量大的時(shí)候,會(huì)造成頁(yè)面卡頓,性能極差

  2. 三級(jí)地區(qū)聯(lián)動(dòng)查詢(xún)復(fù)雜,如果要從一個(gè)縣級(jí)地區(qū)查詢(xún)到所屬的城市和省份,邏輯會(huì)比較復(fù)雜

上面兩個(gè)例子,如果用傳統(tǒng)js邏輯來(lái)寫(xiě),大家頭腦中必定已經(jīng)設(shè)計(jì)好了算法,免不了用forEach、filter、some、find等各種ES678新方法,筆者開(kāi)始也是用了各種酷炫的新方法寫(xiě)出來(lái)發(fā)現(xiàn)有兩個(gè)問(wèn)題:

  1. 寫(xiě)完之后邏輯很復(fù)雜,似乎沒(méi)有100行代碼實(shí)現(xiàn)不了(當(dāng)然有大神比我活兒好)

  2. 即使寫(xiě)了一大堆注釋?zhuān)聜兛雌饋?lái)還是一頭霧水(因?yàn)檫壿嫶_實(shí)很復(fù)雜。。。)

筆者做過(guò)一段時(shí)間php開(kāi)發(fā)(還做過(guò)PM、UI、QA等)忽然想能不能用SQL的方式實(shí)現(xiàn)呢?經(jīng)過(guò)一番研究,筆者寫(xiě)了這樣一個(gè)庫(kù):

Database.js

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

Web SQL Database是WHATWG(Web 超文本應(yīng)用技術(shù)工作組,HTML5草案提出方)在2008 年 1 月提出的***份正式草案,但并未包含在 HTML 5 規(guī)范之中,它是一個(gè)獨(dú)立的規(guī)范,它引入了一套使用 SQL 操作客戶(hù)端數(shù)據(jù)庫(kù)的 API。由于提出時(shí)間較早,盡管 W3C 官方在 2011 年 11 月聲明已經(jīng)不再維護(hù) Web SQL Database 規(guī)范,但這些 API 已經(jīng)被廣泛的實(shí)現(xiàn)在了不同的瀏覽器里,尤其是手機(jī)端瀏覽器。

兼容情況

Web SQL Database 和 Indexed Database有啥區(qū)別?

Indexed Database 更類(lèi)似于 NoSQL 的形式來(lái)操作數(shù)據(jù)庫(kù) , 其中最重要的是 Indexed Database 不使用 SQL 作為查詢(xún)語(yǔ)言。

筆者為了實(shí)現(xiàn)在js里面寫(xiě)SQL的需求,果斷采用了前者作為底層技術(shù)。

Web SQL Database 三個(gè)核心方法:

  • openDatabase:這個(gè)方法使用現(xiàn)有數(shù)據(jù)庫(kù)或新建數(shù)據(jù)庫(kù)來(lái)創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象

  • transaction:這個(gè)方法允許我們根據(jù)情況控制事務(wù)提交或回滾

  • executeSql:這個(gè)方法用于執(zhí)行SQL 查詢(xún)

代碼示例:

   var db = openDatabase('testDB', '1.0', 'Test DB', 2 * 1024 * 1024);

   var msg;

   db.transaction(function (context) {

      context.executeSql('CREATE TABLE IF NOT EXISTS testTable (id unique, name)');

      context.executeSql('INSERT INTO testTable (id, name) VALUES (0, "Byron")');

      context.executeSql('INSERT INTO testTable (id, name) VALUES (1, "Casper")');

      context.executeSql('INSERT INTO testTable (id, name) VALUES (2, "Frank")');

    });

`對(duì)于沒(méi)有SQL經(jīng)驗(yàn)的前端同學(xué)來(lái)講,上面代碼看起來(lái)顯然有點(diǎn)陌生,也不太友好,于是Database.js誕生了:

筆者以業(yè)務(wù)當(dāng)中的一個(gè)需求舉例: 轉(zhuǎn)轉(zhuǎn)游戲業(yè)務(wù)列表頁(yè) 篩選菜單是一個(gè)三級(jí)聯(lián)動(dòng)菜單,每個(gè)菜單變動(dòng)都會(huì)影響其他菜單數(shù)據(jù),如圖:

[[206332]]

原始JSON數(shù)據(jù)結(jié)構(gòu)

可以看出是3級(jí)嵌套結(jié)構(gòu),筆者處理成了扁平化的數(shù)據(jù)結(jié)構(gòu)(過(guò)程略),并分別存入三個(gè)數(shù)據(jù)庫(kù),分別存儲(chǔ)游戲名稱(chēng)、游戲平臺(tái)、商品類(lèi)型,如下圖:

舉例游戲名稱(chēng)數(shù)據(jù)結(jié)構(gòu)如下圖:

通過(guò)chrome控制臺(tái)Application面板可以直接看到數(shù)據(jù)庫(kù),結(jié)構(gòu)、數(shù)據(jù)清晰可見(jiàn)

核心代碼如下:

    /**

      * 打開(kāi)數(shù)據(jù)庫(kù)

      * @returns {Promise.<void>}

      */

     openDataBase(){

       //打開(kāi)數(shù)據(jù)庫(kù),沒(méi)有則創(chuàng)建

       db.openDatabase('GameMenu',1,'zzOpenGameMenu').then(res=>{

         //檢測(cè)數(shù)據(jù)庫(kù)是否存在

         db.isExists('game').then(res=>{

           //數(shù)據(jù)庫(kù)已經(jīng)存在,直接使用,將數(shù)據(jù)交付給頁(yè)面UI組件

           this.setSelectData()

         }).catch(e=>{

           //數(shù)據(jù)庫(kù)不存在,請(qǐng)求接口并處理數(shù)據(jù),然后存入數(shù)據(jù)庫(kù)

           this.getData()

         })

       }).catch(e=>{

         console.err(e)

       })

     },

    /**

      * 獲取分類(lèi)數(shù)據(jù)并存儲(chǔ)到數(shù)據(jù)庫(kù)

      * @returns {Promise.<void>}

      */

     async getData(){

       //接口請(qǐng)求數(shù)據(jù)并處理成三個(gè)扁平數(shù)組

       let data =  await this.getMenuData()

       for(let i in data){

         //創(chuàng)建表并存儲(chǔ)數(shù)據(jù)

         db.create(i,data[i])

       }

       //將數(shù)據(jù)交付給頁(yè)面UI組件

       this.setSelectData()

     },

當(dāng)任意菜單選擇變更時(shí),三列數(shù)據(jù)將重新查詢(xún),核心代碼如下:

    /**

      * 重新查詢(xún)數(shù)據(jù)

      * @param data 點(diǎn)擊菜單攜帶的數(shù)據(jù)

      * @param index 點(diǎn)擊菜單的序號(hào)

      * @param all 三個(gè)菜單當(dāng)前選中數(shù)據(jù)

      */

    async onSelect(data,index,all){

       let target = [],condition = {}

       //業(yè)務(wù)邏輯:處理查詢(xún)條件

       if(all['0'] && all['0']['name']!=defaultData[0].default.name)condition['gameName'] =all['0']['name']

       if(all['1'] && all['1']['name']!=defaultData[1].default.name)condition['platName'] =all['1']['name']

       if(all['2'] && all['2']['name']!=defaultData[2].default.name)condition['typeName'] =all['2']['name']

 

       //創(chuàng)建三個(gè)查詢(xún)?nèi)蝿?wù)

       let tasks = ['game','plat','type'].map((v,k)=>{

           //使用db.select方法查詢(xún)

           return db.select(v,this.formatCondition(v,condition),'name,value','rowid desc','name').then((res)=>{

             target.push({

               options:res.data,

               defaultOption:defaultData[k].default,

               clickHandle:this.onSelect

             })

           })

       })

     //執(zhí)行查詢(xún)

     await Promise.all(tasks)

       //將數(shù)據(jù)交付給聯(lián)動(dòng)菜單組件使用

       this.selectData = target

     }

以上代碼即可完成聯(lián)動(dòng)菜單所需要的數(shù)據(jù)管理工作,看起來(lái)是不是比較清晰?

使用Database.js的優(yōu)勢(shì)

1.將數(shù)據(jù)結(jié)構(gòu)化存儲(chǔ)于Storage中,避免了以文本形式存入Storage或cookie中再解析的性能消耗流程。

2.將復(fù)雜數(shù)據(jù)清晰的在前端進(jìn)行管理和使用,代碼邏輯更清晰,數(shù)據(jù)查詢(xún)更簡(jiǎn)潔!

Database.js使用文檔

openDatabase

  • 功能:打開(kāi)數(shù)據(jù)庫(kù),不存在則創(chuàng)建

  • 語(yǔ)法:openDatabase(dbName,dbVersion,dbDescription,dbSize,callback)

  • 參數(shù):

    • dbName:數(shù)據(jù)庫(kù)名

    • dbVersion:數(shù)據(jù)庫(kù)版本(打開(kāi)已存在數(shù)據(jù)庫(kù)時(shí),版本號(hào)必須一致,否則會(huì)報(bào)錯(cuò))

    • dbDescription:數(shù)據(jù)庫(kù)描述

    • dbSize:數(shù)據(jù)庫(kù)預(yù)設(shè)大小,默認(rèn)1M

    • callback:回調(diào)函數(shù)

query

  • 功能:執(zhí)行sql語(yǔ)句,支持多表查詢(xún)

  • 語(yǔ)法:query(sqlStr,args = [],callback,errorCallback)

  • 參數(shù):

    • sqlStr:sql語(yǔ)句

    • args(Array):傳入的數(shù)據(jù),替換sql中的?符號(hào)

    • callback:成功回調(diào)

    • errorCallback:失敗回調(diào)

  • 示例:

   //插入數(shù)據(jù)

   db.query('INSERT INTO testTable(id,title) VALUES (?,?)',[1,'這是title'])

 

   //多表查詢(xún)

   db.query('select game.*,plat.* from game left join plat on game.name = plat.gameName')

isExists

  • 功能:檢測(cè)表是否存在

  • 語(yǔ)法:isExists(tableName)

  • 參數(shù):

    • tableName:表名

createTable

  • 功能:創(chuàng)建一張表

  • 語(yǔ)法:createTable(tableName,fields)

  • 參數(shù):

    • tableName:表名

    • fields:表結(jié)構(gòu)(需指定字段類(lèi)型)

  • 示例:

   db.createTable('testTable',{

       name:'varchar(200)',

       price:'int(100)'

   })

insert

  • 功能:插入一條或多條數(shù)據(jù)

  • 語(yǔ)法:insert(tableName,data)

  • 參數(shù):

    • tableName:表名

    • data(Object or Array):插入的數(shù)據(jù),多條數(shù)據(jù)請(qǐng)傳入數(shù)組類(lèi)型

  • 示例:

   //插入單條

   db.insert('testTable',{

       name:'商品1',

       price:10

   })

   //插入多條

   db.insert('testTable',[

       {name:'商品1',price:10},

       {name:'商品2',price:20},

       {name:'商品3',price:30},

   ])

將數(shù)據(jù)存入數(shù)據(jù)庫(kù)的常規(guī)流程是先createTable,然后再insert,如果你覺(jué)得這樣麻煩,可以試一下create方法:

create

  • 功能:直接創(chuàng)建數(shù)據(jù)庫(kù)并存入數(shù)據(jù)

  • 注意:類(lèi)庫(kù)會(huì)根據(jù)傳入的數(shù)據(jù)類(lèi)型自動(dòng)設(shè)置數(shù)據(jù)庫(kù)的字段類(lèi)型,這樣可以覆蓋大多數(shù)需求,但如果你的數(shù)據(jù)中,同一個(gè)字段中有不同的數(shù)據(jù)類(lèi)型,有可能不能兼容,建議還是使用常規(guī)流程手動(dòng)設(shè)置類(lèi)型

  • 語(yǔ)法:create(tableName,data)

  • 參數(shù):

    • tableName:表名

    • data(Object or Array):插入的數(shù)據(jù),多條數(shù)據(jù)請(qǐng)傳入數(shù)組類(lèi)型

  • 示例:

   //直接創(chuàng)建表并存儲(chǔ)

   db.create('testTable',[

       {name:'商品1',price:10},

       {name:'商品2',price:20},

       {name:'商品3',price:30},

   ])

delete

  • 功能:刪除數(shù)據(jù)

  • 語(yǔ)法:delete(tableName,condition)

  • 參數(shù):

    • tableName:表名

    • condition(String or Obejct):查詢(xún)條件

  • 示例:

   //刪除一條數(shù)據(jù)

   db.delete('testTable',{name:'商品1'})

關(guān)于condition: 1、傳入array形式時(shí),默認(rèn)查詢(xún)條件連接方式是AND,如果需要用OR等方式,可以在condition中傳入 logic設(shè)定,例如{ logic:'OR'} 2、如果查詢(xún)條件有AND、OR等多種方式,建議使用string方式傳入

select

  • 功能:查詢(xún)數(shù)據(jù)

  • 注意:如果需要多表查詢(xún),可參照query方法

  • 語(yǔ)法:select(tableName,condition = '',fields = '*',order = '',group = '',limit = '')

  • 參數(shù):

    • tableName:表名

    • condition(String or Obejct):查詢(xún)條件

    • fields(String or Array):返回字段,默認(rèn)*,支持distinct

    • order(String or Array):排序規(guī)則

    • group(String or Array):分組規(guī)則

    • limit(String or Array):分頁(yè)規(guī)則

  • 示例:

   //查詢(xún)name=商品1的數(shù)據(jù),并按照price倒序

   db.select('testTable',{

         name:'商品1'

     },'*','price desc')

 

   //查詢(xún)價(jià)格大于0的商品,并用distinct關(guān)鍵字去重

   db.select('testTable',{

         price:'>0'

     },'distinct name,pirce','price desc')

update

  • 功能:更新數(shù)據(jù)

  • 語(yǔ)法:update(tableName,data,condition = '')

  • 參數(shù):

    • tableName:表名

    • data(String or Obejct):更改數(shù)據(jù)

    • condition(String or Obejct):查詢(xún)條件

  • 示例:

   //將商品1的價(jià)格改為99

   db.update('testTable',{

         price:99

     },{

         name:'商品1'

   })

truncate

  • 功能:清空表

  • 語(yǔ)法:truncate(tableName)

  • 參數(shù):

    • tableName:表名

drop

  • 功能:刪除表

  • 語(yǔ)法:drop(tableName)

  • 參數(shù):

    • tableName:表名

如何使用Database.js

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

如果你有更好的想法,歡迎與我交流,個(gè)人微信號(hào):king109400214

責(zé)任編輯:張燕妮 來(lái)源: king109400214
相關(guān)推薦

2022-03-13 23:26:29

JavaScript編程語(yǔ)言開(kāi)發(fā)

2013-08-20 09:36:40

易信革命前行

2021-09-16 09:38:12

開(kāi)發(fā)項(xiàng)目代碼

2022-11-14 21:34:17

2023-03-17 16:02:36

2022-10-30 17:32:25

設(shè)計(jì)模式單例模式

2023-10-30 07:13:56

2018-12-04 13:30:28

Javascript編譯原理前端

2011-05-25 17:17:54

前端開(kāi)發(fā)

2022-06-28 10:58:48

協(xié)議通信加密

2023-04-26 08:43:28

GoCGO語(yǔ)言

2022-08-23 08:53:31

Go項(xiàng)目語(yǔ)言

2020-07-31 13:35:34

Node.js應(yīng)用分析前端

2025-07-01 10:00:00

forEachawait

2017-01-16 13:26:39

2017寫(xiě)前端

2017-06-12 10:50:20

2012-12-20 09:28:18

2015-10-15 09:53:46

SQL恢復(fù)

2023-08-21 11:44:20

2020-06-27 09:09:38

物聯(lián)網(wǎng)遠(yuǎn)程工作IOT
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)