为什么我不能将字符串作为数据参数传递给Blaze.renderWithData()?

时间:2021-09-29 16:40:54

I'm creating a Blaze View with the following call:

我正在使用以下调用创建Blaze View:

Blaze.renderWithData(Template.my_template, myobj._id, html.node());

my_template looks like this:

my_template看起来像这样:

<template name="my_template">
  {{> Template.dynamic template=whichTemplate data=sdata}}
</template>

The sdata helper looks like this:

sdata助手看起来像这样:

sdata: function() {
  return Doodads.findOne({_id: this});
}

Which fails with the following error:

哪个失败,出现以下错误:

Exception in template helper: TypeError: selKey.substr is not a function

模板助手中的异常:TypeError:selKey.substr不是函数

If I do console.log(this) within that helper, I get:

如果我在该帮助器中执行console.log(this),我会得到:

String {0: "N", 1: "7", 2: "j", 3: "o", 4: "y", 5: "g", 6: "w", 7: "P", 8: "g", 9: "e", 10: "s", 11: "R", 12: "f", 13: "w", 14: "q", 15: "o", 16: "7", length: 17, [[PrimitiveValue]]: "N7joygwPgesRfwqo7"}

To correct the problem, I can change the findOne() line to:

要解决此问题,我可以将findOne()行更改为:

  return Doodads.findOne({_id: ""+this});

Which works as expected.

哪个按预期工作。


I am posting this question to help myself (and others) understand what is going on here.

我发布这个问题是为了帮助自己(和其他人)了解这里发生了什么。

Mainly I want to know:

主要是我想知道:

  • Why is there difference between using a String{...} object and a regular string for this call (i.e, why doesn't the selector key object have a substr() method when I'm using a different/weird selector value)?
  • 为什么在此调用中使用String {...}对象和常规字符串之间存在差异(即,当我使用不同/奇怪的选择器值时,为什么选择器键对象没有substr()方法) ?

  • Why does the _id property show up as this weird String{...} object as the template data this when the _id property is usually just a string? Or is it not usually and I've just never noticed?
  • 当_id属性通常只是一个字符串时,为什么_id属性显示为这个奇怪的String {...}对象作为模板数据?或者通常不是,我从来没有注意到?

I've solved the problem with the ""+this hack, but is there a more proper way to do this?

我用“”+这个黑客解决了这个问题,但有没有更合适的方法呢?

2 个解决方案

#1


0  

what is wrong?

According to the Blaze API docs, the signature is:

根据Blaze API文档,签名是:

Blaze.renderWithData(templateOrView, data, parentNode, [nextNode], [parentView])

Blaze.renderWithData(templateOrView,data,parentNode,[nextNode],[parentView])

data Object or Function

数据对象或函数

The data context to use, or a function returning a data context. If a function is provided, it will be reactively re-run.

要使用的数据上下文,或返回数据上下文的函数。如果提供了一个功能,它将被反应性地重新运行。

The data context, in your case, should be an object which includes a whichTemplate property and some id that you can use in your helper.

在您的情况下,数据上下文应该是一个对象,其中包含一个whichTemplate属性和一些可以在助手中使用的id。

Blaze.renderWithData(Template.my_template, {
  _id: myId, 
  whichTemplate: someTemplateName
}, someNode);

or, instead of a data object, pass a function that will be reactively re-run.

或者,而不是数据对象,传递将被反应重新运行的函数。

With this setup, your helper code should be something like:

使用此设置,您的帮助程序代码应类似于:

sdata: function() {
  return Doodads.findOne(this._id);
}

source of the error you were seeing

If you are interested in the cause of the error you were getting, here's what is going on:

如果你对你得到的错误的原因感兴趣,这是正在发生的事情:

In blaze, the countext is bound to the template helper's this reference using Function.protptype.apply(thisArg, [argsArray]) (in this line).

在大火中,countext使用Function.protptype.apply(thisArg,[argsArray])(在此行中)绑定到模板助手的此引用。

