Angular 2 - bypassSecurityTrustHtml以及bypassSecurityTrustScript

时间:2017-07-25 12:40:08

标签: javascript html typescript angular2-template angular2-directives

我有一个按钮(在左侧导航侧),点击其中,我想在右侧显示模板(.html)(内容部分)。模板(.html)路径将从Web服务获取,并且每次都不同(因此没有硬编码值)。

该模板(.html)可以拥有自己的脚本标签。直到Angular 1.x使用ng-include标签很容易,但似乎Angular 2不再支持它了。

我可以使用以下解决方法显示HTML的内容(以及CSS) -

this.sanitizer.bypassSecurityTrustHtml(url);

但是Scripts没有被加载或执行。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

当您的HTML内容中包含单个脚本标记时,[innerHTML]选项可能对您有用。但是如果你有多个脚本标签要加载HTML内容而不是一个可行的选项,因为它不能保证加载和执行脚本的顺序。为此,您必须将HTML附加到任何元素中,并逐个加载脚本中的脚本。

以下解决方案正确解释 - https://ghinda.net/article/script-tags/

您的HTML应该看起来像 -

<div id="scripts"></div>
<div id="content"></div>

在第一个div中,所有脚本都会被附加,第二个,所有HTML内容都将被追加。

首先将HTML转换为字符串并将所有脚本标记推送到scriptArr []。

// run the scripts inside the dom node

    if (scriptArr.length > 0) {
        var $container = document.getElementById('scripts')
        $container.innerHTML = scriptArr
        runScripts($container)
    }

/* helpers */

// runs an array of async functions in sequential order
function seq(arr, callback, index) {
    // first call, without an index
    if (typeof index === 'undefined') {
        index = 0
    }

    arr[index](function () {
        index++
        if (index === arr.length) {
            callback()
        } else {
            seq(arr, callback, index)
        }
    })
}

// trigger DOMContentLoaded
function scriptsDone() {
    var DOMContentLoadedEvent = document.createEvent('Event')
    DOMContentLoadedEvent.initEvent('DOMContentLoaded', true, true)
    document.dispatchEvent(DOMContentLoadedEvent)
}

/* script runner */

function insertScript($script, callback) {
    var s = document.createElement('script')
    if (!s.type) {
        s.type = 'text/javascript'
    }
    if ($script.src) {
        s.onload = callback
        s.onerror = callback
        s.src = $script.src
    } else {
        s.textContent = $script.innerText
    }

    // re-insert the script tag so it executes.
    document.head.appendChild(s)

    // clean-up
    $script.parentNode.removeChild($script)

    // run the callback immediately for inline scripts
    if (!$script.src) {
        callback()
    }
}

// https://html.spec.whatwg.org/multipage/scripting.html
var runScriptTypes = [
            'application/javascript',
            'application/ecmascript',
            'application/x-ecmascript',
            'application/x-javascript',
            'text/ecmascript',
            'text/javascript',
            'text/javascript1.0',
            'text/javascript1.1',
            'text/javascript1.2',
            'text/javascript1.3',
            'text/javascript1.4',
            'text/javascript1.5',
            'text/jscript',
            'text/livescript',
            'text/x-ecmascript',
            'text/x-javascript'
        ]

function runScripts($container) {
    // get scripts tags from a node
    var $scripts = $container.querySelectorAll('script')
    var runList = []
    var typeAttr

    [].forEach.call($scripts, function ($script) {
        typeAttr = $script.getAttribute('type')

        // only run script tags without the type attribute
        // or with a javascript mime attribute value
        if (!typeAttr || (runScriptTypes ? runScriptTypes.indexOf(typeAttr) !== -1 : 'text/javascript')) {
            runList.push(function (callback) {
                insertScript($script, callback)
            })
        }
    })

    // insert the script tags sequentially
    // to preserve execution order
    seq(runList, scriptsDone)
}

let fragment = document.createRange()
    .createContextualFragment(html);

// fragment.baseURI = 'http://toolsqaplp/publish/Dev_Testing/n1d/DS_MAC/en/CATMMGSkillets_en.edu/CATMMGEdc0020_en.doc/src/';
document.getElementById('content')
    .appendChild(fragment);

答案 1 :(得分:0)

official document表示bypassSecurityTrustHtml()适用于您的情况。

我还假设您必须使用[innerHTML]属性来填充目标容器中的内容。

我有一些类似的要求,我需要单个HTML标记和单个脚本标记。我使用了bypassSecurityTrustResourceUrl()

return this.sanitizer.bypassSecurityTrustResourceUrl(url)

我非常确定它会在您获取可执行文件源时也适用于您的情况。

您还可以尝试梳理bypassSecurityTrustScript()bypassSecurityTrustHtml()