how to stop durandal / jquery stripping out script

2019-01-26 17:51发布

问题:

I know there are better patterns but in this case there's some legacy code that we'd like to move to a view. This html has a

<script src="binding.js"></script>

that needs to run after the page renders and displays.

I hoped to do this with a <script src=""> tag, but the tag seems to be getting stripped out.

How do we either get the script tag to render, or do a work-around with durandal?

Example html:

<div>
    <link rel="stylesheet" href="/Content/stylesheet1.css"/>
    <link rel="stylesheet" href="/Content/stylesheet2.css"/>
    <header>
        <h1>heading</h1>
        <h2>sub heading</h2>
    </header>

    <section>
    </section>

    <footer>              
    </footer>
    <script src="dobinding.js"></script>    
</div>

This is helpful:

http://knockoutjs.com/documentation/custom-bindings.html

回答1:

You could use a custom KnockOut binding for this.

Here's a really simple binding - keep in mind this is just an idea:

ko.bindingHandlers.script = {
    update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var scriptName = ko.utils.unwrapObservable(valueAccessor());
        $(element).html("<script src='" + scriptName + "'></script>");
    }
};

In your view (.html file):

<div data-bind="script:'dobinding.js'"></div>

I tested this, and I found that the script is indeed injected, parsed, and executed, but it doesn't stay loaded in the DOM. That may or may not be an issue for you.

Seems that stripping the tags may be a Durandal-specific thing. I haven't figured out the cause yet, but I'll update if I get a chance to dig into it.



回答2:

I believe that the durandal view composition engine only uses the first html element in a view and ignores everything else. So if your script tag is outside the main container in your view I think it gets dropped.

Can you post some html/js for review?



回答3:

If it's not already, you could wrap whatever is going on inside the script in a function (let's call it doBindings) and then embed the script in your index.html file (or equivalent), alongside Knockout, JQuery etc.

Then, in whatever view you need to get that code running in, add a viewAttached method to the view model and make the call to doBindings:

activate: function() {
   ...
}
viewAttached: function() {
   doBindings();
}

That will invoke the function when the view is loaded and the DOM is accessible.

Solution here: Insert script tag in Durandal, but an answer here would have saved me some additional searching, so added here too.