[英]KnockoutJS: RangeError: Maximum call stack size exceeded;
注冊產品時,用戶可以自定義產品的URL! 當用戶輸入Tipo de produto
, Nome
或Link
,該網站將向您顯示該產品的URL
完整網址: http : //i.stack.imgur.com/jZg7G.png
請注意,“ Tipo de produto”字段還會修改URL !!
為此,我在KnockoutJS中創建了一個助手
淘汰賽
ko.bindingHandlers.url =
update: (element, valueAccessor, allBindingsAccessor, viewModel) ->
link = ko.utils.unwrapObservable(valueAccessor())
if link
link = link.toLowerCase().trim().replaceAll(" ", "-")
link = encodeURI(link)
else
link = ""
valueAccessor()(link)
$(element).nextAll(".link-exibicao").text(link).effect("highlight", { color: "#FDBB30" }, 800 )
此幫助程序的唯一目的是生成一個有效的URL並將其顯示在span .link-exibicao
視圖模型
public class ProdutoViewModel
{
[AdditionalMetadata("data-bind", "event: { change: function(data) { Link(data.Nome()); }}")]
public string Nome { get; set; }
[DataType(DataType.Url)]
[AdditionalMetadata("Prefixo", "Produto/")]
public string Link { get; set; }
[Display(Name = "Descrição")]
[DataType(DataType.MultilineText)]
public string Descricao { get; set; }
public int? Ordem { get; set; }
}
AdditionalMetadata
將添加具有該名稱和值的屬性。 例如,屬性Name
將生成HTML:
<input data-bind="value: Nome, event: { change: function(data) { Link(data.Nome()); }}" id="Nome" name="Nome" type="text" value="">
Url.cshtml
下一步是在URL類型的所有字段中添加標記data-bind="url: Link"
:
@model string
@{
var values = ViewData.ModelMetadata.AdditionalValues;
object objDatabind;
string data_bind = "";
if (values.TryGetValue("data-bind", out objDatabind))
{
data_bind = objDatabind.ToString();
}
var nomeCampo = Html.IdForModel();
var objPrefixo = values["Prefixo"];
string prefixo = objPrefixo.ToString();
string separador = "/";
if (!string.IsNullOrWhiteSpace(prefixo))
{
if (prefixo.EndsWith("/") || prefixo.EndsWith("#"))
{
separador = prefixo[prefixo.Length - 1].ToString();
prefixo = prefixo.Substring(0, prefixo.Length - 1);
}
}
}
@Html.TextBoxFor(p => Model, new { data_bind = "value: " + nomeCampo + ", url: " + nomeCampo + (string.IsNullOrWhiteSpace(data_bind) ? "" : ", " + data_bind) })
@Request.Url.Host/<span class="link-prefixo">@prefixo</span><span class="link-separador">@separador</span><span class="link-exibicao"></span>
ProdutoViewModel.cshtml
最后,最簡單的步驟是構建表單=):
<div class="editor-label">
<label>Tipo de produto</label>
</div>
<div class="editor-field">
<select data-bind="options: Tipos, optionsText: 'Nome', value: TipoSelecionado, optionsCaption: 'Selecione...'"></select>
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Nome)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Nome)
@Html.ValidationMessageFor(p => p.Nome)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Link)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Link)
@Html.ValidationMessageFor(p => p.Link)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Descricao)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Descricao)
@Html.ValidationMessageFor(p => p.Descricao)
</div>
<div class="editor-label">
@Html.LabelFor(p => p.Ordem)
</div>
<div class="editor-field">
@Html.EditorFor(p => p.Ordem)
@Html.ValidationMessageFor(p => p.Ordem)
</div>
只要輸入簡單的詞,例如:“我的產品名稱”,一切都可以正常運行!
但是會顯示meu prodúto côm açênto
的錯誤,並顯示以下錯誤!
Uncaught Error: Unable to parse bindings.
Message: RangeError: Maximum call stack size exceeded;
Bindings value: value: Link, url: Link
您訪問值時,bindingHandler導致遞歸更新:
link = ko.utils.unwrapObservable(valueAccessor())
然后設置它:
valueAccessor()(link)
如果link
最終與其當前值相同,則該鏈將停止(可觀察對象不會通知相同(===)值)。
當您通過時: meu prodúto côm açênto
變成: meu-prod%C3%BAto%20c%C3%B4m%20a%C3%A7%C3%AAnto
設置可觀察對象時,它將重新觸發相同的綁定。 因此,它再次調用encodeURI
,現在它已被雙重編碼,例如:
meu-prod%25C3%25BAto%2520c%25C3%25B4m%2520a%25C3%25A7%25C3%25AAnto
再次設置可觀察對象,並且由於此值是新值,它將再次(一次又一次)觸發它,直到您收到調用堆棧錯誤為止。
處理此問題的一些選項是不寫回可觀察的對象,而僅使用綁定對URL進行編碼。
否則,一個不錯的選擇是使用writeable computed observable
來攔截對值的寫入並在模型中進行操作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.