Vue: [Discussion] 2.0 'replace' option deprecation

Created on 29 Apr 2016  路  7Comments  路  Source: vuejs/vue

I noticed 'replace' has been deprecated. Definitely agree that components should have only one root element, however we have other reasons for using replace.

Behavior questions:

  • What is the behavior moving forward? Currently the default value is true. Will this assumption be baked in?
  • How will this interact with the restricted elements in the dom? eg, those outlined in template parsing. Specifically, given this component template:

    <!-- my-component -->
    <div class="foo"><slot></slot></div>
    

    And this parent template:

    <table>
    <tr><th class="bar" is="my-component">stuff</th></tr>
    </table>
    

    What happens to the th element? Wouldn't replacing it with the div lead to invalid html? We use replace false to get around this, resulting in:

    <table>
    <tr><th class="bar" is="my-component"><div class="foo">stuff</div></th></tr>
    </table>
    

    Our usage:

  • From a preference standpoint, I'd like to point you to this comment here :wink:. It's definitely a stylistic preference and could live without. I also find it easier to grep the dom for my-component vs some div.

  • More important to us, replace is necessary for our data table mixin. We can easily insert sorting behavior to any column by just adding is="sort-controls" and a sort key.

    <!-- sort-controls component -->
    <div class="sort-controls no-wrap" v-on:click="pushSort(sortKey)">
      <slot></slot>
      <!-- Other details -->
      ...
    </div>
    
    <!-- example usage -->
    <table class="table table-bordered table-striped table-hover">
      <tr>
          <th class="col-xs-2">Link</th>
          <th class="col-xs-5" is="sort-controls" key="name">Company</th>
          <th class="col-xs-5" is="sort-controls" key="employeeCount">Employees</th>
      </tr>
    
      <tr v-for="company in companies">
          ...
      </tr>
    </table>
    

    It's a terse solution that breaks when replace: true, as the parent th is lost.

Regardless of our specific usage, how do you extend restricted elements when replace: true?

Most helpful comment

@yyx990803 can you point me to the reasoning wherein the replace option was removed?

I used to use the component's tag to act as the mounting point.

The _customElement_ acts as the single node mounting point. Is the virtual dom preventing this behavior? I find it quite cumbersome to continually have to add a surrounding div around the nodes in my template. It would be cleaner to keep the components as their node names per a WebComponents spec. Easier to style around as well.

All 7 comments

Yes, 2.0 assumes the behavior of replace always being true.

Also, 2.0 no longer relies on the actual DOM for template parsing, so as long as you are not using direct DOM elements as your template source, you will no longer be subject to any of the parsing limitations.

As for your example, you can just use <th></th> as your component root node.

As for your example, you can just use as your component root node.

This limits the component to one tag type though. eg, can't use with td. With replace: false, this isn't an issue. It is a limitation, but that said I can't really think of a practical case where this would be necessary.

What about classes and other attributes though - are those preserved?

Everything else works as before.

Ohhh. I just messed around with a fiddle. I didn't realize that the attributes were merged. That works for us.

I just poked through the API reference, and it doesn't explain what happens with element attributes - only the inner content. Maybe this could be better clarified?

PR submitted to the docs repo

@yyx990803 can you point me to the reasoning wherein the replace option was removed?

I used to use the component's tag to act as the mounting point.

The _customElement_ acts as the single node mounting point. Is the virtual dom preventing this behavior? I find it quite cumbersome to continually have to add a surrounding div around the nodes in my template. It would be cleaner to keep the components as their node names per a WebComponents spec. Easier to style around as well.

It seems like a bad assumption to completely remove the option of replace, and it appears I'm not the only one who thinks that. I've got server-side rendered HTML components (i.e. <employee-card name="John Doe"> and I'm using Vue to simply attach functionality.

This causes an inconsistency of CSS rendering in cases when Vue has not yet loaded... and then after it gets bootstrapped. Consider the following: <employee-card> is part of a collection inside of a flexbox container. A flexbox layout affects immediate descendants. So then I'm left with, "Do I put styles on the template's root <div> or the <employee-card> or both?" At one point the page is going to look incorrect... and the page looking correct or incorrect should not be based upon Vue having been bootstrapped or not.

I'm curious, in what way was Vue suffering by the option of replace, especially if the default was made true? I think there needs to be some further consideration into how this affects circumstances other than the typical SPA... specifically in cases where components aren't injected client-side.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ecmel picture ecmel  路  52Comments

asiFarran picture asiFarran  路  34Comments

wenLiangcan picture wenLiangcan  路  39Comments

cherry-geqi picture cherry-geqi  路  35Comments

yyx990803 picture yyx990803  路  36Comments