如何在 Handlebars 模板上下文中传递 JQuery 实例?
How to pass JQuery instance in a Handlebars template context?
我想使用 Handlebars 插入嵌套元素,这些元素可以是 jQuery 元素,例如:
var ul = Handlebars.compile($('#ul').html());
var li = Handlebars.compile($('#li').html());
let el = $(li({slot: 'Hello World!'})).data('foo', Object([42]))
$('#main').append(ul({slot: el}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js"></script>
<div id="main" class="container">
</div>
<script id="ul" type="text/x-handlebars-template">
<ul>
{{{slot}}}
</ul>
</script>
<script id="li" type="text/x-handlebars-template">
<li>
{{slot}}
</li>
</script>
不幸的是,我正在努力解决两个问题:
- Handlebars 期望在上下文中包含 html 内容,因此我松开了
data-foo
。
- 使用
{{{slot}}}
可能不安全
还有什么选择?
要达到预期结果,请使用以下选项
- 使用 attr 而不是 data(),因为它只存储值,不会在 DOM 上设置属性
参考此 link 了解更多详情 - jQuery data attr not setting
- 拆分附加 ul 和 el
代码示例 - https://codepen.io/nagasai/pen/PvrLba?editors=1010
var ul = Handlebars.compile($('#ul').html());
var li = Handlebars.compile($('#li').html());
let el = $(li({slot: 'Hello World!'})).attr('data-foo', Object([42]))
$('#main').append(ul)
$('#main ul').append(el)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js"></script>
<div id="main" class="container">
</div>
<script id="ul" type="text/x-handlebars-template">
<ul>
{{{slot}}}
</ul>
</script>
<script id="li" type="text/x-handlebars-template">
<li>
{{slot}}
</li>
</script>
此问题的一个解决方案是编写一个包装器,在模板 context
中查找 jQuery
个实例。它用纯文本唯一标识符替换每个实例,然后将 jQuery 个实例插入到呈现的模板中:
Handlebars.jQueryCompile = (template) => {
let jQueryObjects = []
let tag = id => `jQueryObject(${id})`
let alter = (obj) => {
if (!(obj instanceof Object)) return
for (var prop in obj) {
if (obj[prop] instanceof jQuery) {
jQueryObjects.push(obj[prop])
obj[prop] = tag(jQueryObjects.length - 1)
} else {
alter(obj[prop])
}
}
}
return (context) => {
alter(context)
let obj = $(template(context))
jQueryObjects.forEach((jq, id) => {
obj.find('*:contains("' + tag(id) + '")').html('').append(jq)
})
return obj
}
}
这是您更新后的示例:
var ul = Handlebars.jQueryCompile($('#ul').html());
var li = Handlebars.jQueryCompile($('#li').html());
let el = $(li({slot: 'Hello World!'})).data('foo', Object([42]))
$('#main').append(ul({slot: el}))
请注意,您不需要使用 {{{}}}
胡须,因为插入的是纯文本而不是 html 元素。
我想使用 Handlebars 插入嵌套元素,这些元素可以是 jQuery 元素,例如:
var ul = Handlebars.compile($('#ul').html());
var li = Handlebars.compile($('#li').html());
let el = $(li({slot: 'Hello World!'})).data('foo', Object([42]))
$('#main').append(ul({slot: el}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js"></script>
<div id="main" class="container">
</div>
<script id="ul" type="text/x-handlebars-template">
<ul>
{{{slot}}}
</ul>
</script>
<script id="li" type="text/x-handlebars-template">
<li>
{{slot}}
</li>
</script>
不幸的是,我正在努力解决两个问题:
- Handlebars 期望在上下文中包含 html 内容,因此我松开了
data-foo
。 - 使用
{{{slot}}}
可能不安全
还有什么选择?
要达到预期结果,请使用以下选项
- 使用 attr 而不是 data(),因为它只存储值,不会在 DOM 上设置属性
参考此 link 了解更多详情 - jQuery data attr not setting
- 拆分附加 ul 和 el
代码示例 - https://codepen.io/nagasai/pen/PvrLba?editors=1010
var ul = Handlebars.compile($('#ul').html());
var li = Handlebars.compile($('#li').html());
let el = $(li({slot: 'Hello World!'})).attr('data-foo', Object([42]))
$('#main').append(ul)
$('#main ul').append(el)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js"></script>
<div id="main" class="container">
</div>
<script id="ul" type="text/x-handlebars-template">
<ul>
{{{slot}}}
</ul>
</script>
<script id="li" type="text/x-handlebars-template">
<li>
{{slot}}
</li>
</script>
此问题的一个解决方案是编写一个包装器,在模板 context
中查找 jQuery
个实例。它用纯文本唯一标识符替换每个实例,然后将 jQuery 个实例插入到呈现的模板中:
Handlebars.jQueryCompile = (template) => {
let jQueryObjects = []
let tag = id => `jQueryObject(${id})`
let alter = (obj) => {
if (!(obj instanceof Object)) return
for (var prop in obj) {
if (obj[prop] instanceof jQuery) {
jQueryObjects.push(obj[prop])
obj[prop] = tag(jQueryObjects.length - 1)
} else {
alter(obj[prop])
}
}
}
return (context) => {
alter(context)
let obj = $(template(context))
jQueryObjects.forEach((jq, id) => {
obj.find('*:contains("' + tag(id) + '")').html('').append(jq)
})
return obj
}
}
这是您更新后的示例:
var ul = Handlebars.jQueryCompile($('#ul').html());
var li = Handlebars.jQueryCompile($('#li').html());
let el = $(li({slot: 'Hello World!'})).data('foo', Object([42]))
$('#main').append(ul({slot: el}))
请注意,您不需要使用 {{{}}}
胡须,因为插入的是纯文本而不是 html 元素。