vue 中 插槽(<slot>) 小记

    xiaoxiao2022-07-02  96

            Vue中插槽主要分为默认插槽、具名插槽、作用域插槽,前两种插槽的内容和样式皆由父组件决定,也就是说显示什么内容和怎样显示都由父组件决定;但是第三种插槽就不同了,作用域插槽的样式由父组件决定,内容却由子组件控制。简单来说:前两种插槽不能绑定数据,作用域插槽是一个带绑定数据的插槽。下面分别看看这三种插槽的使用:

    1、不带插槽

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Examples</title> <script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <child> <p>这段文字不能显示。</p> </child> </div> <script type="text/javascript"> var child ={ template:`<div><p>不带插槽,不会显示组件里的内容。</p></div>` }; var vm = new Vue({ el: '#app', components: { child } }); </script> </body> </html>

    2、带单个插槽:未命名插槽,这个插槽是默认插槽,也就是说它会作为所有未匹配到插槽的内容的统一出口。

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Examples</title> <script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <child> <p>这段文字通过插槽能够显示。</p> </child> </div> <script type="text/javascript"> var child ={ template:`<div><p>带插槽,会显示组件里的内容。</p><slot></slot></div>` }; var vm = new Vue({ el: '#app', components: { child } }); </script> </body> </html>

    3、具名插槽:子模板里的<slot>标签具有name属性,将匹配内容片段中有对应 slot 特性的元素。

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Examples</title> <script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <child> <p slot="title">Title</p> <p slot="header">Header</p> <p slot="footer">Footer</p> <p>Content</p> </child> </div> <script type="text/javascript"> var child ={ template:`<div> <p>这是child:</p> <slot name="title"></slot> <slot name="header"></slot> <slot></slot> <slot name="footer"></slot> </div>` }; var vm = new Vue({ el: '#app', components: { child } }); </script> </body> </html>

    注意看最终的显示结果:是跟子组件里 <slot> 的顺序一致

    4、作用域插槽

            首先要牢记一条准则:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。但有的时候你希望提供的组件带有一个可从子组件获取数据的可复用的插槽,这时候就需要用到作用域插槽了。

            作用域插槽就是父组件在调用子组件的时候给子组件传了一个插槽,这个插槽为作用域插槽,该插槽必须放在 <template> 标签里,同时声明从子组件接收的数据放在一个自定义属性内,并定义该数据的渲染方式。

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Examples</title> <script type="text/javascript" src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <p>父组件接收的来自子组件 slot 传递过来的参数prop [这个名称可以自由定义] 的值:</p> <child :lists="lists"> <template slot="lang" slot-scope="prop"> {{prop}} </template> </child> <child :lists="lists"> <template slot="lang" slot-scope="prop"> <li>{{prop.item.name}}</li> </template> </child> </div> <script type="text/javascript"> var child ={ props: ["lists"], //接收父组件传进来的参数 // 为了让 item 在父级的插槽内容可用,可以将 item 作为一个 <slot> 元素的特性绑定上去(绑定在<slot>元素上的特性被称为插槽prop) template:`<ul> <slot v-for="(list, index) in lists" name="lang" :item="list"></slot> </ul>` }; var vm = new Vue({ el: '#app', data: { lists: [ {id:1, name:'HTML'}, {id:2, name:'JavaScript'}, {id:3, name:'VueJS'}, {id:4, name:'AngularJS'}, ] }, components: { child } }); </script> </body> </html>

            可以看到,在子组件中有个插槽 <slot> 通过 v-bind 绑定了一个值 item,在父组件中引用了子组件child,child标签里面可以看到作用域插槽 template,此时 slot-scope 就是一个对象,这个对象是由子组件的插槽 <slot> 所绑定的值所组成的一个对象,比如在这里 slot-scope = {item},这里的 item 来自子组件,而这里 slot-scope 的值是 prop,所以可以通过 {{prop.item.name}} 的方式访问到 name 属性。

            运行结果:

    在 2.5.0+,slot-scope 不再限制在 <template> 元素上使用,而可以用在插槽内的任何元素或组件上:

    <child :lists="lists"> <!-- 2.5.0+ 版本中,slot-scope 用于 div 标签中也是ok的,低于这个版本的会报错 --> <div slot="lang" slot-scope="prop"> <li>{{prop.item.id}}. {{prop.item.name}}</li> </div> </child>

    个人理解,如有不对,欢迎指正~

    最新回复(0)