JSON數據存儲和瀏覽器數據存儲

一、JSON

1.JSON的由來

  • 在目前的開發(fā)中,JSON是一種非常重要的數據格式,它并不是編程語言,而是一種可以在服務器和客戶端之間傳輸的數據格式。

  • JSON的全稱是 JavaScript Object Notation(JavaScript對象符號):

    • JSON是由Douglas Crockford構想和設計的一種輕量級資料交換格式,算是JavaScript的一個子集。
    • 但是雖然JSON被提出來的時候是主要應用JavaScript中,但是目前已經獨立于編程語言,可以在各個編程語言中使用。
    • 很多編程語言都實現了將JSON轉成對應模型的方式。
  • 其他的傳輸格式:

    • XML:在早期的網絡傳輸中主要是使用XML來進行數據交換的,但是這種格式在解析、傳輸等各方面都弱于JSON,所以目前已經很少在被使用了。
    • Protobuf:另外一個在網絡傳輸中目前已經越來越多使用的傳輸格式是protobuf,但是直到2021年的3.x版本才支持JavaScript,所以目前在前端使用的較少。
  • 目前JSON被使用的應用場景也越來越多

    • 網絡數據的傳輸JSON數據。
    • 項目的某些配置文件。
      • 小程序的 app.json文件
    • 非關系型數據庫(NoSQL)將json作為存儲格式。

2.JSON的基本語法

  • JSON文件的后綴名是.json

  • JSON的頂層支持三種類型的值:

    • 簡單值:數字(Number)、字符串(String,不支持單引號)、布爾類型(Boolean)、null類型
    • 對象值:由key、value組成,key是字符串類型,并且必須添加雙引號,值可以是簡單值、對象值、數組值
    • 數組值:數組的值可以是簡單值、對象值、數組值。
  • JSON不能有注釋

  • JSON不能有多余的逗號

3.JSON序列化

  • 某些情況下我們希望將JavaScript中復雜類型轉化成JSON格式的字符串,這樣方便對其進行處理。
    • 比如我們希望將一個對象保存到localStorage中
    • 但是如果我們直接存放一個對象,這個對象會被轉化成 [object Object]格式的字符串,并不是我們想要的結果。
const obj={
  name:"wjy",
  age:18,
  friends:{
    name:"hyz"
  },
  hobbies:["籃球","足球"]
}

// 將對象數據存儲在localStorage中
// * 因為localStorage的第二個參數也是需要傳字符串類型,所以會先將對象類型轉化為string類型 
localStorage.setItem("obj",obj);

// * 取出存儲的值
console.log(localStorage.getItem("obj"));//[object Object]

在瀏覽器中的 顯示 [object Object]

image-20220522203839374.png
  • 通過JSON.stringify()將對象轉化為JSON字符串。
  • 通過JSON.parse()將JSON字符串解析為一個對象

3.1 序列化JSON.stringify的細節(jié)

  • 可以傳入第二個參數

    • 可以是數組
      • 在數組可以指定哪些屬性需要進行轉換
    • 也可以是一個回調函數
      • 會回調每個key-value
  • 也可以傳入第三個參數

    • 是對字符串進行美化
    • 可以傳入數字或字符串
      • 數字n:會在key使用n個空格
      • 字符串:會在key前面添加傳入的字符串
const obj={
  name:"wjy",
  age:18,
  friends:{
    name:"hyz"
  },
  hobbies:["籃球","足球"],
}

// * 需求:將上面的對象轉成JSON字符串
// * 1. 直接轉化
const jsonString1=JSON.stringify(obj)

console.log(jsonString1); // {"name":"wjy","age":18,"friends":{"name":"hyz"},"hobbies":["籃球","足球"]}

// * 2.stringify第二個參數replacer
// * 2.1 傳入數組:設定哪些是需要轉換的。
const jsonString2=JSON.stringify(obj,["name","friends"])
console.log(jsonString2);// {"name":"wjy","friends":{"name":"hyz"}}

// * 2.2 傳入一個回調函數:會遍歷每個key value
// 年齡虛歲要加1
const jsonString3=JSON.stringify(obj,(key,value)=>{
  if(key=="age") return value+1;
  return value;
})

console.log(jsonString3);//{"name":"wjy","age":19,"friends":{"name":"hyz"},"hobbies":["籃球","足球"]}

// *3 stringify有第三個參數 space:可以是數字或者字符串
const jsonString4=JSON.stringify(obj,null,2)
console.log(jsonString4);

