javascriptvue.jsv-slot

In Vue2.7, v-slot is not available, how to solve the problem?


When I run the following code, I get the following results (Google Chrome running screenshot).

<!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>17-Learning of Scoped Slots and Named Slots</title>
    <style>
      .h1Class{
        color:red;
      }
    </style>
  </head>
  <body>
    <div id="div_new">
      <h1 class="h1Class">first set</h1>
      <cpn></cpn>
      <h1 class="h1Class">second set</h1>
      <cpn>
        <!-- first method -->
        <template  slot="slotName" slot-scope="planallScope">
        <!-- second method after Vue2.6 -->
        <!-- <template v-slot:slotName="planallScope" > -->
          <h4>{{planallScope.planall[0]}}</h4>
          <h4>{{planallScope.planall[1]}}</h4>
          <h4>{{planallScope.planall[2]}}</h4>
        </template>
      </cpn>
    </div>
    <template id="template_div">
      <div>
        <slot v-bind:planall="plan" name="slotName">
          <ul>
            <li v-for="item in plan"> {{ item }}</li>
          </ul>
        </slot>
      </div>
    </template>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.7/dist/vue.js"></script>
    <script>
      const templateDivText = {
        template: '#template_div',
        data() {
          return {
            plan:  ['C#', 'Java', 'JavaScript']
          }
        },
      } 
    const app_new = new Vue({
      el: '#div_new',
      components: {
        'cpn': templateDivText,
      },
    })
    </script>
  </body>
  </html>

The running result is as follows:

enter image description here

When I use v-slot, the code is as follows:

  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>17-Learning of Scoped Slots and Named Slots</title>
    <style>
      .h1Class{
        color:red;
      }
    </style>
  </head>
  <body>
    <div id="div_new">
      <h1 class="h1Class">first set</h1>
      <cpn></cpn>
      <h1 class="h1Class">second set</h1>
      <cpn>
        <!-- first method -->
        <!-- <template  slot="slotName" slot-scope="planallScope"> -->
        <!-- second method after Vue2.6 -->
        <template v-slot:slotName="planallScope" >
          <h4>{{planallScope.planall[0]}}</h4>
          <h4>{{planallScope.planall[1]}}</h4>
          <h4>{{planallScope.planall[2]}}</h4>
        </template>
      </cpn>
    </div>
    <template id="template_div">
      <div>
        <slot v-bind:planall="plan" name="slotName">
          <ul>
            <li v-for="item in plan"> {{ item }}</li>
          </ul>
        </slot>
      </div>
    </template>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.7/dist/vue.js"></script>
    <script>
      const templateDivText = {
        template: '#template_div',
        data() {
          return {
            plan:  ['C#', 'Java', 'JavaScript']
          }
        },
      } 
    const app_new = new Vue({
      el: '#div_new',
      components: {
        'cpn': templateDivText,
      },
    })
    </script>
  </body>
  </html>

The running result is as follows:

enter image description here

So in Vue2.7, v-slot is not available, how to solve the problem?


Solution

  • Your syntax is correct, except one little detail: you can't use camelCase for slot names.
    To be fair, I don't precisely know why, it has to do with template compilation and with the fact the slot names get parsed as element attributes in <template v-slot:slot-name"scope">. Vue's styling guideline does strongly advise on using kebab-case for attributes, directives and the likes, when used in templates or JSX.
    However, name="slotName" + <template #slot-name="scope"> doesn't seem to work for slots.

    In short, name="slotName" (+ <template #slotName="scope") does not work, but name="slot-name" (+ <template #slot-name="scope") does.

    See it working, in Vue 2.7.7:

    const templateDivText = Vue.defineComponent({
      template: '#template_div',
      data() {
        return {
          plan: ['C#', 'Java', 'JavaScript']
        }
      },
    })
    const app_new = new Vue({
      el: '#div_new',
      components: {
        'cpn': templateDivText,
      },
    })
    <script src="https://cdn.jsdelivr.net/npm/vue@2.7.7/dist/vue.min.js"></script>
    
    <div id="div_new">
      <cpn>
        <template #slot-name="{planall}">
           <h4>{{planall[0]}}</h4>
           <h4>{{planall[1]}}</h4>
           <h4>{{planall[2]}}</h4>
         </template>
      </cpn>
    </div>
    
    <template id="template_div">
      <div>
         <slot name="slot-name" :planall="plan">
            <ul>
              <li v-for="item in plan"> {{ item }}</li>
            </ul>
          </slot>
        </div>
      </template>

    Notes: