为了账号安全,请及时绑定邮箱和手机立即绑定

未捕获的 FirebaseError:使用无效数据调用函数 DocumentReference

未捕获的 FirebaseError:使用无效数据调用函数 DocumentReference

繁花如伊 2023-08-05 11:49:53
我目前正在尝试制作一份调查问卷,让用户对图像进行评分。我想将用户对图像评分的值与他们对图像评分的值一起推送到数据库。我目前正在将其打印到控制台日志,但在将其发送到数据库时遇到问题。它表示单选按钮的数据不是对象。这是我第一次使用firebase,对JS的经验很少。function validate() {    var radio = document.getElementsByName("answer");    var checked = false;    for (var i = 0; i < radio.length; i++) {        if (radio[i].checked) {            checked = true;            break;        } else {            checked = false;        }    }    if (checked) {        for (var i = 0; i < radio.length; i++)        {            if (radio[i].checked)            {                selected = (radio[i].value)                window.sessionStorage.setItem("selected", JSON.stringify(selected));                console.log(selected)                changeImage();            }        }             } else {        alert("You must select an answer!")    }}  var currentImage = 0;var imageArray = ["/Users/rate/images/images/practice/sun1.jpg", "/Users/rate/images/images/practice/sun2.jpg", "/Users/rate/images/images/practice/sun3.jpg", "/Users/rate/images/images/practice/sun4.jpg"]function changeImage(){    if (currentImage >= imageArray.length - 1) {        writeToDB();      } else {        currentImage += 1;      }    document.getElementById("mainImage").src = imageArray[currentImage]    img = imageArray[currentImage].slice(-8)    console.log(img)    window.sessionStorage.setItem("selected", JSON.stringify(img));}function writeToDB() {    var selected = JSON.parse(window.sessionStorage.getItem("selected"));    var firebaseConfig = {        apiKey: "***",        authDomain: "**",        databaseURL: "**",        projectId: "**",        storageBucket: "**",        messagingSenderId: "**",        appId: "**",        measurementId: "**"    };
查看完整描述

2 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

因此,考虑到您想要获得比实际告诉数据库更多的数据,答案会更加复杂。每个文档的数据结构可能更像这样:


{

  url: /* string containing image's url */,

  rating: [4, 2, 5, 0] /* array containing ratings given for this image

}

每个图像应该以大致相同的方式表示 - 所以如果你有一个名为 的集合images,那么你可能会有这样的东西:


const dbRef = firebase.firestore();

const imagesRef = dbRef.collection('images');


const oneImage = imagesRef.doc('JdBPHMYWfNMMlMpfsjv5');

oneImage.get().then(function(doc){

  console.log( doc.data() )

  // that might return 

  {

    'url': '/img/sun002.jpg',

    'rating': [5,2,3,2,0,5]

  }


  /***

   * but! In your case, you'd likely want to create the HTML fragment

   * you'll be injecting for this particular image:

   ***/

  // so let's pull all the stuff out of the database, and create an object

  //  that includes the image's id.

  const image = {id: doc.id, ...doc.data() }


  // Using that, we can create an HTML fragment that generates the radio buttons

  const imageEl = document.createRange().createContextualFragment(`<div class='img-container'>

  <img src='${image.url}'>

  <fieldset class='image-rating'>Rate this image: 

    <label>0 <input type='radio' name='rating' data-uid='${image.id}' value=0 /></label>

    <label>1 <input type='radio' name='rating' data-uid='${image.id}' value=1 /></label>

    <label>2 <input type='radio' name='rating' data-uid='${image.id}' value=2 /></label>

    <label>3 <input type='radio' name='rating' data-uid='${image.id}' value=3 /></label>

    <label>4 <input type='radio' name='rating' data-uid='${image.id}' value=4 /></label>

    <label>5 <input type='radio' name='rating' data-uid='${image.id}' value=5 /></label>

  </fieldset>

</div>

'`)


// Let's add a listener for the click on the wrapper for all these radios

imageEl.querySelector('.image-rating').addEventListener('click', handleRatingClick)


// And finally, let's add this image block to the page!

document.querySelector("#images-content-pane").appendChild(imageEl)


})

doc请注意,每个图像在集合中都是其自己的,但它可以包含您可能喜欢的任何属性。您可以添加一个caption属性,或者任何可能对您有用的内容。

但有几点需要注意:

  1. 我以编程方式创建每个图像的容器,并将侦听器动态添加到每个图像的字段集。

  2. 我正在data-uid向每个单选按钮添加一个属性。我们稍后需要它,以便我们知道要更新哪个图像文档!

然后,稍后,当您为此图像添加评级时,您只需引用该特定图像并将所选评级添加到数组中即可:

// In my case, I had a fieldset wrap all my radio buttons, and a click was handled there:

const handleRatingClick = (event) =>{

  // First, let's get the clicked el:

  const ratingBtn = event.target;

  const imageId = ratingBtn.dataset.uid;

  const rating = ratingBtn.value;



  // And here I update the array in the rating property, by adding the given value

  imagesRef.doc(imageId).update({

    rating: firebase.firestore.FieldValue.arrayUnion(Number(rating))

  })


}

请注意,这不是唯一的方法,甚至不是正确的方法。重点是,您需要将每个图像视为数据库中的文档,并且需要在创建或更新它时为 firestore 提供一个对象。


您可以像您正在做的那样,并使用 localStorage/sessionStorage 中的图像,但即便如此, sessionStorage 中的值也需要是一个对象,包含


{

  url,

  answer

}

这样做.set()只会覆盖每次答案的值,而不是随着时间的推移存储它们。另外,为了让你的工作正常,你需要在某个地方存储一个 doc.id 。

查看完整回答
反对 回复 2023-08-05
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

通过将图像名称和评级值添加到字典中来解决



查看完整回答
反对 回复 2023-08-05
  • 2 回答
  • 0 关注
  • 104 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信