// {
//   "name": "wjy",
//   "age": 18,
//   "friends": {
//     "name": "hyz"
//   },
//   "hobbies": [
//     "籃球",
//     "足球"
//   ]
// }

// * 4.如果轉換的對象有toJSON這個函數,會直接使用這個函數的返回值
// const jsonString5=JSON.stringify(obj);
// console.log(jsonString5);

3.2 序列化JSON.parse細節(jié)

  • 它可以傳入第二個參數
    • 一個回調函數,可以進行對key-value進行攔截
const JSONString='{"name":"wjy","age":19,"friends":{"name":"hyz"},"hobbies":["籃球","足球"]}';

// * 第二個參數可以對值進行攔截
const info=JSON.parse(JSONString,(key,value)=>{
  if(key=="age") return value-1;
  return value
});
console.log(info);

3.3 實現深拷貝

  • 賦值:引用的是同一片空間
  • 淺拷貝:只是拷貝第一層屬性的值
  • 深拷貝:兩個對象之間完全沒有關系,JSON.stringify和JSON.parse實現深拷貝存在一些缺陷
const obj={
  name:"wjy",
  age:18,
  friends:{
    name:"hyz"
  },
  hobbies:["籃球","足球"],
  foo(){
    console.log("foo函數");
  }
}

// * 將obj對象的內容放到info變量中
// * 1. 引用賦值
const info=obj


// * 淺拷貝:只是將里面的屬性拷貝了一份,

/**
 * * Object.assign()
 */
const info2={...obj};
console.log(info2==obj); //false
info2.age=100;
console.log("obj的age:",obj.age);
info2.hobbies[0]="吃零食";
console.log("obj的hobbies:",obj.hobbies);

// * 深拷貝 :讓兩個對象完全沒有關系 
// * 使用JSON.stringify和JSON.parse,但是對函數是無能為力的
const info3=JSON.parse(JSON.stringify(obj))
info3.friends.name="tqy";
console.log(obj.friends.name);
console.log(info3);

二、瀏覽器的存儲方案

1.認識Storage

  • WebStorage主要提供了一種機制,可以讓瀏覽器提供一種比cookie更直觀的key、value存儲方式:
    • localStorage:本地存儲,提供的是一種永久性的存儲方法,在關閉掉網頁重新打開時,存儲的內容依然保留。
    • sessionStorage:會話存儲,提供的是本次會話的存儲,在關閉掉會話時,存儲的內容會被清除。
image-20220522232723625.png

1.1 localStorage和sessionStorage有什么區(qū)別

  • 我們會發(fā)現localStorage和sessionStorage看起來非常的相似。
  • 那么它們有什么區(qū)別呢?
    • 驗證一:關閉網頁后重新打開,localStorage會保留,sessionStorage不會保留
    • 驗證二:在頁面內實現跳轉,localStorage會保留,sessionStorage也會保留
    • 驗證三:在頁面外實現跳轉(打開新的網頁),localStorage會保留,sessionStorage不會保留。

1.2 Storage常見的方法和屬性

適用于localStorage和sessionStorage

Storage具有如下的屬性和方法

  • 屬性

    • Storage.length:只讀屬性
      • 返回一個整數,表示存儲在Storage對象中的數據項數量。
  • 方法

    • Storage.key():該方法接受一個數值n作為參數,返回存儲中第n個key名稱。

    • Storage.getItem():該方法接受一個key作為參數,并且返回key對應的value。

    • Storage.setItem():該方法接受一個key和value,并且將會key和value添加到存儲中。

      • 如果key存儲,則更新對應的值。
    • Storage.removeItem():該方法接受一個key作為參數,并把該key對應的value從存儲中刪除。

    • Storage.clear():該方法的作用是清空存儲中的所有key。

1.3 封裝Storage

class JYCache{
  constructor(isLocal=true){
    this.storage=isLocal?localStorage:sessionStorage;
  }

  setItem(key,value){
    if(value){
      this.storage.setItem(key,JSON.stringify(value))
    }
  }

  getItem(key){
    let value=this.storage.getItem(key);
    if(value){
      value=JSON.parse(value);
    }
    return value;
  }

  key(index){
    return this.storage.key(index);
  }

  removeItem(key){
    this.storage.removeItem(key);
  }

  length(){
    return this.storage.length;
  }

}

const localCache=new JYCache();
const sessionCache=new JYCache(false);

export {
  localCache,
  sessionCache
}

