插槽和具名插槽 作用域插槽

260 阅读1分钟

插槽和具名插槽

1 插槽和具名插槽

解决组件内容传递问题 slot不能直接绑定事件外部嵌套span slot可以是标签组件

父模板里调用的数据属性,使用的都是父模板里的数据 子模板里调用的数据属性,使用的都是子模板里的数据

slot 下面的span就是插槽

<myForm>
    <span>提交</span>    
</myForm>

插槽

<script>
    const app = Vue.createApp({
        data() {
            return {
                text:'提交'
            }
        },

        template : `
            <myForm> 
                <span>{{ text }}</span>       
                <test />
            </myForm>
            <myForm> 
                <button>{{ text }}</button>    
            </myForm>
            
        `
    });

    app.component('myForm',{
        data() {
            return {
                text:'子模板text'
            }
        },

        methods: {
            handleClick(){
                alert('hello');
            }
        },
        template : `
            <div> 
                <input />    
                <span @click="handleClick"> 
                    <slot /> 
                    {{ text }} 
                </span>
            </div>
        `
    });

    app.component('test',{
        template : `
            <div>test</div>
        `
    });
    const vm = app.mount('#root');

</script>

效果 image

没有slot时的默认值 ; slot署名拆成两个部分

不使用slot时是希望有个默认的按钮

<script>
    //slot 插槽
    // slot中的数据作用域的问题
    // 父模板里调用的数据属性,使用的都是父模板里的数据
    // 子模板里调用的数据属性,使用的都是子模板里的数据
    const app = Vue.createApp({
        data() {
            return {
                text:'提交'
            }
        },

        template : `
            <myForm> 
                <span>{{ text }}</span>       
            </myForm>
            <myForm> 
                <button>{{ text }}</button>    
            </myForm>

            <myForm></myForm>
            
        `
    });

    app.component('myForm',{
        data() {
            return {
                text:'子模板text'
            }
        },

        methods: {
            handleClick(){
                alert('hello');
            }
        },
        template : `
            <div> 
                <input />    
                <span @click="handleClick"> 
                    <slot> default value<button>按钮</button> </slot> 
                </span>
            </div>
        `
    });

    app.component('test',{
        template : `
            <div>test</div>
        `
    });
    const vm = app.mount('#root');

</script>

具名插槽

slot插入中间位置 slot署名拆成两个部分

<script>
    const app = Vue.createApp({
        data() {
            return {
                text:'提交'
            }
        },
        // slot插入中间位置 slot署名拆成两个部分
        template : `
            <layout>
                <template v-slot:header> 
                    <div> header </div>
                </template>
                <template v-slot:footer> 
                    <div> footer </div>
                </template>
            </layout>
        `
    });

    app.component('layout',{
        template : `
            <div> 
                <slot name="header"></slot>
                <div> content </div>
                <slot name="header"></slot>
            </div>
        `
    });

    const vm = app.mount('#root');

</script>

Maximum call stack size exceeded 栈溢出,死循环 子组件中用了原生的方法

2 作用域插槽

v-slot简写为# slotProps 子组件绑定的所有属性在slotProps

<script>
    const app = Vue.createApp({
        data() {
            return {
                text:'提交'
            }
        },
        // slotProps 子组件绑定的所有属性在slotProps
        template : `
            <myList v-slot="{item , index}">
                <div> {{item }} {{index }} </div>    
            </myList>
        `

        /*
        <myList v-slot="slotProps">
                <div> {{ slotProps.item }} {{ slotProps.index }} </div>    
            </myList>
        */
    });

    app.component('myList',{
        data() {
            return {
                list : [41,51,61],
            }
        },
        template:`
            <slot v-for ="(item,index) in list" :item="item" :index="index"/>
        `,

        /* 
            <div v-for ="item in list "> {{ item }} </div>
        */
    });

    const vm = app.mount('#root');

</script>