- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在 Meteor(使用 Blaze)上开发响应式(Reactive)依赖树,但我没有找到最好的方法。
一、问题
在此示例中,我有一个设置了 item
对象的容器,该对象具有属性 elements
(数组)。
elements
属性是循环,并且会为其每个实例加载一个子模板。
可以在子模板上更新元素,但更新不会传播到容器。
此外,我还添加了一个 Add
按钮来更新 item
ReactiveVar(来自 container
)。每个字段渲染都会在容器上的 item
更新后更新,因此对象已更新但未重新渲染。
HTML
<template name="container">
{{#let item=getItem}}
<h1>Update {{item._id}}</h1>
{{#each element in item.elements}}
<div>
{{> elementForm element}}
<small>{{element.name}}</small>
</div>
{{/each}}
{{/let}}
<button name="add">Add</button>
</template>
<template name="elementForm">
{{#let el=getEl}}
<input value="{{el.name}}"/>
{{/let}}
</template>
父模板
Template.container.onCreated(function onContainerCreated() {
// From data
let item = {
_id: '123abc',
elements: [
{name: "El #1"},
{name: "El #2"},
{name: "El #3"},
]
}
// Create master ReactiveVar
this.item = new ReactiveVar(item);
});
Template.container.helpers({
getItem() {
return Template.instance().item.get();
},
});
Template.container.events({
// Add a new element (Will refresh all elements render)
'click button[name="add"]'(e) {
let instance = Template.instance()
let item = instance.item.get()
item.elements.push({name: "new El"})
instance.item.set(item)
},
})
子模板
/* Element */
Template.elementForm.onCreated(function onElementCreated() {
this.el = new ReactiveVar(this.data)
});
Template.elementForm.helpers({
getEl() {
return Template.instance().el.get()
}
})
Template.elementForm.events({
'change input'(e) {
let instance = Template.instance()
let el = instance.el.get()
el.name = e.currentTarget.value
instance.el.set(el)
}
})
预览
由于 meteor 无法集成到嵌入代码中,所以我制作了一些图像。
默认页面
更新输入不影响容器渲染
添加一个新项目,将重新渲染所有容器并获取新值
解决方案 1 ?将 item
ReactiveVar 发送给子级
我知道将整个 ReactiveVar 发送给 child 可以是在 child 上使用 .set()
方法的解决方案。
但是如果我使用这个 hack,我将不得不将整个 item
发送到每个 elementForm
(不是最好的)
示例
/* Html */
<Template name="parentTemplate">
<small>{{getFoo}}</small>
{{> childTemplate getItem}}
</Template>
<Template name="childTemplate">
<input value="{{getFoo}}" />
</Template>
/* Parent */
Template.parentTemplate.onCreated(function onParentCreated() {
this.item = new ReactiveVar({ foo: bar})
});
Template.parentTemplate.helpers({
getFoo() {
return Template.instance().item.get().foo
},
getItem() {
return Template.instance().item // Send reactive var, net value (.get)
}
})
/* Child */
Template.childTemplate.onCreated(function onChildCreated() {
this.item = this.data.item // Use Parent Reactive var
});
Template.childTemplate.helpers({
getFoo() {
return Template.instance().item.get().foo
},
})
Template.childTemplate.events({
'change input'(e) {
let item = Template.instance().item.get()
item.foo = e.currentTarget.value
Template.instance().item.set(item) // Will update parent
},
})
解决方案2?回调
另一种解决方案是,除了元素数据之外,还向子模板发送每个操作(例如更改)的回调,以通知父模板更新特定元素的主 ReactiveVar。
示例
/* Html */
<Template name="parentTemplate">
<small>{{getFoo}}</small>
{{> childTemplate getData}}
</Template>
<Template name="childTemplate">
<input value="{{getFoo}}" />
</Template>
/* Parent */
Template.parentTemplate.onCreated(function onParentCreated() {
this.item = new ReactiveVar({ foo: bar})
});
Template.parentTemplate.helpers({
getFoo() {
return Template.instance().item.get().foo
},
getData() {
let instance = Template.instance()
return {
item: instance.item.get(),
onChange: function(val) {
// Update item here
let item = instance.item.get()
item.foo = val
instance.item.set(item)
}
}
}
})
/* Child */
Template.childTemplate.onCreated(function onChildCreated() {
});
Template.childTemplate.helpers({
getFoo() {
return Template.instance().data.item.foo
},
})
Template.childTemplate.events({
'change input'(e) {
// Call parent callback
Template.instance().data.onChange(e.currentTarget.value)
},
})
最后一个问题
处理父/子模板以处理项目对象中的元素列表的最佳方法是什么?
最佳答案
实际上是一个好问题。
恕我直言,根据具体情况,我主要采用您的解决方案 1。
类似于:
Template.container.onCreated(function(){
//each elements are ReactiveVar
let item = {
_id: '123abc',
elements: [
{name: new ReactiveVar("El #1")},
{name: new ReactiveVar("El #2")},
{name: new ReactiveVar("El #3")},
]
}
// I don't wrap the wole item on a ReactiveVar if I don't need it.
});
然后,当您使用 #each
对其进行迭代时,您将仅将当前元素数据注入(inject)到子级的数据上下文中。从这里,您可以轻松地执行以下操作:
Template.childTemplate.helpers({
getName() {
return this.name.get();
},
})
Template.childTemplate.events({
'change input'(e, tp) {
newVal = e.currentTarget.value
tp.currentData().name.set(newVal);
}
});
我使用了一些“快捷方式”作为 Template.currentData()
并使用 this.name.get()
在助手上直接访问数据上下文。
您还可以直接访问模板实例作为事件的第二个参数:
'change input'(event, templateInstance) {}
我没有测试过,我只是给你一个想法。
希望这对您有帮助。
关于javascript - Meteor:如何获取对象属性的响应式(Reactive)父/子依赖模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40226822/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!