2. IndexedDB

  • 什么是IndexDB呢?

    • 我們能看到DB這個詞,就說明它其實是一種數據庫(Database),通常情況下在服務器端比較常見。
    • 在實際的開發(fā)中,大量的數據都是存儲在數據庫的,客戶端主要是請求這些數據并且展示。
    • 有時候我們可能會存儲一些簡單的數據到本地(瀏覽器中),比如token、用戶名、密碼、用戶信息等,比較少存儲大量的數據。
    • 那么如果確實有大量的數據需要存儲,這個時候可以選擇使用IndexDB
  • IndexedDB是一種底層的API,用于在客戶端存儲大量的結構化數據。

    • 它是一種事務型數據庫系統(tǒng),是一種基于JavaScript面向對象數據庫,有點類似于NoSQL(非關系型數據庫)
      • 事務是對數據庫進行操作的時候一個操作單元
    • IndexDB本身就是基于事務的,我們只需要指定數據庫模式,打開與數據庫的連接,然后檢索和更新一系列事務即可。

key是一個個數值型,value是一個個對象

2.1 IndexedDB的連接數據庫

  • 第一步:打開indexedDB的某一個數據庫。
    • 通過indexedDB.open(數據庫名稱,數據庫版本)方法。
    • 如果數據庫不存在,那么會創(chuàng)建這個數據庫。
    • 如果數據庫已經存在,那么會打開這個數據庫。
// * 打開數據庫,和數據庫建立連接
// * 有wjy數據庫就打開,沒有就會創(chuàng)建。
const dbRequest=indexedDB.open("wjy",2)
let db=null;
// * 數據庫連接失敗
dbRequest.onerror=function(err){
  console.log("數據庫連接失敗");
}

dbRequest.onsuccess=function(event){
  db=event.target.result;
  // console.log("數據庫連接成功");
}

// * 第一次打開 或者版本發(fā)生更新
dbRequest.onupgradeneeded=function(event){
  const db=event.target.result;

  // * 創(chuàng)建一些存儲對象
  // * keyPath:設置表的主鍵 ,例如users的主鍵是id
  db.createObjectStore("users",{keyPath:"id"})
}

class User{
  constructor(id,name,age){
    this.id=id;
    this.name=name;
    this.age=age;
  }
}

const users=[
  new User(100,"wjy",20),
  new User(101,"hyz",20),
  new User(102,"tqy",20),
]

// 獲取btns ,監(jiān)聽點擊
const btns=document.querySelectorAll("button")
for(let i=0;i<btns.length;i++){
  btns[i].onclick=function(){
    console.log("db:",db);
    // * 創(chuàng)建一個事務
    const transaction=db.transaction(["users"],"readwrite")
    console.log("transaction:",transaction);
    // * 獲取一個具體的store對象
    const store=transaction.objectStore("users");
    switch(i){
      case 0:
        console.log("點擊了新增");
        for(const user of users){
          const request=store.add(user);
          request.onsuccess=function(){
            console.log(`${user.name}插入成功`);
          }
        }
        transaction.oncomplete=function(){
          console.log("添加操作全部完成");
        }
        break;
      case 1:
        // * 查詢方式一:store.get() (知道主鍵,根據主鍵查詢)
        // console.log("點擊了查詢");
        // const request=store.get(100);
        // request.onsuccess=function(event){
        //   console.log(event.target.result);
        // }

        // * 查詢方式二
        const request=store.openCursor()
       request.onsuccess=function(event){
         const cursor=event.target.result;
         if(cursor){
           if(cursor.key==101)
           {
            console.log(cursor.key,cursor.value);
           }else cursor.continue()
         }else{
           console.log("查詢完成");
         }
       }
        break;
      case 2:
        const request2=store.openCursor()
        request2.onsuccess=function(event){
          const cursor=event.target.result;
          if(cursor){
            if(cursor.key==101)
            {
              cursor.delete()
            }else cursor.continue()
          }else{
            console.log("查詢完成");
          }
        }
        console.log("點擊了刪除");
        break;
      case 3:
        const deleteRequest=store.openCursor()
        deleteRequest.onsuccess=function(event){
          const cursor=event.target.result;
          if(cursor){
            if(cursor.key==101)
            {
              const value=cursor.value;
              value.name="curry"
              cursor.update(value)
             console.log(cursor.key,cursor.value);
            }else cursor.continue()
          }else{
            console.log("查詢完成");
          }
        }
        console.log("點擊了修改");
        break;
    }
  }
}

三、總結

JSON的數據存儲和瀏覽器的數據存儲.png
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容