如何在Handlebars模板上下文中传递JQuery实例?

时间:2019-06-07 12:27:29

标签: javascript jquery html handlebars.js

我想使用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>

不幸的是,我正在努力解决两个问题:

  • 把手希望上下文中包含html内容,因此我放弃了data-foo
  • 使用{{{slot}}}可能不安全

有什么选择?

2 个答案:

答案 0 :(得分:1)

要获得预期结果,请在

下使用以下选项
  1. 使用 attr 代替 data(),因为它仅存储值,并且不会在DOM上设置属性

请参阅此链接以获取更多详细信息-jQuery data attr not setting

  1. 分割追加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>

答案 1 :(得分:0)

解决此问题的一种方法是编写一个包装,在模板jQuery中查找context个实例。它将每个实例替换为纯文本唯一标识符,然后将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元素,因此不需要使用{{{}}}胡子。