17-不得不学的Vue.js基础之插槽 slot

前端 · 2020-07-22 ·
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>插槽 slot</title>
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>
</head>

<body>
    <div id="app">

        <!--1.插槽基础功能:父组件向子组件传递数据,将父组件的数据插入到子组件中。在具名插槽和作用域插槽引入新的统一语法,既 v-slot 指令,取代了slot 和 slot-scope-->
        <p>
            <alert-box>
                I want to transmit something!
            </alert-box>
        </p>

        <!--2.插槽内容:插槽内容可以包含任何模板代码,包括HTML、其他组件,如下所示-->
        <p>
            <navagation-link url="http://mla.xin">
                Your Profile(文本)
            </navigation-link>
        </p>
        <p>
            <navagation-link url="http://mla.xin">
                <strong class="html">HTML</strong>
            </navigation-link>
        </p>
        <p>
            <navagation-link url="http://mla.xin">
                <strong class="html">其他组件</strong>
                <alert-box>
                    I want to transmit something!
                </alert-box>
            </navigation-link>
        </p>
        <!--如果组件navigation-link 没有包含一个 <slot> 元素,则该组件起始标签和结束标签之间的任何内容都会被抛弃-->

        <!--3.编译作用域:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。-->
        <p>
            <navagation-link-scope url="http://mla.xin">
                {{user.name}}
            </navagation-link-scope>
        </p>

        <!--4.后备内容(默认值):可以给插槽提供一个默认值,在没有提供内容时默认显示后备内容,如果提供了插槽内容,则显示插槽内容。-->
        <!--默认显示插槽内容Submit-->
        <p>
            <submit-button></submit-button>
            <!--显示 "save"-->
            <submit-button>Save</submit-button>
        </p>

        <!--5.具名插槽:注意:在具名插槽和作用域插槽引入新的统一语法,即v-slot指令,取代了slot和slot-scope。-->
        <!--可以使用元素的attribute:name 属性,给插槽命名。-->
        <base-layout>
            <template v-slot:header>
                <h1>Here is header</h1>
            </template>
            <p>A paragraph for the main content.</p>
            <p>And another one.</p>
            <template v-slot:footer>
                <p>Here is footer</p>
            </template>
        </base-layout>

        <!--6.作用域插槽:使得父组件可以访问子组件的内容,是子组件将自己的数据暴漏给父组件使用。-->
        <p>
            <current-user>
                <template v-slot:default="slotProps">
                    <strong>{{ slotProps.user.lastName }}</strong>
                </template>
            </current-user>
            <current-user>
                <template v-slot="slotProps">
                    <strong>{{ slotProps.user.firstName }}</strong>
                </template>
            </current-user>
        </p>
        <!--作用域插槽就是父组件在调用子组件的时候给子组件传了一个作用域插槽,该插槽必须放在template标签里面,同时声明从子组件接收的数据放在一个自定义属性内,并定义该数据的渲染方式。slot-scope 已废弃-->
        <p>
            <scope-layout>
                <template v-slot="props">
                    <strong>{{ props.value }}</strong>
                </template>
            </scope-layout>
        </p>
        <p>
            <scope-layout>
                <template v-slot="props">
                    <i>{{ props.value }}</i>
                </template>
            </scope-layout>
        </p>
        
    </div>
    <script>
    // 1.注册全局组件alert-box!
    Vue.component('alert-box', {
        template: `
				<span class="demo-alert-box">
					<slot></slot>
					<strong>Success!</strong>
				</span>
			`
    });
    // 2.注册全局组件navagation-link!
    Vue.component('navagation-link', {
        props: ['url'],
        template: `
				<a v-bind:href ='url' class ='nav-link'>
				  <slot></slot>
				</a>
			`
    });
    // 3.注册全局组件navagation-link-scope!
    Vue.component('navagation-link-scope', {
        props: ['url'],
        template: `
				<a v-bind:href ='url' class ='nav-link'>
				  <slot></slot>
				</a>
			`
    });
    // 4.注册全局组件submit-button!
    Vue.component('submit-button', {
        template: `
				<button type="submit">
				  <slot>Submit</slot>
				</button>
			`
    });
    // 5.注册全局组件base-layout!
    Vue.component('base-layout', {
        template: `
				<div class="container">
					<header>
						<slot name="header"></slot>
					</header>
					<main>
					    <slot></slot>  
					</main>
					<footer>
					    <slot name="footer"></slot>   
					</footer>
				</div>
			`
    });
    // 6.注册全局组件current-user!
    Vue.component('current-user', {
        data: function() {
            return {
                user: {
                    firstName: 'xin',
                    lastName: 'mla'
                }
            }
        },
        template: `
				<span>
				  <slot v-bind:user="user"></slot>
				</span>
               `
    });
    Vue.component('scope-layout', {
        data: function() {
            return {
                list: [1, 2, 3, 4]
            }
        },
        template: `
				<span class="scope-layout-c">
                    <slot v-for="value in list" :value=value>
                    </slot>
               	 </span>
               `
    });
    var vm = new Vue({
        el: "#app",
        data: {
            user: {
                name: 'Vue'
            }
        }
    });
    </script>
</body>

</html>

以下是测试数据:

I want to transmit something!

Your Profile(文本)

HTML

其他组件 I want to transmit something!

{{user.name}}

Save

A paragraph for the main content.

And another one.

%