Использование слота в компонентизации vue

Vue.js
Использование слота в компонентизации vue

Слот может открывать слот в дочернем компоненте, и когда родительский компонент ссылается на компонент, вы можете определить функцию или модуль, которые будут отображаться в слоте.

1. Один слот

В подкомпоненте напишите тег слота в соответствующей позиции.Когда родительский компонент ссылается на субкомпонент, напишите элемент, который будет вставлен в слот в теге субкомпонента; Вы также можете настроить слот для отображения содержимого по умолчанию в слоте дочернего компонента, когда для родительского компонента слот не установлен; родительский компонент.vue

<template>
    <div class="home">
        <child-componment>
            <p>
                这是父组件的slot替代内容!
            </p>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    },
    data(){
        return {
        message: ''
        }
    }
};
</script>
​

дочерний компонент

<template>
    <div class="childComponment">
        <h2>这是子组件childComponment!</h2>
        <slot>
            <span style="color: red;">如果父组件没有插入内容,我这样可以设置默认的显示内容</span>
        </slot>
    </div>
</template>
​
<script>
export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    }
};
</script>

2. Total SLOT (одновременное использование нескольких слотов)

Укажите имя для слота, вы можете распространять несколько слотов слотов, но может быть только один неназванный слот; Содержание слота родительского компонента, если вы не пишете слот = «xxx», будет вставлен в неназванный слот дочернего компонента; Если неназванный слот не указан (слот по умолчанию), дополнительный контент в родительском компоненте будет отброшен.

<template>
    <div class="home">
        <child-componment>
            <h1 slot="header">
                父组件的header
            </h1>
            <h6 slot="footer">父组件的footer</h6>
            
            <h6>父组件的无名slot-1</h6>
            <p>
                父组件的无名slot-2
            </p>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    },
    data(){
        return {
            message: ''
        }
    }
};
</script>
​

Подсборка

<template>
    <div class="childComponment">
        <span>这是子组件childComponment的正常内容!</span>
        <div class="header">
            <slot name="header">
                <span style="color: red;">子组件默认header-slot</span>
            </slot>
        </div>
        <div class="container">
            <!-- 如果没有指定无名slot(默认slot),父组件内多余的内容将会被抛弃 -->
            <slot>
                <span style="color: red;">子组件默认无名slot</span>
            </slot>
        </div>
        <div class="footer">
            <slot name="footer">
                <span style="color: red;">子组件默认footer-slot</span>
            </slot>
        </div>
    </div>
</template>
​
<script>
export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    }
};
</script>
<style scoped>
.childComponment{
    font-size: 16px;
}
.header{
    height: 100px;
    border:1px solid red;
    color: red;
}
.container{
    height: 500px;
    border: 1px solid black;
    color: black;
}
.footer{
    height:100px;
    border: 1px grey solid;
    color: grey;
}
</style>

3. Слоты прицела

<template>
    <div class="home">
        <child-componment>
            <template slot-scope="slotProps">
                <!-- 这里显示子组件传来的数据 -->
                <p>{{slotProps}}</p>
            </template>
        </child-componment>
    </div>
</template>
​
<script>
import childComponment from '@/components/childComponment.vue'
export default {
    name: "home",
    components:{
        childComponment
    }
};
</script>
​

Подсборка

<template>
    <div class="childComponment">
        <span>这是子组件childComponment的正常内容!</span>
        <div class="container">
            <!-- 如果没有指定无名slot(默认slot),父组件内多余的内容将会被抛弃 -->
            <slot msg="子组件信息" slotData="子组件数据"></slot>
        </div>
    </div>
</template>

Советы: Действует на сокеты или именованные сокеты

Случай: компонент списка

Это наиболее часто используемый случай для слотов, позволяющий компонентам настраивать способ отображения каждого элемента компонента.

<template>
  <div class="about">
    <h1>This is about page</h1>
    <my-list :books="books">
        <template slot="bookList" slot-scope="myListProps">
            <li>{{myListProps.bookName}}</li>
        </template>
    </my-list>
  </div>
</template>
<script>
import myList from '@/components/myList.vue'
export default {
    components:{
        myList
    },
    data(){
        return {
            books: [
                {name: 'css揭秘'},
                {name: '深入浅出nodejs'},
                {name: 'javascript设计模式与开发实战'}
            ]
        }
    }
}
</script>

Дочерний компонент myList.vue

<template>
  <div class="myList">
    <h1>This is myList page</h1>
    <ul>
        <slot name="bookList" v-for="book in books" :bookName="book.name"></slot>
    </ul>
  </div>
</template>
<script>
export default {
    props:{
        books:{
            type: Array,
            default: function(){
                return []
            }
        }
    },
    mounted(){
        console.log(this.books)
    }
}
</script>

На самом деле вышеописанный случай можно использовать непосредственно в цикле for родительского компонента, здесь он используется только как слот области действия для демонстрационного слота; Сценарии использования слотов с ограниченной областью действия в реальной разработке в основном таковы: не только слоты подкомпонентов могут использоваться повторно, но и содержимое слотов может быть непоследовательным.

4. Доступ к слоту

Vue2.0 предоставляет метод $slot для доступа к слоту. Код здесь берет код «именованного слота (с использованием нескольких слотов одновременно)» в качестве примера и изменяет дочерний компонент childComponment.vue.

export default {
    name: "childComponment",
    data(){
        return {
            message: ''
        }
    },
    mounted(){
        let header = this.$slots.header
        let main = this.$slots.default
        let footer = this.$slots.footer
        console.log(header)
        console.log(main)
        console.log(footer)
        console.log(footer[0].elm.innerHTML)
    }
};

распечатать результат:

Содержимое elm — это содержимое слота, а структура следующая: