This is the third day of my participation in the November Gwen Challenge. Check out the details: the last Gwen Challenge 2021

preface

Scope slots make vUE components more versatile and reusable. Perhaps the only downside is that the concept is a little hard to understand, and often when I see code that is hard to understand, I try to use it in real projects to solve problems THAT I have encountered before. The following text describes a problem I encountered on a real project using scopedSlots to solve it.

The body of the

In app.js, build the my-list component, render the Shapes and colors test arrays, and accept the passed title property as follows:

Vue.component('my-list', {
  template: '#my-list'.props: [ 'title' ]
  data() {
    return {
      shapes: [{name: 'Square'.sides: 4 }, 
          { name: 'Hexagon'.sides: 6 }, 
          { name: 'Triangle'.sides: 3}].colors: [{name: 'Yellow'.hex: '#F4D03F'}, {name: 'Green'.hex: '# 229954' },
	      { name: 'Purple'.hex: '#9B59B6'}}; }});new Vue({
  el: '#app'
});
Copy the code

Implement data rendering at Shapes and colors in index.html, and write templates in my-list components

<div id="app">
  <my-list :title="Shapes">
    <div class="list-item" v-for="item in shapes">
      <div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
    </div>
  </my-list>
  <my-list :title="Colors">
    <div class="list-item" v-for="color in colors">
      <div>
        <div class="swatch" :style="{ background: color.hex }"></div>
        {{ color.name }}
      </div>
    </div>
  </my-list>
</div>

<script type="text/x-template" id="my-list">
  <div class="my-list">
    <div class="title">{{ title }}</div>
    <div class="list">
      <slot></slot>
    </div>
  </div>
</script>
Copy the code

Add some CSS and see the rendering as shown belowAlthough two sets of lists are implemented, there is repetitive code inside the component implementation<div class="list-item" v-for="item in ..." >If we can move it intomy-listHow nice it would be to implement it inside a component instead of on a parent component! ScopedSlots solves this problem successfully.

scopedSlots

It’s called “scoped” slot because even though its template is rendered inside the parent component, the parent component can read the data specified inside the child component through scopedSlots. We overwrote the code inside app.js

Vue.component('my-list', {
  template: '#my-list'.props: [ 'title'.'items']});Copy the code

In index.html, the complete code for the changes is shown below

<div id="app">
  <my-list title="Shapes" :items="shapes">
    <template scope="shape">// Scoped provides access to a single data shape inside a child component<div>{{ shape.name }} <small>({{ shape.sides }} sides)</small></div>
    </template>
  </my-list>
  <my-list title="Colors" :items="colors">
    <template scope="color">
      <div>
        <div class="swatch" :style="{ background: color.hex }"></div>
        {{ color.name }}
      </div>
    </template>
  </my-list>   
</div>

<script type="text/x-template" id="my-list">
  <div class="my-list">
    <div class="title">{{ title }}</div>
    <div class="list">
      <div v-for="item in items">
        <slot v-bind="item"></slot>
      </div>
    </div>
  </div>
</script>
Copy the code

Let’s look at the Shapes List. The template must contain the Scope property, which we give an alias shape that gives us access to the scope properties. Inside the template, we can display the Shape List as we did in the previous code.

conclusion

With scopedSlots, there is still as much HTML markup as before, but it has delegated common functionality to components, which is good for system code robustness.