我正在寻找一种使用Reactive Var管理HTML标签类型的解决方案。我看了所有Blaze文档,但什么也没发现。
我想在更新布尔型ReactiveVar时将标签从div
更改为form
。
Template.MyExample.onCreated(function() {
this.is_form = new ReactiveVar(false)
})
Template.MyExample.helpers({
getTag() {
return Template.instance().is_form.get() ? 'form' : 'div'
}
})
这显然行不通:
<Template name="MyExample">
<{{getTag}}>
</{{getTag}}>
</Template>
我找到的“最佳”方法是创建一个标记模板,并一次列出每种情况,但是我不喜欢这种解决方案。
Template.MyExample.onCreated(function() {
this.is_form = new ReactiveVar(false)
})
Template.MyExample.helpers({
getTag() {
return Template.instance().is_form.get() ? 'form' : 'div'
}
})
Template.MyExample.events({
'click .switch'(e, instance) {
e.preventDefault()
instance.is_form.set(!instance.is_form.get())
}
})
Blaze模板:
<Template name="MyExample">
<div>
<a href="#" class="switch">Switch type</a>
{{#MyTag tag=getTag}}
Parent tag is {{getTag}}
{{/MyTag}}
{{#MyTag tag="a" attributes=(object href="#" target="_blank")}}
Link
{{/MyTag}}
</div>
</Template>
<Template name="MyTag">
{{#if equals tag 'form'}}
<form {{attributes}}>
{{> Template.contentBlock }}
</form>
{{else if equals tag 'a'}}
<a {{attributes}}>
{{> Template.contentBlock }}
</a>
<!-- and more and more.... -->
{{else}}
<div {{attributes}}>
{{> Template.contentBlock }}
</div>
{{/if}}
</Template>
所需的助手:
Template.registerHelper('object', function({hash}) {
return hash;
})
Template.registerHelper('equals', function (a, b) {
return a === b
})
这是有效的,但我想知道对于Meteor(和DOM更新)是否有太多帮助。此解决方案是像简单的{{#if}}...{{/if}}
一样工作还是更笨重?
答案 0 :(得分:0)
Blaze基本上不支持您请求的功能。虽然静态代码生成器可以轻松地包含动态标签,但这在运行时非常困难,在这种情况下,您必须处理DOM树,该树的元素的标签类型在设计上是不可变的。
我首先想到了一种解决方法,该方法使用onRendered
的{{1}}中的jQuery使用子交换:
MyTag
但这不幸的是不起作用,因为内容框失去了它的反应性,而当前Template的jQuery实例失去了它对根元素的作用域。我只是在这里添加它,以防有人赶上并找到可行的解决方案。
现在,仍然有一种使用动态模板的解决方案:
Template.MyTag.onRendered(function () {
const instance = this
instance.autorun(() => {
const data = Template.currentData()
const attributes = data.attributes || {}
const elementName = data.tag
const refTag = instance.$('.my-tag-ref')
const newTag = $(`<${elementName}>${refTag.html()}</${elementName}>`)
Object.keys(attributes).forEach(attKey => newTag.attr(attKey, attributes[ attKey ]))
newTag.addClass('my-tag-ref')
refTag.replaceWith(newTag)
})
})
如您所见,缺点显然是您必须定义许多新模板。优点是,您不必再使用那么多的if / else,它就会使您支付更多的钱,而您必须在代码中包含<Template name="MyTag">
{{#Template.dynamic template=getTemplate data=getData}}
{{> Template.contentBlock }}
{{/Template.dynamic}}
</Template>
<template name="mytaga">
<a {{attributes}}>
{{> Template.contentBlock }}
</a>
</template>
<template name="mytagform">
<form {{attributes}}>
{{> Template.contentBlock }}
</form>
</template>
<template name="mytagdiv">
<div {{attributes}}>
{{> Template.contentBlock }}
</div>
</template>
。
各个助手如下所示:
MyTag
这是有效的,但我想知道对于Meteor(和DOM更新)是否有太多帮助。此解决方案是否像简单的{{#if}} ... {{/ if}}那样工作?还是比较笨重?
总体来说,Blaze比React或Vue慢。但是,渲染仅在反应性数据更新时才更新,因此与要触发的更新量一样重。