Vuejs的component的数据进行了沙箱隔离,除js全局变量如Math, Date之类外无法访问用户自定义的变量,所以使用component写组件或嵌套组件时明白变量的访问非常重要
编译作用域
在看componnent的使用之前,来看下component编译作用域,明白作用域范围才能顺利写出想要的组件
假设我们有一个组件child-component,在父组件中代码如下:
<child-component> ?{{ message }}</child-component>
编译时message的作用域应该是父组件还是子组件呢,答案是父组件
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译
Vue.component(‘child-component‘, { ?// 有效,因为是在正确的作用域内 ?template: ‘<div v-show="someChildProperty">Child</div>‘, ?data: function () { ???return { ?????someChildProperty: true ???} ?}})
slot在component中有单slot,具名slot和作用域slot之分,先来看看最简单的单slot应用
单个slot
直接上代码,其中的name字段会在父组件中初始化并赋值
父组件<div id="test"><test-slot> ?????<h3>{{name}}</h3> ?????<p>Something bad happened.</p></test-slot></div>
组件Vue.component("test-slot",{ ??????????// 插槽允许有默认内容 ??????????template: ??????????????`<div> ???????????????????<strong>Error!</strong> ???????????????????<slot></slot> ???????????????</div> ??????????????`, ???????????data:function () { ???????????????return { ???????????????????name:"perry" ???????????????} ???????????} ???????});new Vue({ ???????el:"#test" ???????data:{name:"500 error"}});结果:<div> ???<strong>Error!</strong> ???<h3>500 error</h3> ???<p>Something bad happened.</p></div>
具名slot
具名插槽比较有意思,在模板制定时非常好用,比如我们要写一个模板包含头尾和内容部分,希望在模板中定义好一部分公共的东西
具名slot通过name来管理多个slot的解析,其中没有name的slot会被归为default slot放到没有name的节点下面,default slot会无视散落在不同地方的html的位置,都将放到default slot的
模板位置中来
Vue.component("slot-name",{ ??????????template: ??????????????`<div> ?????????????????????<header> ???????????????????????????<slot name="header"></slot> ?????????????????????</header> ????????????????????<main> ???????????????????????<slot ></slot> ????????????????????</main> ????????????????????<footer> ???????????????????????<slot name="footer"></slot> ????????????????????</footer> ????????????????</div> ??????????????`});<slot-name> ??????<h3>开始</h3>
<p>Default slot内容1</p> ??????<template slot="header"> ?????????????<ul> ??????????????????<li>主页</li> ??????????????????<li>分诊</li> ??????????????????<li>护理</li> ??????????????????<li>病历</li> ??????????????</ul> ???????</template> ???????<template slot="footer"> ??????????<p>结尾</p> ???????</template></slot-name>
运行结果:
作用域slot
作用域插槽在解决需要动态生成字符串模板时非常有用,特别针对控件编写者
例如实现一个简单的datagrid控件,控件在页面component中相当于子控件,使用者希望只关注表头和每行数据业务上,直接上代码
控件代码Vue.component("datagrid",{ ???????????props:{ ???????????????data:null ???????????}, ???????????template:` ??????????????<table> ???????????????????<thead> ???????????????????????<slot name="headslot"></slot> ???????????????????</thead> ???????????????????<tbody> ???????????????????????<tr ?v-for="item in data"> ???????????????????????????<slot name="bodyslot" :item="item">{{item.text}</slot> ???????????????????????</tr> ??????????????????</tbody> ??????????????</table> ??????????` });在父组件中(页面上)使用如下:<datagrid :data="todos"> ??????<template slot="headslot"> ?????????????<tr> ???????????????????<td>id</td> ????????????????????<td>text</td> ????????????????????<td>isTrue</td> ??????????????</tr> ??????</template> ?????<template slot="bodyslot" slot-scope="{item}"> ???????????????????<td>{{item.id}}</td> ???????????????????<td>{{item.text}}</td> ???????????????????<td>{{item.isTrue}}</td> ?????</template></datagrid>
如上代码,简单的datagrid就实现了,在父组件中只需要在head中指定table的head具体内容,对应的body中tr的每个td的字段绑定,其它交给控件处理
其中数据源是datagrid中的data属性,与slot通信是通过slot-scope来实现数据域传递,这点非常关键
控件中 :item="item" 与父组件slot-scope="{item}" 完成数据访问的传递,其中slot-scope="{item}"语句也可以通过"slot-scope="slotProps"来实现数据传递,slotProps对像相当于当slot对象上
所有props属性的根,通过slotProps对象都能访问到
在js调用如下:
var vm = new Vue({ ???????????????el:"#app", ???????????????data:{ ???????????????????todos:[ ???????????????????????{text:"A",id:1,isTrue:true}, ???????????????????????{text:"B",id:2,isTrue:true}, ???????????????????????{text:"C",id:3,isTrue:false}, ???????????????????????{text:"D",id:4,isTrue:true}, ???????????????????] ???????????????} ???????????});
在data中的todos属性已经与页面的table形成了关联,只要todos属性发生变化,页面的table会自动更新tbody中的数据行,这就是数据驱动的精髓
Vuejs之Component slot 插槽详解
原文地址:https://www.cnblogs.com/johnx/p/9777099.html