评级系统 javascript 不会将结果发送到 firebase
Rating system javascript will not send results to firebase
我有一个可以正常运行的脚本,可以根据评分值推送评分,例如 1/5、2/5、3/5 等。但该脚本根本不与 firebase 通信。我的 javascript 是否有问题,这会阻止输入值按指示发送到 firebase?这是所有必要的代码。另外,在文档的头部有一个 link 到 firebase.js。
(function() {
var firebaseUrl = "https://myFirebase.firebaseIO.com/rating";
var itemId = (rootRef).child;
var rootRef = new Firebase(firebaseUrl); // Reference the Firebase location
var itemRef = rootRef.child("items").child(itemId); //Define itemRef as the variable for itemId in firebase
var star = $('.rating');
var numRatings;
star.click(function() { //Watch out for rating1 inside of the website and grab its value. i.e. 1, 2, 3, 4, or 5
itemRef.child("ratings").child("numRatings").set(star.val()); //Set ratings inside of Firebase with values such as 1, 2, 3, 4, and 5, under items such as item1, item2, item3, etc...
});
var cumulativeRating;
var averageRating;
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--Rating system begin-->
<div class="rating">
<div class="starRating">
<div>
<div>
<div>
<div>
<input id="rating1" class="rating" type="radio" name="rating" value="1">
<label for="rating1"><span>1</span></label>
</div>
<input id="rating2" class="rating" type="radio" name="rating" value="2">
<label for="rating2"><span>2</span></label>
</div>
<input id="rating3" class="rating" type="radio" name="rating" value="3">
<label for="rating3"><span>3</span></label>
</div>
<input id="rating4" class="rating" type="radio" name="rating" value="4">
<label for="rating4"><span>4</span></label>
</div>
<input id="rating5" class="rating" type="radio" name="rating" value="5">
<label for="rating5"><span>5</span></label>
</div>
<h3 class="ratingtext">Rated 4/5 by 103 users</h3>
<!--Rating system end-->
您更新安全规则了吗?
在 firebase 中(link 参考)转到规则并添加感兴趣的数组或对象(从教程中复制示例对象)
例如设置rating的读写为true
你的代码中有不少小错误。我将带您了解其中的一些。但请不要只是复制代码,而是花时间了解我是如何解决这些问题的。您的首要目标应该是能够调试自己的代码以摆脱这些更简单的错误。
OK,我把两个问题写上去。可能还有更多,但这已经需要足够的时间了。
- 处理 Firebase 中还没有数据的情况
- 获取点击的单选按钮的值
处理 Firebase 中还没有数据的情况
当我将您的代码粘贴到 jsbin 时发生的第一件事是它会将此记录到开发工具中的 JavaScript 控制台(您可以使用 F12开发时应该始终保持打开状态):
Uncaught TypeError: Cannot read property 'numRatings' of null
这是空指针异常的现代 JavaScript 版本,是因为您在 null
或 undefined
上执行了 .numRatings
。幸运的是,你只有一个地方 .numRatings
:
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
});
所以看起来 ratingsData
没有价值,这确实发生在项目第一次获得评级时。在这种情况下,Firebase 将使用 null
(或 undefined
)触发 value
事件。
处理起来很容易:
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
if (ratingsData) {
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
}
});
在实际实施中,您可能希望向 if
添加一个 else
并表明还有 no/not 足够的评级。
获取单击的单选按钮的值
将点击值传递给 Firebase 的代码段是:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set(star.val());
});
我做的第一件事是在其中添加一个日志语句,以查看点击是否通过代码:
var star = $('.rating');
star.click(function() {
console.log('click');
itemRef.child("ratings").child("numRatings").set(star.val());
});
当我现在单击单选按钮时,它会记录 click
。所以看起来连接正确。我通常会在下一步放置 JavaScript debugger
statement 而不是 console.log
,但这次决定不这样做。
我做的下一个技巧是设置一个简单的 Firebase 记录器来显示更改是否通过到 Firebase:
new Firebase('https://you.firebaseIO.com/rating').on('value', function(s) { console.log(JSON.stringify(s.val())); })
您可以将其添加到脚本顶层的任何位置。我最常将它添加到 Chrome 的开发工具的控制台中。每次 Firebase 的值发生变化时,它都会记录如下内容:
{"items":{"42":{"ratings":{"numRatings":"3"}}}}
或者这是它应该做的,但在您的原始脚本中它从来没有这样做过。所以我们进入了点击处理程序,但该值没有进入 Firebase。
仔细检查发现了一些奇怪的东西:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set(star.val());
});
您在此代码段的第一行中使用变量 star
来指向所有评级元素。但随后在点击处理程序中您执行 star.val()
,这意味着您希望它引用单个评级元素:被点击的元素。
此处关于变量名称的快速说明:您通过对包含所有评级元素的变量使用单数 star
为自己设置了这个错误。我将该变量命名为 stars
,以表明它包含多颗星。这样,当您键入 stars.val()
.
时,您会更容易看到某些东西有气味
我不是 jQuery 专家,但是 docs for jQuery's click method 的快速 Google 似乎表明您可以作为 this
访问单击的元素。所以片段需要是:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set($this).val());
});
然后,我的 Firebase JSON 记录器开始输出数据:
{"items":{"42":{"ratings":{"numRatings":"3"}}}}
这些值现在已进入 Firebase!
从问题中消除技术
请注意,最后一项更改与 Firebase 无关。如果您尝试提醒值,也会发生这种情况:
var star = $('.rating');
star.click(function() {
alert(star.val());
});
这是调试问题(或创建 MCVE)时的一个关键点:尝试尽可能多地从问题中删除技术。通过从这个小代码片段中删除 Firebase,问题从 "why doesn't my star rating make it into Firebase?" 变为 "why doesn't this code fragment show the value of the star I clicked?" 或者一旦你掌握了它 "how do I get the value of the element I clicked?"。最后一个是一个问题,您可以输入 Google 并期望得到一个不错的结果,因为您不是第一个遇到这个问题的人。尝试在 Firebase 上构建星级评分系统的人数要少得多。
终于
正如我已经说过的,您的脚本仍有问题。例如:我的 Firebase JSON logger:
每次单击单选按钮都会生成一对行
{"items":{"42":{"ratings":{"numRatings":"3"}}}}
{"items":{"42":{"ratings":{"numRatings":""}}}}
因此,每次我单击单选按钮时,似乎都会触发 Firebase 中的两次更改,第二次更改会撤消第一次更改的工作。我很确定我能弄清楚为什么会这样。但我希望通过以上课程,您将能够自己解决这个问题。
我的最终剧本:
(function() {
var firebaseUrl = "https://your.firebaseio.com/rating";
var itemId = 42; // TODO: look up Id of the actual item
var rootRef = new Firebase(firebaseUrl);
var itemRef = rootRef.child("items").child(itemId);
var star = $('.rating');
var numRatings;
star.click(function() {
itemRef.child("ratings").child("numRatings").set($(this).val());
});
var cumulativeRating;
var averageRating;
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
if (ratingsData) {
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
}
});
})();
它也在 jsbin 上,我在那里进行调试:http://jsbin.com/lekifefuce/1/edit?js,output
我有一个可以正常运行的脚本,可以根据评分值推送评分,例如 1/5、2/5、3/5 等。但该脚本根本不与 firebase 通信。我的 javascript 是否有问题,这会阻止输入值按指示发送到 firebase?这是所有必要的代码。另外,在文档的头部有一个 link 到 firebase.js。
(function() {
var firebaseUrl = "https://myFirebase.firebaseIO.com/rating";
var itemId = (rootRef).child;
var rootRef = new Firebase(firebaseUrl); // Reference the Firebase location
var itemRef = rootRef.child("items").child(itemId); //Define itemRef as the variable for itemId in firebase
var star = $('.rating');
var numRatings;
star.click(function() { //Watch out for rating1 inside of the website and grab its value. i.e. 1, 2, 3, 4, or 5
itemRef.child("ratings").child("numRatings").set(star.val()); //Set ratings inside of Firebase with values such as 1, 2, 3, 4, and 5, under items such as item1, item2, item3, etc...
});
var cumulativeRating;
var averageRating;
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!--Rating system begin-->
<div class="rating">
<div class="starRating">
<div>
<div>
<div>
<div>
<input id="rating1" class="rating" type="radio" name="rating" value="1">
<label for="rating1"><span>1</span></label>
</div>
<input id="rating2" class="rating" type="radio" name="rating" value="2">
<label for="rating2"><span>2</span></label>
</div>
<input id="rating3" class="rating" type="radio" name="rating" value="3">
<label for="rating3"><span>3</span></label>
</div>
<input id="rating4" class="rating" type="radio" name="rating" value="4">
<label for="rating4"><span>4</span></label>
</div>
<input id="rating5" class="rating" type="radio" name="rating" value="5">
<label for="rating5"><span>5</span></label>
</div>
<h3 class="ratingtext">Rated 4/5 by 103 users</h3>
<!--Rating system end-->
您更新安全规则了吗?
在 firebase 中(link 参考)转到规则并添加感兴趣的数组或对象(从教程中复制示例对象)
例如设置rating的读写为true
你的代码中有不少小错误。我将带您了解其中的一些。但请不要只是复制代码,而是花时间了解我是如何解决这些问题的。您的首要目标应该是能够调试自己的代码以摆脱这些更简单的错误。
OK,我把两个问题写上去。可能还有更多,但这已经需要足够的时间了。
- 处理 Firebase 中还没有数据的情况
- 获取点击的单选按钮的值
处理 Firebase 中还没有数据的情况
当我将您的代码粘贴到 jsbin 时发生的第一件事是它会将此记录到开发工具中的 JavaScript 控制台(您可以使用 F12开发时应该始终保持打开状态):
Uncaught TypeError: Cannot read property 'numRatings' of null
这是空指针异常的现代 JavaScript 版本,是因为您在 null
或 undefined
上执行了 .numRatings
。幸运的是,你只有一个地方 .numRatings
:
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
});
所以看起来 ratingsData
没有价值,这确实发生在项目第一次获得评级时。在这种情况下,Firebase 将使用 null
(或 undefined
)触发 value
事件。
处理起来很容易:
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
if (ratingsData) {
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
}
});
在实际实施中,您可能希望向 if
添加一个 else
并表明还有 no/not 足够的评级。
获取单击的单选按钮的值
将点击值传递给 Firebase 的代码段是:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set(star.val());
});
我做的第一件事是在其中添加一个日志语句,以查看点击是否通过代码:
var star = $('.rating');
star.click(function() {
console.log('click');
itemRef.child("ratings").child("numRatings").set(star.val());
});
当我现在单击单选按钮时,它会记录 click
。所以看起来连接正确。我通常会在下一步放置 JavaScript debugger
statement 而不是 console.log
,但这次决定不这样做。
我做的下一个技巧是设置一个简单的 Firebase 记录器来显示更改是否通过到 Firebase:
new Firebase('https://you.firebaseIO.com/rating').on('value', function(s) { console.log(JSON.stringify(s.val())); })
您可以将其添加到脚本顶层的任何位置。我最常将它添加到 Chrome 的开发工具的控制台中。每次 Firebase 的值发生变化时,它都会记录如下内容:
{"items":{"42":{"ratings":{"numRatings":"3"}}}}
或者这是它应该做的,但在您的原始脚本中它从来没有这样做过。所以我们进入了点击处理程序,但该值没有进入 Firebase。
仔细检查发现了一些奇怪的东西:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set(star.val());
});
您在此代码段的第一行中使用变量 star
来指向所有评级元素。但随后在点击处理程序中您执行 star.val()
,这意味着您希望它引用单个评级元素:被点击的元素。
此处关于变量名称的快速说明:您通过对包含所有评级元素的变量使用单数 star
为自己设置了这个错误。我将该变量命名为 stars
,以表明它包含多颗星。这样,当您键入 stars.val()
.
我不是 jQuery 专家,但是 docs for jQuery's click method 的快速 Google 似乎表明您可以作为 this
访问单击的元素。所以片段需要是:
var star = $('.rating');
star.click(function() {
itemRef.child("ratings").child("numRatings").set($this).val());
});
然后,我的 Firebase JSON 记录器开始输出数据:
{"items":{"42":{"ratings":{"numRatings":"3"}}}}
这些值现在已进入 Firebase!
从问题中消除技术
请注意,最后一项更改与 Firebase 无关。如果您尝试提醒值,也会发生这种情况:
var star = $('.rating');
star.click(function() {
alert(star.val());
});
这是调试问题(或创建 MCVE)时的一个关键点:尝试尽可能多地从问题中删除技术。通过从这个小代码片段中删除 Firebase,问题从 "why doesn't my star rating make it into Firebase?" 变为 "why doesn't this code fragment show the value of the star I clicked?" 或者一旦你掌握了它 "how do I get the value of the element I clicked?"。最后一个是一个问题,您可以输入 Google 并期望得到一个不错的结果,因为您不是第一个遇到这个问题的人。尝试在 Firebase 上构建星级评分系统的人数要少得多。
终于
正如我已经说过的,您的脚本仍有问题。例如:我的 Firebase JSON logger:
每次单击单选按钮都会生成一对行{"items":{"42":{"ratings":{"numRatings":"3"}}}}
{"items":{"42":{"ratings":{"numRatings":""}}}}
因此,每次我单击单选按钮时,似乎都会触发 Firebase 中的两次更改,第二次更改会撤消第一次更改的工作。我很确定我能弄清楚为什么会这样。但我希望通过以上课程,您将能够自己解决这个问题。
我的最终剧本:
(function() {
var firebaseUrl = "https://your.firebaseio.com/rating";
var itemId = 42; // TODO: look up Id of the actual item
var rootRef = new Firebase(firebaseUrl);
var itemRef = rootRef.child("items").child(itemId);
var star = $('.rating');
var numRatings;
star.click(function() {
itemRef.child("ratings").child("numRatings").set($(this).val());
});
var cumulativeRating;
var averageRating;
itemRef.child("ratings").on("value", function(ratingsSnapshot) {
var ratingsData = ratingsSnapshot.val();
if (ratingsData) {
numRatings = ratingsData.numRatings;
cumulativeRating = ratingsData.cumulativeRating;
averageRating = cumulativeRating / numRatings;
}
});
})();
它也在 jsbin 上,我在那里进行调试:http://jsbin.com/lekifefuce/1/edit?js,output