Nested Javascript Templates … is this possible / valid?

前端 未结 6 1801
小蘑菇
小蘑菇 2020-12-03 18:21

Is it possible to have nested JavaScript template tags e.g.



        
相关标签:
6条回答
  • 2020-12-03 18:35

    You can use <style type="text/html"></style> or <noscript></noscript> to wrap your <script></script> tag.

    I think <noscript> is better than <style>

    example:

    <noscript id="s">
      <div class="r">
        <p>{%= o.rand %}</p>
        <script>
          console.log('sdf');
        </script>
      </div>
    </noscript>

    <style id="s" type="text/html">
      <div class="r">
        <p>{%= o.rand %}</p>
        <script>
          console.log('sdf');
        </script>
      </div>
    </style>

    0 讨论(0)
  • 2020-12-03 18:39

    Try this:

    <script id="Product" type="text/html">
    <!--
        <div class="product">
            ....
            <div class="features">
                <script id="Features" type="text/html">
                    <div class="feature">
                        ...
                    </div>
                </script>
            </div>
            ...
        </div>
    -->
    </script>
    

    When you need to get it:

    document.getElementById("Product").text.replace(/(?:^\s*<!--\s*)|(?:\s*-->\s*$)/g, "");
    
    0 讨论(0)
  • 2020-12-03 18:41

    Yes, it is possible to have nested <script> tags (with XHTML application/xhtml+xml):

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <title>XHTML nested &lt;script&gt;</title>
    </head>
    <body>
      <script id="Product" type="text/html">
        <div class="product">
          ....
          <div class="features">
            <script id="Features" type="text/html">nested
              <div class="feature">
                ...
              </div>
            </script>
          </div>
          ...
        </div>
      </script>
    </body>
    </html>
    

    Code snippet does not support XHTML, I have to use iframe with data URL:

    <iframe src="data:application/xhtml+xml,%3Chtml%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20contenteditable%3D%22true%22%3E%3Chead%3E%3Ctitle%3EXHTML%20nested%20%26lt%3Bscript%26gt%3B%3C%2Ftitle%3E%3C%2Fhead%3E%3Cbody%3E%3Cstyle%3Estyle%2C%20script%20%7B%20display%3A%20block%3B%20font-family%3A%20monospace%3B%20white-space%3A%20pre%3B%20padding-left%3A%2010px%20%7D%0Astyle%20%7B%20border-left%3A%2010px%20solid%20%2398A6C0%20%7D%0Ascript%20%7B%20border-left%3A%2010px%20solid%20%23D6F034%20%7D%3C%2Fstyle%3E%3Cscript%20id%3D%22Product%22%20type%3D%22text%2Fhtml%22%3Eouter%0A%20%20%20%20%3Cdiv%20class%3D%22product%22%3E%0A%20%20%20%20%20%20%20%20....%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22features%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cscript%20id%3D%22Features%22%20type%3D%22text%2Fhtml%22%3Einner%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22feature%22%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fscript%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%3C%2Fdiv%3E%0A%3C%2Fscript%3E%3C%2Fbody%3E%3C%2Fhtml%3E" width="100%"></iframe>

    Yes, it is possible to have nested <script> tags in HTML DOM:

    productScript = document.createElement('script')
    productScript.setAttribute('id', 'Product')
    productScript.setAttribute('type', 'text/html')
    productScript.appendChild(document.createTextNode('outer'))
    
    product = document.createElement('div')
    product.setAttribute('class', 'product')
    product.appendChild(document.createTextNode(`
            ....
            `))
    
    features = document.createElement('div')
    features.setAttribute('class', 'features')
    
    featuresScript = document.createElement('script')
    featuresScript.setAttribute('id', 'Features')
    featuresScript.setAttribute('type', 'text/html')
    featuresScript.appendChild(document.createTextNode('inner'))
    
    feature = document.createElement('div')
    feature.setAttribute('class', 'feature')
    feature.appendChild(document.createTextNode(`
            ...
        `))
    
    featuresScript.appendChild(feature)
    features.appendChild(featuresScript)
    product.appendChild(document.createTextNode(`
            ...
        `))
    product.appendChild(features)
    productScript.appendChild(product)
    document.body.appendChild(productScript)
    script[type="text/html"] {
      display: block;
      font-family: monospace;
      white-space: pre;
      padding-left: 10px;
      border-left: 10px solid #D6F034
    }

    No, it is not possible to have nested <script> tags in HTML serialization. Its content is not parsed:

    let product = document.getElementById('Product')
    console.log(product.textContent)
    <script id="Product" type="text/html">
        <div class="product">
            ....
            <div class="features">
                <script id="Features" type="text/html">nested
                    <div class="feature">
                        ...
                    </div>
                </script>
            </div>
            ...
        </div>
    </script>

    0 讨论(0)
  • 2020-12-03 18:42

    You can't nest script tags. The way script tags work, the browser reads the opening tag and then starts building up a string of the code therein without interpreting that code at all. It stops doing that the first time it sees the exact sequence < / s c r i p t >. The browser will always stop at the first of those it finds, and crucially it ignores any intervening opening tag sequence, like < s c r i p t >. This is because the browser doesn't parse the script code, that's not its job. It's a separation of concerns thing. (script tags probably shouldn't be tags at all, but rather something more like a CDATA structure. But they're what we have.)

    E.g., from the browser's point of view:

    <script id="Product" type="text/html">              SCRIPT STARTS HERE
        <div class="product">                           SCRIPT CODE CONTINUES
            ....                                        SCRIPT CODE CONTINUES
            <div class="features">                      SCRIPT CODE CONTINUES
                <script id="Features" type="text/html"> SCRIPT CODE CONTINUES (*NOT* START OF SCRIPT)
                    <div class="feature">               SCRIPT CODE CONTINUES
                        ...                             SCRIPT CODE CONTINUES
                    </div>                              SCRIPT CODE CONTINUES
                </script>                               SCRIPT ENDS
            </div>                                      ENDING `div` TAG (probably mis-matched)
            ...
        </div>
    </script>                                           MIS-MATCHED ENDING `script` TAG
    

    Now, if you're using a server-side templating engine of some kind that will replace those script tags with markup and then send the updated markup to the browser, then it's up to the templating engine whether it supports nesting. Browsers do not.

    0 讨论(0)
  • 2020-12-03 18:43

    Are okay with using jQuery? If so, this very possible (and even, dare I say, common):

    http://blog.reybango.com/2010/07/12/jquery-javascript-templates-tutorial-nesting-templates/

    0 讨论(0)
  • 2020-12-03 18:56

    Sometimes I think I want nested scipt tags for templating, but this is what you have to do instead:

    Script 1

     <script id="Product" type="text/html">
         <div class="product">
             ....
             <div class="features">
                 <!-- INSERT FEATURES HERE -->   
             </div>
             ...
         </div>
     </script>
    

    Script 2

     <script id="Product_Features" type="text/html">
         <div class="feature">
    
         </div>
     </script>
    

    You can 'namespace' the ID if you really want, to indicate it is a 'child' template. This makes it clearer is it not intended to be used by itself (obviously this is up to you if it makes sense or not).

    After reading T.J.s answer this became the only obvious alternative to what I originally thought I wanted (nested scripts).

    However, you probably don't need nested templates unless you need to make a choice as to which 'child' template is used. If there's only one possible layout for the child template then just use a 'foreach' according to your template engine.

    0 讨论(0)
提交回复
热议问题