亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript利用normalizr實現(xiàn)復雜數據轉換

 更新時間:2022年07月25日 15:17:07   作者:jump__jump  
當我們需要進行數據轉換以便拆分和維護時,可以使用redux作者 Dan Abramov 編寫的normalizr來處理數據,本文將為大家詳細講講其用法,感興趣的可以了解一下

筆者曾經開發(fā)過一個數據分享類的小程序,分享邏輯上類似于百度網盤。當前數據可以由被分享者加工然后繼續(xù)分享(可以控制數據的過期時間、是否可以加工數據以及繼續(xù)分享)。

分享的數據是一個深度嵌套的 json 對象。在用戶讀取分享數據時存入小程序云數據庫中(分享的數據和業(yè)務數據有差異,沒使用業(yè)務服務器進行維護)。如果拿到數據就直接存儲的話,很快云數據庫就會變得很大,其次我們也沒辦法分析各項和檢索各項子數據給予分享者。

這時候需要進行數據轉換以便拆分和維護。我們可以使用 redux 作者 Dan Abramov 編寫的 normalizr 來處理數據。

normalizr 創(chuàng)立的初衷是處理深層,復雜的嵌套的對象。

如何使用

稍微修改一下官方的例子,假定獲取到如下書籍的數據:

{
  id: "1",
  title: "JavaScript 從入門到放棄",
  // 作者
  author: {
    id: "1",
    name: "chc"
  },
  // 評論
  comments: [
    {
      id: "1",
      content: "作者寫的太好了",
      commenter: {
        id: "1",
        name: "chc"
      }
    },
     {
      id: "2",
      content: "樓上造假數據哈",
      commenter: {
        id: "2",
        name: "dcd"
      }
    },
  ]
}

這時候我們可以寫出 3 個主體: 書籍信息、評論以及用戶。我們先從基礎的數據來構造模式:

import { normalize, schema } from 'normalizr';

// 構造第一個實體 用戶信息
const user = new schema.Entity('users');

// 構造第二個實體 評論
const comment = new schema.Entity('comments', {
  // 評價者是用戶
  commenter: user
});

// 構造第三個實體 書籍
const book = new schema.Entity('books', {
  // 作者
  author: user,
  // 評論
  comments: [comment]
});

// 傳入數據以及當前最大的 schema 信息
const normalizedData = normalize(originalData, book);

先來看一下最終數據。

{
  "entities": {
    "users": {
      "1": {
        "id": "1",
        "name": "chc"
      },
      "2": {
        "id": "2",
        "name": "dcd"
      }
    },
    "comments": {
      "1": {
        "id": "1",
        "content": "作者寫的太好了",
        "commenter": "1"
      },
      "2": {
        "id": "2",
        "content": "樓上造假數據哈",
        "commenter": "2"
      }
    },
    "books": {
      "1": {
        "id": "1",
        "title": "JavaScript 從入門到放棄",
        "author": "1",
        "comments": [
          "1",
          "2"
        ]
      }
    }
  },
  "result": "1"
}

去除其他信息,我們可以看到獲取了 3 個不同的實體對象, users,comments,books。對象的鍵為當前 id,值為當前平鋪的數據結構。這時候我們就可以使用對象或者數組(Object.values) 來新增和更新數據。

解析邏輯

看到這里,大家可能是很懵的。先不管代碼實現(xiàn),這里先分析一下庫是如何解析我們編寫的 schema 的,以便大家可以在實際場景中使用,再看一遍數據和 schema 定義:

數據結構

{
  id: "1",
  title: "JavaScript 從入門到放棄",
  // 作者
  author: {
    id: "1",
    name: "chc"
  },
  // 評論
  comments: [
    {
      id: "1",
      content: "作者寫的太好了",
      commenter: {
        id: "1",
        name: "chc"
      }
    },
     {
      id: "2",
      content: "樓上造假數據哈",
      commenter: {
        id: "2",
        name: "dcd"
      }
    },
  ]
}

書籍信息是第一層對象,數據中有 id, title, author, comments,對應 schema 如下

const book = new schema.Entity('books', {
  // 作者
  author: user,
  // 一本書對應多個評論,所以這里使用數組
  comments: [comment]
});