According to the EcmaScript standard, if thisArg is a primitive, it will be boxed.

根据EcmaScript标准,如果thisArg是原始的,它将被装箱。

thisArg

The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.

这个值的价值提供给乐趣。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,则null和undefined将替换为全局对象,并且原始值将被加框。

(source: MDN)

This causes a String object, which does not have a substr method, be transferred to the MiniMongo.Collection's find() method, which fails here.

这会导致没有substr方法的String对象被转移到MiniMongo.Collection的find()方法,该方法在此处失败。

#2


0  

If your data is created from some other source than a Meteor subscription, it could be that your _id is a MongoDB ObjectId, which is not a string.

如果您的数据是从Meteor订阅之外的其他来源创建的,则可能是您的_id是MongoDB ObjectId,它不是字符串。

Have a look in the Mongo shell, if you do a .findOne on the myobj object and it shows up looking something like

看看Mongo shell,如果你在myobj对象上做一个.findOne,它会显示出像

"_id" : ObjectId("57cd946429bca10300f0fd55")

#1


0  

what is wrong?

According to the Blaze API docs, the signature is:

根据Blaze API文档,签名是:

Blaze.renderWithData(templateOrView, data, parentNode, [nextNode], [parentView])

Blaze.renderWithData(templateOrView,data,parentNode,[nextNode],[parentView])

data Object or Function

数据对象或函数

The data context to use, or a function returning a data context. If a function is provided, it will be reactively re-run.

要使用的数据上下文,或返回数据上下文的函数。如果提供了一个功能,它将被反应性地重新运行。

The data context, in your case, should be an object which includes a whichTemplate property and some id that you can use in your helper.

在您的情况下,数据上下文应该是一个对象,其中包含一个whichTemplate属性和一些可以在助手中使用的id。

Blaze.renderWithData(Template.my_template, {
  _id: myId, 
  whichTemplate: someTemplateName
}, someNode);

or, instead of a data object, pass a function that will be reactively re-run.

或者,而不是数据对象,传递将被反应重新运行的函数。

With this setup, your helper code should be something like:

使用此设置,您的帮助程序代码应类似于:

sdata: function() {
  return Doodads.findOne(this._id);
}

source of the error you were seeing

If you are interested in the cause of the error you were getting, here's what is going on:

如果你对你得到的错误的原因感兴趣,这是正在发生的事情:

In blaze, the countext is bound to the template helper's this reference using Function.protptype.apply(thisArg, [argsArray]) (in this line).

在大火中,countext使用Function.protptype.apply(thisArg,[argsArray])(在此行中)绑定到模板助手的此引用。

According to the EcmaScript standard, if thisArg is a primitive, it will be boxed.

根据EcmaScript标准,如果thisArg是原始的,它将被装箱。

thisArg

The value of this provided for the call to fun. Note that this may not be the actual value seen by the method: if the method is a function in non-strict mode code, null and undefined will be replaced with the global object, and primitive values will be boxed.

这个值的价值提供给乐趣。请注意,这可能不是方法看到的实际值:如果方法是非严格模式代码中的函数,则null和undefined将替换为全局对象,并且原始值将被加框。

(source: MDN)

This causes a String object, which does not have a substr method, be transferred to the MiniMongo.Collection's find() method, which fails here.

这会导致没有substr方法的String对象被转移到MiniMongo.Collection的find()方法,该方法在此处失败。

#2


0  

If your data is created from some other source than a Meteor subscription, it could be that your _id is a MongoDB ObjectId, which is not a string.

如果您的数据是从Meteor订阅之外的其他来源创建的,则可能是您的_id是MongoDB ObjectId,它不是字符串。

Have a look in the Mongo shell, if you do a .findOne on the myobj object and it shows up looking something like

看看Mongo shell,如果你在myobj对象上做一个.findOne,它会显示出像

"_id" : ObjectId("57cd946429bca10300f0fd55")