2017-07-08 56 views
0

我非常熟悉的「child_added」,「child_changed」,「child_removed」和「價值」的理念。 每當我使用一個列表,這應該是動態更新自己,我應該使用除「值」之外的所有函數,並且每當我只需要數據的靜態快照時,我將使用「值」。如何有效地使用child_added

我的問題如下:

難道真的寫三個觸發器(4如果算上「child_moved」),每當我有一個列表的最好方法?一個簡單的應用程序有很多列表。 如果是的話,它是如何以最有效的方式在JavaScript中完成的?我目前的做法如下:

  • on child_added:遍歷整個列表;看看密鑰與我剛從事件收到的密鑰相等的位置,並將其值保存爲oldValue;現在發現prevChildKey指數和prevChildKey的索引後插入剛接到孩子,而除去myList中[myList.indexOf(屬性oldValue)]從列表中
  • 上child_changed:遍歷我的整個列表;看看密鑰與我剛從事件收到的密鑰相等的位置,並將其值保存爲oldValue;設置myList [myList.indexOf(oldValue)] = newValue;
  • on child_removed:與上面相同,只是與myList.splice(...)
  • on child_moved:我沒有實現這一點。但是我可能需要它,當調用child_changed時,這導致我的元素的順序發生變化。所以有一個非常類似的邏輯child_added

有沒有辦法以更優雅的方式處理這個問題?我第一次嘗試通過myList [child.key]訪問元素,但這不適用於我。

編輯:添加代碼來說明吧,很多的代碼申請每個列表在我的應用

myRef.orderByChild("timestamp").on("child_added",(message,prevChildKey) => { 
     //Transform the firebase-date into my own format 
     var template = { 
      senderName: message.val().sender, 
      time: message.val().timestamp, 
      id: message.key} 

     //Check where to add this 
     if(prevChildKey){ 
      this.messages.forEach(currentMessage => { 
       if(currentMessage.id === prevChildKey){ 
        var indexToAdd = this.messages.indexOf(currentMessage); 
        this.messages.splice(indexToAdd+1,0,template]; 
       } 
      }); 
     }else 
      this.messages.unshift(template); 

}); 
myRef.on("child_changed", message => { //orderByChild makes no sense here, right ? 
    //Transform the firebase-date into my own format 
    var template = { 
     senderName: message.val().sender, 
     time: message.val().timestamp, 
     id: message.key} 

    var toBeUpdated = undefined; 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === message.id){ 
      this.messages[this.messages.indexOf(currentMessage)] = template; 
     } 
    }) 

    //How do I preserve ordering here, since I was ordering by timestamp on child_added before and I don't check if that value changed 
} 
myRef.on("child_removed", oldMessage => { 

    //Remove the message 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === oldMessage.id){ 
      this.messages.splice(this.messages.indexOf(currentMessage),1); 
     } 
    }) 
} 
myRef.orderByChild("timestamp").on("child_moved", (message,prevChildKey) => { //Not too sure, how this works. Do I need the orderByChild here to preserve it ? 

    var messageToMove = undefined; 
    var messagePosition = undefined; 
    var indexToMoveTo = undefined; 
    this.messages.forEach(currentMessage => { 
     if(currentMessage.id === message.id){ 
      messagePosition = this.messages.indexOf(currentMessage); 
      messageToMove = this.messages[messagePosition]; 
     } 
     if(currentMessage.id === prevChildKey){ 
      indexToMoveTo = this.messages.indexOf(currentMessage) + 1; 
     } 
    }) 

    //Remove the message from where it was 
    this.messaged.splice(messagePosition,1); 
    //Add the message at the new position 
    this.messages.splice(indexToMoveTo,0,messageToMove); 

} 
+0

您在問我們是否有更有效的方法來做某件事。我們大多數人都不擅長解析代碼的描述。所以請發佈[演示您當前解決方案的最小實際代碼](http://stackoverflow.com/help/mcve),我們可能會提供更多幫助。 –

+0

我添加了一些代碼作爲演示 – Thomas

+0

用例描述有點不清楚; *爲什麼*你在迭代列表來查看密鑰是否與剛收到的密鑰相同?你是否試圖保持帖子的順序?如果是這樣,只是每個帖子的時間戳,他們將始終在正確的順序?此外,如果添加,更改或刪除了某個帖子,則該帖子將傳遞給您的應用,從而再次直接訪問該節點,因此無需遍歷列表以查找它。即如果node_3被更改,該密鑰(node_3)被傳遞給你的應用,你可以直接訪問node_3/child_nodes來更新它們。 – Jay

回答

0

所以我莫名其妙地需要我的火力得到了本地的元素映射 表示它。

哦!這很容易!

如您所知,Firebase將其數據存儲在鍵值對中。

因此,例如,一個用戶節點將

users 
    uid_0 
     name: "Bill" 
    uid_1 
     name: "Larry" 

如果你在一個節點改名字,說比爾·比利的uid_0節點(及其子數據)傳遞給你的應用程序中快照,關鍵是uid_0。該鍵將對應於您存儲在陣列中的數據。

有很多方法可以解決這個問題。

一種方式是存儲對象的數組作爲鍵值對字典英寸一些僞代碼

myDictionary = [ "uid_0": [name: "Billy"] ] 
myArray[0] = myDictionary 

然而,「分類器」的方式來做到這將是創建一個用戶類和存儲那些在陣列中,與鍵(uid_0)作爲類的屬性之一

UserClass { 
    key = "" 
    name = "" 
} 

let aUser = UserClass 
aUser.key = snapshot.key 
aUser.name = snapshot.value("name") //loose pseudo code, dont copy/paste! 

myArray[0] = userClass 

然後,當您的應用程序收到快照時,您可以查詢從snapshot.key收到的userClass.key的數組。

大圖是Firebase通過密鑰進行存儲和訪問,它保持一致並且不變,所以它是用來保持你的朋友的工具(消息s)陣列與Firebase同步。

編輯:如果您希望通過在HashMap(字典)中存儲鍵和元素編號來直接訪問已排序的數組對象,則可以實現鏈接列表。

Map<String, String> map = new HashMap<String, String>(); 
map.put("uid_0", "0"); 

然後打印出指數uid_0

System.out.println(map.get("uid_0")); 

其輸出指數:0

如果你只想用一個存儲機制,一個TreeMap(自然順序)或LinkedHashMap是要走的路。

map.put("uid_0", *values for uid_0, name etc*); 
+0

感謝您的答案,但爲snapshot.key找到相應的userClass.key我仍然需要迭代我的數組來找到它。不是嗎?這是我目前的做法,只是沒有課堂。總是找到匹配的userClass.key並保持排序仍然是很多代碼(如我的文章所示)。 – Thomas

+0

我的歉意 - 我在高層發言,提供利用snapshot.key保持排列的背景。我更新了答案,提供了更多細節 - 我建議利用LinkedHashMap進行存儲,因爲您的數據可能是由Firebase在讀取數據時訂購的,並且LinkedHashMap將保持該順序並且可以直接訪問snapshot.key元素。 – Jay

+0

我也在考慮這個。但首先,據我所知,JavaScript不支持LinkedHasMaps。只有不保留訂單的目錄。另一點是,在視圖內* ngFor(對於Angular)不能迭代地圖。所以我需要編寫一個單獨的函數,將鍵作爲數組提供,然後通過鍵引用我的目錄中的確切條目。可悲的是,我在網上找到的所有教程只是簡單地忽略了child_ *(除了child_added)事件。但必須有一個平滑的方式來解決這個問題在JavaScript(或打字稿)。 – Thomas