其中 id ,title 是 book 本身的屬性,無需關注,把需要解析的數據結構寫出來。books 字符串與解析無關,對應 entities 對象的 key。

再看 user

const user = new schema.Entity('users');

user 沒有需要解析的信息,直接定義實體即可。

最后是評論信息

const comment = new schema.Entity('comments', {
  // 評價者是用戶
  commenter: user
});

{
  id: "1",
  content: "作者寫的太好了",
  commenter: {
    id: "1",
    name: "chc"
  }
}

把 comments 從原本的數據結構中拿出來,實際也就很清晰了。

高階用法

處理數組

normalizr 可以解析單個對象,那么如果當前業(yè)務傳遞數組呢?類似于 comment 直接這樣使用即可:

[
  {
    id: '1',
    title: "JavaScript 從入門到放棄"
    // ...
  },
  {
    id: '2',
    // ...
  }
]

const normalizedData = normalize(originalData, [book]);

反向解析

我們只需要拿到剛才的 normalizedData 中的 result 以及 entities 就可以獲取之前的信息了。

import { denormalize, schema } from 'normalizr';

//...

denormalize(normalizedData.result, book, normalizedData.entities);

Entity 配置

開發(fā)中可以根據配置信息重新解析實體數據。

const book = new schema.Entity('books', {
  // 作者
  author: user,
  // 一本書對應多個評論,所以這里使用數組
  comments: [comment]
}, {
  // 默認主鍵為 id,否則使用 idAttribute 中的數據,如 cid,key 等
  idAttribute: 'id',
  // 預處理策略, 參數分別為 實體的輸入值, 父對象
  processStrategy: (value, parent, key) => value,
  // 遇到兩個id 相同數據的合并策略,默認如下所示,我們還可以繼續(xù)修改
  mergeStrategy: (prev, prev) => ({
    ...prev,
    ...next,
    // 是否合并過,如果遇到相同的,就會添加該屬性
    isMerge: true
  }),
});

// 看一下比較復雜的例子,以 user 為例子
const user = new schema.Entity('users', {
}, {
  processStrategy: (value, parent, key) => {
    // 增加父對象的屬性
    // 例如 commenter: "1" => commenterId: "1" 或者 author: "2" => "authorId": "2"
    // 但是目前還無法通過 delete 刪除 commenter 或者 author 屬性
    parent[`${key}Id`] = value.id

    // 如果是從評論中獲取的用戶信息就增加 commentIds 屬性
    if (key === 'commenter') { 
      return {
        ...value, 
        commentIds: [parent.id] 
      } 
    }
    // 不要忘記返回 value, 否則不會生成 user 數據
    return {
      ...value,
      bookIds: [parent.id]
    };
  }
  mergeStrategy: (prev, prev) => ({
    ...prev,
    ...next,
    // 該用戶所有的評論歸并到一起去
    commentIds: [...prev.commentIds, ...next.commentIds],
    // 該用戶所有的書本歸并到一起去
    bookIds: [...prev.bookIds, ...next.bookIds],
    isMerge: true
  }),
})

// 最終獲取的用戶信息為
{
  "1": {
    "id": "1",
    "name": "chc"
    // 用戶 chc 寫了評論和書籍,但是沒有進行過合并
    "commentIds": ["1"],
    "bookIds": ["1"],
  },
  "2": {
    "id": "2",
    "name": "dcd",
    // 用戶 dcd 寫了 2 個評論,同時進行了合并處理
    "commentIds": [
      "2",
      "3"
    ],
    "isMerge": true
  }
}

當然了,該庫也可以進行更加復雜的數據格式化,大家可以通過 api 文檔 來進一步學習和使用。

其他

當然了,normalizr 使用場景畢竟有限,開源負責人也早已換人。目前主庫已經無人維護了(issue 也也已經關閉)。當然了,normalizr 代碼本身也是足夠穩(wěn)定。

筆者也在考慮一些新的場景使用并嘗試為 normalizr 添加一些新的功能(如 id 轉換)和優(yōu)化(ts 重構),如果您在使用 normalizr 的過程中遇到什么問題,也可以聯(lián)系我,存儲庫目前在 normalizr-helper 中。

到此這篇關于JavaScript利用normalizr實現(xiàn)復雜數據轉換的文章就介紹到這了,更多相關JavaScript normalizr復雜數據轉換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論