我是 的新手 meteor /火焰 但这就是我公司正在使用的。
我很难理解 Blaze 如何决定渲染基于 ReactiveDict
的内容。
TL;博士
我从 ReactiveDict
创建了一些子模板父数组中的数组。当 ReactiveDict
时,子模板中的数据不会刷新。变化,我不明白为什么。
我可能对 Blaze 渲染有误解。你能帮帮我吗?
家长
父 Html 模板
<template name="parent">
{{#each child in getChildren}}
{{> childTemplate (childArgs child)}}
{{/each}}
</template>
父 Javascript
react 变量
该模板呈现来自
getChildren
的子模板仅检索 ReactiveDict
的助手.// Child data object
const child = () => ({
id: uuid.v4(),
value: ""
});
// Create a reactive dictionary
Template.parent.onCreated(function() {
this.state = new ReactiveDict();
this.state.setDefault({ children: [child()] });
});
// Return the children from the reactive dictionary
Template.parent.helpers({
getChildren() {
return Template.instance().state.get('children');
}
});
子模板参数(来自 父 模板)
父模板为子模板提供了一些用于设置默认值和回调的数据。
每个都使用
childArgs
实例化使用 child 的 id
的函数设置正确的数据和回调。单击
add
时按钮,它将一个 child 添加到 children
ReactiveDict
中的数组.单击
delete
时按钮,它会从 children
中删除 child ReactiveDict
中的数组.Template.parent.helpers({
// Set the children arguments: default values and callbacks
childArgs(child) {
const instance = Template.instance();
const state = instance.state;
const children = state.get('children');
return {
id: child.id,
// Default values
value: child.value,
// Just adding a child to the reactive variable using callback
onAddClick() {
const newChildren = [...children, child()];
state.set('children', newChildren);
},
// Just deleting the child in the reactive variable in the callback
onDeleteClick(childId) {
const childIndex = children.findIndex(child => child.id === childId);
children.splice(childIndex, 1);
state.set('children', children);
}
}
}
})
child
子 html 模板
该模板显示来自父级和 2 个按钮的数据,
add
和 delete
.<template name="child">
<div>{{value}}</div>
<button class="add_row" type="button">add</button>
<button class="delete_row" type="button">delete</button>
</template>
子 javascript(事件)
这里调用的两个函数是作为参数从 传递的回调函数。家长 模板。
// The two functions are callbacks passed as parameters to the child template
Template.child.events({
'click .add_row'(event, templateInstance) {
templateInstance.data.onAddClick();
},
'click .delete_row'(event, templateInstance) {
templateInstance.data.onDeleteClick(templateInstance.data.id);
},
问题
我的问题是当我删除一个 child 时(使用回调来设置
ReactiveDict
就像 onAddClick()
函数),我的数据没有正确呈现。文本示例:
我添加这样的行。
child 1 | value 1
child 2 | value 2
child 3 | value 3
当我删除
child 2
,我明白了:child 1 | value 1
child 3 | value 2
我想要这个:
child 1 | value 1
child 3 | value 3
我正在初始化
child
来自 childArgs
的数据在 Template.child.onRendered()
功能。getChildren()
删除 child
时调用函数在 ReactiveDict
并且我在变量中有正确的数据( children
中的 ReactiveDict
)。 onRendered()
永远不会被调用( child 的 onCreated()
函数也不是)。这意味着为 显示的数据 child 模板错误。 图片示例
我正在添加图片以帮助理解:
正确的html
显示的 HTML 是正确的:我有 3 个 child ,我删除了第二个。在我的 HTML 中,我可以看到显示的两个 child 在其 div 中具有正确的 ID。然而显示的数据是错误的。
过时的数据
我已经删除了第一张照片中的第二个 child 。显示的 child 应该是第一个和第三个。
在控制台日志中,我的数据是正确的。红色数据是第一位的。紫色是第三个。
然而我们可以看到被删除的 child 的数据显示出来了(
asd
和 asdasd
)。删除标签时,我可以在日志中看到第二个 child 的 ID,尽管它不应该再存在了。第二个 child ID 为绿色。我可能误会了什么。你能帮帮我吗?
最佳答案
我不知道从哪里开始,但有很多错误,我宁愿在这里提供一个运行中的解决方案并附上评论。
首先是each
函数应该正确地传递 id 而不是整个 child 或 find
会导致错误:
<template name="parent">
{{#each child in getChildren}}
{{#with (childArgs child.id)}}
{{> childTemplate this}}
{{/with}}
{{/each}}
</template>
在帮助程序中,您可以避免调用过多的
Template.instance()
使用 lexical scoping 函数:childArgs (childId) {
const instance = Template.instance()
const children = instance.state.get('children')
const childData = children.find(child => child.id === childId)
const value = {
// Default values
data: childData,
// Just adding a child to the reactive variable using callback
onAddClick () {
const children = instance.state.get('children')
const length = children ? children.length : 1
const newChild = { id: `data ${length}` }
const newChildren = [...children, newChild]
instance.state.set('children', newChildren)
},
// Just deleting the child in the reactive variable in the callback
onDeleteClick (childId) {
const children = instance.state.get('children')
const childIndex = children.findIndex(child => child.id === childId)
children.splice(childIndex, 1)
instance.state.set('children', children)
}
}
return value
}
然后注意,在事件回调
'click .delete_row'
您正在使用 templateInstance.data.id
但这是 总是 undefined
与您当前的结构。应该是 templateInstance.data.data.id
因为data
总是为模板实例中的所有数据定义,如果您命名属性 data
那么您必须通过 data.data
访问它:Template.childTemplate.events({
'click .add_row' (event, templateInstance) {
templateInstance.data.onAddClick()
},
'click .delete_row' (event, templateInstance) {
templateInstance.data.onDeleteClick(templateInstance.data.id)
}
})
现在,为什么您的数据被奇怪地排序也是有道理的。看看
onDeleteClick
打回来:onDeleteClick (childId) {
// childId is always undefined in your code
const children = instance.state.get('children')
const childIndex = children.findIndex(child => child.id === childId)
// childIndex is always -1 in your code
// next time make a dead switch in such situations:
if (childIndex === -1) {
throw new Error(`Expected child by id ${childId}`)
}
children.splice(childIndex, 1)
// if index is -1 this removes the LAST element
instance.state.set('children', children)
}
所以你的问题是拼接行为并将未经检查的索引传递给拼接:
The index at which to start changing the array. If greater than the length of the array, start will be set to the length of the array. If negative, it will begin that many elements from the end of the array (with origin -1, meaning -n is the index of the nth last element and is therefore equivalent to the index of array.length - n). If array.length + start is less than 0, it will begin from index 0.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice
关于javascript - 误解 `each...in` 用 react 变量渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59248122/