zoukankan      html  css  js  c++  java
  • 深入了解Vue组件 — 插槽

    1.插槽

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
    <div id="app">
    	<navigation-link :url="url">Your Profile({{ user.name }})</navigation-link>	
    </div>
    <script>
    	Vue.component('navigation-link', {
    		props: {
    			url: String,
    		},
    		template: `<a :href="url"><slot></slot></a>`
    	});
    
        new Vue({
            el: '#app',
            data: {
                url: 'https://www.baidu.com',
    			user: {
    				name: 'hjj'
    			}
            }
        });
    </script>
    </body>
    </html>
    

    当组件渲染的时候,<slot></slot>将会被替换为"Your Profile"。

    注意:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
    <div id="app">
    	<navigation-link url="/profile">Your Profile {{ url }}</navigation-link>	
    </div>
    <script>
    	Vue.component('navigation-link', {		
    		template: `<a><slot></slot></a>`
    	});
    
        new Vue({
            el: '#app',
            data: {
    			
            }
        });
    </script>
    </body>
    </html>
    

    上面代码通过{{ url }}访问url会报错。

    1.1 默认值

    有时为一个插槽设置具体的后备 (也就是默认的) 内容是很有用的,它只会在没有提供内容的时候被渲染。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
    </head>
    <body>
    <div id="app">
    	<submit-button></submit-button>
    	<submit-button>提交</submit-button>
    </div>
    <script>
    	Vue.component('submit-button', {
    		template: `<button type="submit"><slot>Submit</slot></button>`
    	});
    
        new Vue({
            el: '#app',
            data: {
    			
            }
        });
    </script>
    </body>
    </html>
    

    注意到<slot>Submit</slot>的Submit是默认值。

    1.2 具名插槽

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <!-- <script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script> -->
    	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
    	<base-layout>
    	  <template v-slot:header>
    		<h1>Here might be a page title</h1>
    	  </template>
    
    	  <p>A paragraph for the main content.</p>
    	  <p>And another one.</p>
    
    	  <template v-slot:footer>
    		<p>Here's some contact info</p>
    	  </template>
    	</base-layout>
    </div>
    <script>
    	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>`
    	});
    
        new Vue({
            el: '#app',
            data: {
    			
            }
        });
    </script>
    </body>
    </html>
    

    在向具名插槽提供内容的时候,我们可以在一个<template>元素上使用v-slot指令,并以v-slot的参数的形式提供其名称(比如<template v-slot:header>,它匹配<slot name="header"></slot>)。
    注意:<main><slot></slot></main><slot>没有带name,则带有隐含的名字default。任何没有被包裹在带有v-slot<template>中的内容都会被视为默认插槽的内容。

    1.3 作用域插槽

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
    	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
    	<current-user>
    		<template v-slot:default="slotProps">
    			{{ slotProps.user.firstName }}
    		</template>
    	</current-user>
    	<br/>
    	<!-- 当只有默认插槽时,我们可以把`v-slot`直接用在组件上。 -->
    	<current-user v-slot:default="slotProps">
    		{{ slotProps.user.firstName }}
    	</current-user>
    	<br/>
    	<current-user v-slot="slotProps">
    		{{ slotProps.user.firstName }}
    	</current-user>
    </div>
    <script>
    	Vue.component('current-user', {
    		data: function(){
    			return {
    				user: {
    					firstName: 'He'
    				}
    			}
    		},
    		template: `<span><slot v-bind:user="user"></slot></span>`
    	});
    
        new Vue({
            el: '#app',
            data: {
    			
            }
        });
    </script>
    </body>
    </html>
    

    绑定在<slot>元素上的特性被称为插槽 prop。这里我们将包含所有插槽 prop 的对象命名为slotProps,但你也可以使用任意你喜欢的名字。

    1.3.1 解构插槽prop

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
    	<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
    	<current-user v-slot="{user}">
    		{{ user.firstName }}
    	</current-user>
    	<br/>
    	<current-user v-slot="{user: person}">
    		{{ person.firstName }}
    	</current-user>
    </div>
    <script>
    	Vue.component('current-user', {
    		data: function(){
    			return {
    				user: {
    					firstName: 'He'
    				}
    			}
    		},
    		template: `<span><slot v-bind:user="user"></slot></span>`
    	});
    
        new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    

    1.4 具名插槽的缩写

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <base-layout>
          <template #header>
            <h1>Here might be a page title</h1>
          </template>
    
          <p>A paragraph for the main content.</p>
          <p>And another one.</p>
    
          <template #footer>
            <p>Here's some contact info</p>
          </template>
        </base-layout>
    	<current-user #default="slotProps">
            {{ slotProps.user.firstName }}
        </current-user>
    	<br/>
    	<current-user #default="{ user }">
            {{ user.firstName }}
        </current-user>
    </div>
    <script>
        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>`
        });
    	
        Vue.component('current-user', {
            data: function(){
                return {
                    user: {
                        firstName: 'He'
                    }
                }
            },
            template: `<span><slot v-bind:user="user"></slot></span>`
        });
    
        new Vue({
            el: '#app',
            data: {
                
            }
        });
    </script>
    </body>
    </html>
    

    具名插槽v-slot:header可简写为#header

    1.5 其它示例

    插槽 prop 允许我们将插槽转换为可复用的模板,这些模板可以基于输入的 prop 渲染出不同的内容。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <style>
    
        </style>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
    	<todo-list>
    	  <template v-slot:todo="{ todo }">
    		<span v-if="todo.isComplete">✓</span>
    		{{ todo.text }}
    	  </template>
    	</todo-list>
    	<todo-list>
    	  <template v-slot:todo="{ todo }"></template>
    	</todo-list>
    	<todo-list></todo-list>
    </div>
    <script>
        Vue.component('todo-list', {
    		data: function(){
    			return {
    				todos: [
    					{id: 1, text: 'Hey', isComplete: true},
    					{id: 2, text: 'Thank you', isComplete: true},
    					{id: 3, text: 'Very much', isComplete: false},
    				]
    			}
    		},
            template: `<ul>
    					  <li v-for="todo in todos" v-bind:key="todo.id">
    						<slot name="todo" v-bind:todo="todo">
    						  {{ todo.text }}
    						</slot>
    					  </li>
    					</ul>`
        });
    
        new Vue({
            el: '#app'
        });
    </script>
    </body>
    </html>
    

    1.6 总结

    <navigation-link :url="url">Your Profile({{ user.name }})</navigation-link>
    Vue.component('navigation-link', {props: {url: String},template: `<a :href="url"><slot></slot></a>`});
    
    data: {url: '...', user: {name: '...'}}
    

    1、默认值

    <submit-button></submit-button>
    <submit-button>提交</submit-button>
    
    template: `<button type="submit"><slot>Submit</slot></button>`
    

    2、具名插槽

    <base-layout><template v-slot:header>...</template></base-layout>
    
    template: `<div class="container"><header><slot name="header"></slot></header>...</div>`
    

    3、作用域插槽

    // 不是具名插槽,就是默认插槽。
    <current-user><template v-slot:default="slotProps">{{ slotProps.user.firstName }}</template></current-user>
    <current-user v-slot:default="slotProps">{{ slotProps.user.firstName }}</current-user>
    <current-user v-slot="slotProps">{{ slotProps.user.firstName }}</current-user>
    
    Vue.component('current-user', {
    	data: function(){return {user: {firstName: 'He'}}},
    	template: `<span><slot v-bind:user="user"></slot></span>`
    });
    
    // 解构
    <current-user v-slot="{user}">{{ user.firstName }}</current-user>
    <current-user v-slot="{user: person}">{{ person.firstName }}</current-user>
    
    Vue.component('current-user', {
    	data: function(){return {user: {firstName: 'He'}}},
    	template: `<span><slot v-bind:user="user"></slot></span>`
    });
    

    4、具名插槽的缩写

    <base-layout><template #header>...</template></base-layout>
    <current-user #default="slotProps">{{ slotProps.user.firstName }}</current-user>
    <current-user #default="{ user }">{{ user.firstName }}</current-user>
    
    template: `<div class="container"><header><slot name="header"></slot></header>...</div>`
    template: `<span><slot v-bind:user="user"></slot></span>`
    

    5、其他示例

    <todo-list>
    	<template v-slot:todo="{ todo }"><span v-if="todo.isComplete">✓</span>{{ todo.text }}</template>
    </todo-list>
    <todo-list>
    	<template v-slot:todo="{ todo }"></template>
    </todo-list>
    
    Vue.component('todo-list', {
    	data: function(){ return { todos: [...] }},
    	template: `<ul>
    		<li v-for="todo in todos" v-bind:key="todo.id">
    			<slot name="todo" v-bind:todo="todo">{{ todo.text }}</slot>
    		</li>
    	</ul>`
    });
    

    参考:

  • 相关阅读:
    webdriver---API---(java版) the fifth part
    【CSP-S2019模拟】题解
    【CSP-S2019模拟】题解
    【洛谷P5113】—魔女的夜宴Sabbat of the witch(分块+基数排序)
    【Codeforces 666 E】—Forensic Examination(广义Sam+线段树合并)
    【洛谷P4081】【USACO17DEC】—Standing Out from the Herd(广义Sam)
    【洛谷P4451】整数的lqp拆分(生成函数)
    【CSP-S 2019模拟】题解
    【Codeforces 335 E】—Counting Skyscrapers
    【Codeforces 793 G】—Oleg and chess(线段树优化建图+最大流)
  • 原文地址:https://www.cnblogs.com/gzhjj/p/11778265.html
Copyright © 2011-2022 走看看