Vue.js是一个易于使用的Web应用程序框架,可用于开发交互式前端应用程序。
在本文中,我将介绍命名插槽和作用域插槽。
有时我们的模板中会有多个插槽。为了区分每个插槽,我们必须给它们命名。
我们可以使用name
属性定义具有命名插槽的组件,如下所示:
Vue.component("layout", { template: ` <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> `});
然后我们可以将上述组件一起使用,如下所示:
src/index.js:
Vue.component("layout", { template: ` <div> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div> `});
new Vue({ el: "#app"});
index.html:
<!DOCTYPE html><html> <head> <title>App</title> <meta charset="UTF-8" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <layout> <template v-slot:header> <h1>Header</h1> </template> <p>Main</p> <template v-slot:footer> <p>Footer</p> </template> </layout> </div> <script src="src/index.js"></script> </body></html>
填充具有header
名称的插槽:
<template v-slot:header> <h1>Header</h1></template>
填充具有footer
名称的插槽:
<template v-slot:footer> <p>Footer</p></template>
填充没有名称的插槽:
<p>Main</p>
我们还可以使用v-slot:default
填充没有名字的默认插槽,如下所示:
<template v-slot:default> <p>Main</p></template>
无论哪种方式,渲染出来的HTML都是相同的。
我们可以使用作用域插槽来访问子组件中的数据。
为了使子组件中的数据在父组件中可用,我们可以使用v-bind
指令。
一个简单的示例,从父级去获取子级组件数据如下:
src/index.js:
Vue.component("user", { data() { return { user: { firstName: "Joe", lastName: "Smith" } }; }, template: `<p> <slot v-bind:user="user"></slot> </p>`});
new Vue({ el: "#app"});
index.html:
<!DOCTYPE html><html> <head> <title>App</title> <meta charset="UTF-8" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> </user> </div> <script src="src/index.js"></script> </body></html>
在上面的代码中,我们设置了子组件上的插槽数据:
<p> <slot v-bind:user="user"></slot></p>
在根Vue实例中就可以使用user
了。
然后在根模板中,我们可以这样使用user
:
<user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template></user>
通过slotProps
访问用户的数据,slotProps
可以访问子组件中的v-bind
提供的所有数据。
如果只有一个默认插槽,那么我们可以直接在子组件上使用v-slot:default
或v-slot
,如下所示:
<user v-slot:default="slotProps"> {{
<user v-slot="slotProps"> {{ slotProps.user.firstName }}</user>
如果还有其他命名的插槽,则可能存在歧义,因此无法使用上述语法。
如果我们有多个插槽,那么我们必须老老实实编写如下内容:
src/index.js:
Vue.component("user", { data() { return { user: { firstName: "Joe", lastName: "Smith" } }; }, template: `<p> <slot v-bind:user="user" name='first-name'></slot> <slot v-bind:user="user" name='last-name'></slot> </p>`});
new Vue({ el: "#app"});
index.html:
<!DOCTYPE html><html> <head> <title>App</title> <meta charset="UTF-8" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <user> <template v-slot:first-name="slotProps"> {{ slotProps.user.firstName }} </template> <template v-slot:last-name="slotProps"> {{ slotProps.user.lastName }} </template> </user> </div> <script src="src/index.js"></script> </body></html>
在上面的代码中,我们必须明确命名插槽,然后才能分别通过v-slot:first-name="slotProps"
和v-slot:last-name="slotProps"
访问子组件的数据。
另外,我们将插槽内容包装在template中。
我们可以使用解构赋值运算符来解构插槽作用域数据。
例如,我们可以按以下方式使用它:
src/index.js:
Vue.component("user", { data() { return { user: { firstName: "Joe", lastName: "Smith" } }; }, template: `<p> <slot v-bind:user="user" name='first-name'></slot> <slot v-bind:user="user" name='last-name'></slot> </p>`});
new Vue({ el: "#app"});
index.html:
<!DOCTYPE html><html> <head> <title>App</title> <meta charset="UTF-8" /> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <user> <template v-slot:first-name="{ user }"> {{ user.firstName }} </template> <template v-slot:last-name="{ user }"> {{ user.lastName }} </template> </user> </div> <script src="src/index.js"></script> </body></html>
在上面的代码中,我们没有使用slotProps,而是将其更改为{ user }
。{ user }
与slotProps.user
相同。
我们可以使用命名插槽和作用域插槽创建多个插槽,并分别从父级的子级组件中去访问数据。
命名插槽可防止歧义,并允许我们使用多个插槽。
另外,我们可以在子组件中使用v-bind
,然后在组件中使用slotProps
从父组件访问子组件的数据。