Vue学习笔记(八)插槽

在使用组件时,组件开始标签和结束标签的内容会被忽视,如下代码

<div id="app">
    <my-com>I want to be shown</my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<h1>this is the template</h1>"
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

这里my-com开始标签和结束标签间的内容不会显示出来,整个标签都被模板覆盖了,如果要在html中传入开始标签和结束标签之间的内容的话,就可以使用插槽。

插槽的基本使用


插槽通过<slot>标签来实现,组件标签间的内容会出现在模板中<slot></slot>的位置。如下代码

<div id="app">
    <my-com>I want to be shown</my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<h1>this is the template  <slot></slot></h1>"
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

在页面中最终就会渲染为

<div id="app">
    <h1>this is the template  I want to be shown</h1>
</div>

可以看到标签间的内容已经被渲染到原来的<slot></slot>的位置了。

标签间的内容会以html的方式解析出来,即是说可以在标签里面放html结构。

<div id="app">
    <my-com>
        <span>I am a span</span>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><p>this is the template</p>  <slot></slot></div>"
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

渲染到页面后为

<div id="app">
    <div>
        <p>this is the template</p> 
        <span>I am a span</span>
    </div>
</div>

插槽的后备内容/默认值


如果要在标签内没内容时传入一个默认值,那么直接在模板中的<slot></slot>间插入内容即可。

<div id="app">
    <my-com>I want to be shown</my-com>
    <my-com></my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><p>this is the template</p>  <slot>I am the default value</slot></div>"
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

在页面中渲染为

<div id="app">
    <div>
        <p>this is the template</p> 
        I want to be shown
    </div> 
    <div>
        <p>this is the template</p> 
        I am the default value
    </div>
</div>

具名插槽


如果要在模板的不同位置插入不同的内容,就可以使用具名插槽,为每个位置指定具体的名称,分别插入不同的内容。

具名插槽在组件标签中使用template来包裹插槽的内容,并使用v-slot指明插槽的名称,然后在模板中的<slot></slot>中再使用name属性来指明要使用哪一个插槽。

<div id="app">
    <my-com>
        <template v-slot:first>I am the first</template>
        <template v-slot:second>I am the second</template>
        <template v-slot:third>I am the third</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: `<div>
            <h1>
                <slot name="first"></slot>
            </h1>
            <h2>
                <slot name="second"></slot>
            </h2>
            <h3>
                <slot name="third"></slot>
            </h3>
        </div>`
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

在页面中渲染为

<div id="app">
    <div>
        <h1>I am the first</h1> 
        <h2>I am the second</h2> 
        <h3>I am the third</h3>
    </div>
</div>

无名称的插槽

如果有一个template没有指明使用插槽名称,则默认使用defult作为名称

<div id="app">
    <my-com>
        <template v-slot:first>I am the first</template>
        <template v-slot:second>I am the second</template>
        <template v-slot:third>I am the third</template>
        <template>I don't have v-slot</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: `<div>
        <h1>
            <slot name="first"></slot>
        </h1>
        <h2>
            <slot name="second"></slot>
        </h2>
        <h3>
            <slot name="third"></slot>
        </h3>
        <p>
            <slot name="default"></slot>
        </p>
    </div>`
    })


    let vm = new Vue({
        el: "#app",
        data: {},
        methods: {}
    })
</script>

页面中渲染为

<div id="app">
    <div>
        <h1>I am the first</h1> 
        <h2>I am the second</h2> 
        <h3>I am the third</h3> 
        <p>   I don't have v-slot</p>
    </div>
</div>

变量控制

v-slot也可以绑定data中变量对应的内容,只要在v-slot后面的内容添加[]即可。

<div id="app">
    <my-com>
        <template v-slot:[h1]>I am the first</template>
        <template v-slot:[h2]>I am the second</template>
        <template v-slot:[h3]>I am the third</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: `<div>
    <h1>
        <slot name="first"></slot>
    </h1>
    <h2>
        <slot name="second"></slot>
    </h2>
    <h3>
        <slot name="third"></slot>
    </h3>
</div>`
    })


    let vm = new Vue({
        el: "#app",
        data: {
            h1: 'first',
            h2: 'second',
            h3: 'third'
        },
        methods: {}
    })
</script>

在页面中渲染为

<div id="app">
    <div>
        <h1>I am the first</h1> 
        <h2>I am the second</h2> 
        <h3>I am the third</h3>
    </div>
</div>

v-slot缩写

v-slot和v-bind,v-on一样,有自己的缩写"#"。使用缩写与原来渲染出来的结果是相同的。

<div id="app">
    <my-com>
        <template #:[h1]>I am the first</template>
        <template #:[h2]>I am the second</template>
        <template #:[h3]>I am the third</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: `<div>
<h1>
    <slot name="first"></slot>
</h1>
<h2>
    <slot name="second"></slot>
</h2>
<h3>
    <slot name="third"></slot>
</h3>
</div>`
    })


    let vm = new Vue({
        el: "#app",
        data: {
            h1: 'first',
            h2: 'second',
            h3: 'third'
        },
        methods: {}
    })
</script>

插槽的作用域


插槽可以使用其组件所在的父组件的data,但不可以直接使用其组件的data

<div id="app">
    <my-com>
        <!-- childStr无法正常显示,会报childStr没定义的错误 -->
        <p>{{childStr}}</p>
        <p>{{parentStr}}</p>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><slot></slot></div>",
        data: () => {
            return {
                childStr: "child"
            }
        }
    })


    let vm = new Vue({
        el: "#app",
        data: {
            parentStr: "parent"
        }
    })
</script>

要使用其组件中的data,可以在其父作用域中设置一个插槽prop,在组件的模板中将组件的data中的值作为slot的特性绑定到父作用域中。设置插槽prop可以使用v-slot(#),与上面指明哪一个slot使用“:”不一样,这里使用的是“=”。

<div id="app">
    <my-com>
        <template v-slot="slotProps">{{slotProps.childStr}}</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><slot :childStr='childStr'></slot></div>",
        data: () => {
            return {
                childStr: "child"
            }
        }
    })


    let vm = new Vue({
        el: "#app",
        data: {
            parentStr: "parent"
        }
    })
</script>

解构插槽

在设置插槽prop时,可以采用解构插槽的方法,这样会更为便利,减少了prop名称的设置

<div id="app">
    <my-com>
        <template v-slot="{childStr}">{{childStr}}</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><slot :childStr='childStr'></slot></div>",
        data: () => {
            return {
                childStr: "child"
            }
        }
    })


    let vm = new Vue({
        el: "#app",
        data: {
            parentStr: "parent"
        }
    })
</script>

使用解构插槽时,可以设置默认值,在没有该值时使用默认值,直接使用=即可。

<div id="app">
    <my-com>
        <template v-slot="{childStr='default value'}">{{childStr}}</template>
    </my-com>
</div>

<script>
    Vue.component("myCom", {
        template: "<div><slot :childStr='childStr'></slot></div>"
    })


    let vm = new Vue({
        el: "#app",
        data: {
            parentStr: "parent"
        }
    })
</script>

页面最后渲染为

<div id="app">
    <div>default value</div>
</div>

可以看到最后是使用了默认值。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值