流星:强制渲染元素
Meteor: Force rendering an element
我有一个通用模板在我的应用中多次使用:
<template name="genericCollapse">
{{data-1}}
<a href=# class='collapsed' data-toggle='collapse'
data-target='#uniqueId'>Show/hide data-2</a>
<div class='collapse' id='uniqueId'>
{{data-2}}
</div>
</template>
通过点击应用中的其他位置,data-1 和 data-2 会同时更改(使用会话变量)。但是,如果模板已经在屏幕上,则只有 data-1 和 data-2 发生变化,但 div 的折叠状态保持(显然)不变。如果它之前打开过,它将保持打开状态。
我想实现的是,每当 data-1/data-2 发生变化时,div 和 a 都被迫再次处于折叠状态。
我尝试添加
<a href=# class='{{collapsed}}'
Template.genericCollapse.helpers({
collapsed () {return "collapsed " + Random.Id()},
})
这不仅非常丑陋,而且也没有帮助,因为 div 的 class 仍然保留 "collapse show",即使 div 有第二个助手,我无法摆脱 "show".
重新渲染整个模板也是可以接受的,但我很难确定调用 Blaze.render() 的父节点——它永远不一样——而且我也不确定放在哪里这样调用正确。
这是怎么做到的?
您可以通过将 class 返回到助手的元素来以流星的方式做到这一点,如下所示:
模板:
<template name="genericCollapse">
{{data-1}}
<a href=# class={{isCollapsed}} data-toggle='collapse'
data-target='#uniqueId'>Show/hide data-2</a>
...
...
</template>
帮手:
Template.genericCollapse.helpers({
isCollapsed: function(){
if()// logic to check if it needs to be collapsed
return "collapsed"
else
return "collapse"
}
});
看起来你在和 bootstrap 打架。当您单击 link 时, show
class 是由 bootstrap 添加的,对吗?因为此 class 不是由您的 html 标记设置的,所以您需要在基础数据更改时自行删除它。您可以通过观察数据的变化,然后直接修改 DOM。
这是一个基本示例:
Template.myTemplate.onCreated(function () {
const query = MyCollection.find({},{fields: {data-1: 1, data-2: 1}});
const handle = query.observeChanges({
changed(id, fields) {
$('.show').removeClass('show');
}
});
这假定存在一个包含您要控制的字段 data-1
和 data-2
的集合。如果您的 data-1
和 data-2
是执行某些计算的助手,那么您可能希望使用基于反应变量的 Tracker
来解决这个问题。
@Michel Floyd 关于战斗的说法是正确的 bootstrap。
但是,既然你说你正在使用 Session
变量,那么只需使用 auto运行 即可:
Template.genericCollapse.onRendered(function() {
this.autorun(() => {
const data1 = Session.get('data-1');
const data2 = Session.get('data-2');
if (data1 === someCondition || data2 === someOtherCondition) {
this.$('.collapse').collapse('show');
} else {
this.$('.collapse').collapse('hide');
}
});
任何时候 data-1
或 data-2
发生变化,此功能将重新 运行
非常感谢您的帮助!
@Michel Floyd 让我意识到我的问题不是由任何与 Meteor 相关的问题引起的,而是 bootstrap.
@Fred Stark 为解决方案添加了一个很好的变体,他使用 auto运行 更像 Meteor 风格,他使用 .collapse('hide') 而不是 .removeClass('show') 至少在 iOS.
上提供了一些不错的淡出效果
因为我混淆了几个问题,我会一一澄清:
查找触发器: 您可以按照建议使用 auto运行 或 observeChanges,但最终两者都不是必需的,因为总是会调用 Meteor 助手。
第一次尝试:
<a href=# class='{{collapsed}}'
Template.genericCollapse.helpers({
collapsed () {return "collapsed"},
})
当模板中的某些内容发生变化时,此助手中的代码将始终 运行。如果 data-1 或 data-2 由于任何原因发生变化,代码将被执行,所以这是我的触发器。
正确使用助手: 第一次尝试在 html 上没有任何作用,因为空格键 {{collapsed}} 没有改变它的内容。尽管执行了帮助程序代码,但 return 值不会更改,因此对 html 端没有影响。
为了看到任何变化,return 值每次都必须不同。
第二次尝试:
Template.genericCollapse.helpers({
collapsed () {return "collapsed " + Random.Id()},
})
正如我已经说过的那样丑陋,但至少它为 a 设置了正确的 class。
去掉"show":米歇尔来了:因为div中的"show"是由Bootstrap控制的,你不能用任何类型的 spacebar/helper 来控制它——但是用 javascript。
第三次尝试:
Template.genericCollapse.helpers({
collapsed () {
$('.show').removeClass('show');
return "collapsed " + Random.Id()},
})
这有效!如果存在具有 class "show" 的其他元素,可能有必要缩小“.show”的范围,但这是可行的方法。
美化: 将 Random.Id() 作为 class 仍然很糟糕。因此,让我们像对待 div 一样对待 a。此外,我们应该使用 "uniqueId" 作为两者的标识符。
第四次尝试:
Template.genericCollapse.helpers({
collapsed () {
$('[data-target="#uniqueId"]').addClass('collapsed');
$('#uniqueId').removeClass('show');
return "collapsed"},
})
让它闪亮: 助手 {{collapsed}} 不再需要 return 任何值,这一切都用 javascript.我们只需要触发功能,所以这是最终代码:
<template name="genericCollapse">
{{data-1}}
<a href=# class='collapsed' data-toggle='collapse' {{hook}}
data-target='#uniqueId'>Show/hide data-2</a>
<div class='collapse' id='uniqueId'>
{{data-2}}
</div>
</template>
Template.genericCollapse.helpers({
hook () {
$('[data-target="#uniqueId"]').addClass('collapsed');
$('#uniqueId').removeClass('show');
}
})
很有魅力。
我有一个通用模板在我的应用中多次使用:
<template name="genericCollapse">
{{data-1}}
<a href=# class='collapsed' data-toggle='collapse'
data-target='#uniqueId'>Show/hide data-2</a>
<div class='collapse' id='uniqueId'>
{{data-2}}
</div>
</template>
通过点击应用中的其他位置,data-1 和 data-2 会同时更改(使用会话变量)。但是,如果模板已经在屏幕上,则只有 data-1 和 data-2 发生变化,但 div 的折叠状态保持(显然)不变。如果它之前打开过,它将保持打开状态。
我想实现的是,每当 data-1/data-2 发生变化时,div 和 a 都被迫再次处于折叠状态。 我尝试添加
<a href=# class='{{collapsed}}'
Template.genericCollapse.helpers({
collapsed () {return "collapsed " + Random.Id()},
})
这不仅非常丑陋,而且也没有帮助,因为 div 的 class 仍然保留 "collapse show",即使 div 有第二个助手,我无法摆脱 "show".
重新渲染整个模板也是可以接受的,但我很难确定调用 Blaze.render() 的父节点——它永远不一样——而且我也不确定放在哪里这样调用正确。
这是怎么做到的?
您可以通过将 class 返回到助手的元素来以流星的方式做到这一点,如下所示:
模板:
<template name="genericCollapse">
{{data-1}}
<a href=# class={{isCollapsed}} data-toggle='collapse'
data-target='#uniqueId'>Show/hide data-2</a>
...
...
</template>
帮手:
Template.genericCollapse.helpers({
isCollapsed: function(){
if()// logic to check if it needs to be collapsed
return "collapsed"
else
return "collapse"
}
});
看起来你在和 bootstrap 打架。当您单击 link 时, show
class 是由 bootstrap 添加的,对吗?因为此 class 不是由您的 html 标记设置的,所以您需要在基础数据更改时自行删除它。您可以通过观察数据的变化,然后直接修改 DOM。
这是一个基本示例:
Template.myTemplate.onCreated(function () {
const query = MyCollection.find({},{fields: {data-1: 1, data-2: 1}});
const handle = query.observeChanges({
changed(id, fields) {
$('.show').removeClass('show');
}
});
这假定存在一个包含您要控制的字段 data-1
和 data-2
的集合。如果您的 data-1
和 data-2
是执行某些计算的助手,那么您可能希望使用基于反应变量的 Tracker
来解决这个问题。
@Michel Floyd 关于战斗的说法是正确的 bootstrap。
但是,既然你说你正在使用 Session
变量,那么只需使用 auto运行 即可:
Template.genericCollapse.onRendered(function() {
this.autorun(() => {
const data1 = Session.get('data-1');
const data2 = Session.get('data-2');
if (data1 === someCondition || data2 === someOtherCondition) {
this.$('.collapse').collapse('show');
} else {
this.$('.collapse').collapse('hide');
}
});
任何时候 data-1
或 data-2
发生变化,此功能将重新 运行
非常感谢您的帮助!
@Michel Floyd 让我意识到我的问题不是由任何与 Meteor 相关的问题引起的,而是 bootstrap.
@Fred Stark 为解决方案添加了一个很好的变体,他使用 auto运行 更像 Meteor 风格,他使用 .collapse('hide') 而不是 .removeClass('show') 至少在 iOS.
上提供了一些不错的淡出效果因为我混淆了几个问题,我会一一澄清:
查找触发器: 您可以按照建议使用 auto运行 或 observeChanges,但最终两者都不是必需的,因为总是会调用 Meteor 助手。 第一次尝试:
<a href=# class='{{collapsed}}'
Template.genericCollapse.helpers({
collapsed () {return "collapsed"},
})
当模板中的某些内容发生变化时,此助手中的代码将始终 运行。如果 data-1 或 data-2 由于任何原因发生变化,代码将被执行,所以这是我的触发器。
正确使用助手: 第一次尝试在 html 上没有任何作用,因为空格键 {{collapsed}} 没有改变它的内容。尽管执行了帮助程序代码,但 return 值不会更改,因此对 html 端没有影响。 为了看到任何变化,return 值每次都必须不同。 第二次尝试:
Template.genericCollapse.helpers({
collapsed () {return "collapsed " + Random.Id()},
})
正如我已经说过的那样丑陋,但至少它为 a 设置了正确的 class。
去掉"show":米歇尔来了:因为div中的"show"是由Bootstrap控制的,你不能用任何类型的 spacebar/helper 来控制它——但是用 javascript。 第三次尝试:
Template.genericCollapse.helpers({
collapsed () {
$('.show').removeClass('show');
return "collapsed " + Random.Id()},
})
这有效!如果存在具有 class "show" 的其他元素,可能有必要缩小“.show”的范围,但这是可行的方法。
美化: 将 Random.Id() 作为 class 仍然很糟糕。因此,让我们像对待 div 一样对待 a。此外,我们应该使用 "uniqueId" 作为两者的标识符。 第四次尝试:
Template.genericCollapse.helpers({
collapsed () {
$('[data-target="#uniqueId"]').addClass('collapsed');
$('#uniqueId').removeClass('show');
return "collapsed"},
})
让它闪亮: 助手 {{collapsed}} 不再需要 return 任何值,这一切都用 javascript.我们只需要触发功能,所以这是最终代码:
<template name="genericCollapse">
{{data-1}}
<a href=# class='collapsed' data-toggle='collapse' {{hook}}
data-target='#uniqueId'>Show/hide data-2</a>
<div class='collapse' id='uniqueId'>
{{data-2}}
</div>
</template>
Template.genericCollapse.helpers({
hook () {
$('[data-target="#uniqueId"]').addClass('collapsed');
$('#uniqueId').removeClass('show');
}
})
很有魅力。