本章开始介绍slot机制。
slot是WEBComponent引进的东西,叫做插槽。在浏览器中,它为一个content元素。不过有资料表明,它会更名为slot。 并且在其他语言的模板引擎中,slot标签更为常用。因此avalon2的组件机制使用slot元素。
但说了这么久,slot元素到底是什么鬼?slot是一个占位符。它有一个name属性。假如另一个地方,也有一个元素,它带一个slot属性,当这两个属性值一致,那么那个元素就会 挪过来,替换掉这个slot元素。
<p id="eee"><slot name="aaa">这是插槽元素,这里面的内容是什么也无关</slot></p>
<p id="kkk"><span slot="aaa">这是要移动的元素</span></p>
最后会转换为
<p id="eee"><span slot="aaa">这是要移动的元素</span></p>
<p id="kkk"></p>
是不是很神奇呢?但是这不是所有浏览器都支持。avalon2 使用了一些魔术让IE6也支持slot。
为了方便我们下面的讲解。我们需要引入更多概念。
slot标签元素: 插槽元素, 用来占位,就是我们上学时,用一本书放在某个座位上占着位置。
带slot属性的元素: 插卡元素,用来替换同名的插槽元素。
然后到我们的组件,我们使用wbr, xmp, template, ms-*等元素来声明它们是某种组件,它们称之为组件容器(所有带ms-widget属性的元素都是插槽元素)。它们与插槽元素一样,是用来占位与被替换掉的。
<div ms-controller='widget1' >
<xmp :widget="{is:'ms-button'}" ><span slot="content">button!</span></xmp>
<p><button :click="@click">click</button></p>
</div>
那么组件容器是被谁替换呢?当然是组件。我们使用avalon.component来定义组件时,必须有一个template属性,它是一个HTML模块,它会转换为组件。比如说上面的ms-button.
avalon.component('ms-button', {
template: '<button type="button"><slot name="content" /></button>',
defaults: { }
})
template里面有slot元素来占位,而组件容器里面有带slot属性的元素来替换。
一个组件可以拥有N个slot元素,它们的name值不能重复。但是外面的插卡元素则可以重复。
avalon.component('ms-tabs', {
template: '<div><p>它有{{@num}}个面板</p><slot name="tab"/></div>',
defaults: {
num: 3
}
})
vm = avalon.define({
$id: 'widget1'
})
<div ms-controller='widget1' >
<xmp :widget="{is:'ms-tabs'}">
<div slot="tab">面板1</div>
<hr>
<div slot="tab">面板2</div>
<hr>
<div slot="tab">面板3</div>
<hr>
</xmp>
</div>
生成的结构如下:
这也是我们做切换卡的基础。好了,我们看一下切换卡是如何做的。
DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src='../../dist/avalon.js'></script>
<script>
function heredoc(fn) {
return fn.toString().replace(/^[^\/]+\/\*!?\s?/, '').
replace(/\*\/[^\/]+$/, '').trim().replace(/>\s*</g, '><')
}
avalon.component('ms-tabs', {
template: heredoc(function () {
/*
<div>
<div><slot name="btn"/></div>
<div><slot name="tab"/></div>
</div>
*/
}),
defaults: {
buttons: [],
tabs: [],
active: function (index) {
this.activeIndex = index
},
activeIndex: 0,
}
})
var vm = avalon.define({
$id: 'widget1',
buttons: [111, 222, 333],
aa: '动态内容',
ddd: function () {
console.log('xxxx')
},
change: function () {
vm.aa = '更新内容'+(new Date -0)
}
})
</script>
</head>
<body>
<h1>slot的使用</h1>
<p>对slot元素使用循环绑定生成大量元素,一起迁进组件内部</p>
<div ms-controller='widget1' >
<xmp :widget="{is:'ms-tabs',buttons: @buttons}">
<button ms-for='(index,button) in @buttons'
ms-click='@active(index)'
type='button'
slot='btn'
>{{button}}</button>
<div slot="tab" ms-visible="0 == @activeIndex">
<p>这是面板1</p>
</div>
<div slot="tab" ms-visible="1 == @activeIndex">
{{@aa}} <button ms-click="@change" type="button">change</button>
</div>
<div slot="tab" ms-visible="2 == @activeIndex">
这是面板3
</div>
</xmp>
</div>
</body>
</html>
切换卡包含两大块内容,上面用来切换的按钮,及下面的用来显示的面板。由于每次只显示一个面板,我们需要使用ms-visible来做隐藏。
最后生成的切换卡是这样的。
我们可以下这样的结论。slot用来为组件传入大片内容的, ms-widget配置项是用来传入够短的配置项。
大家可以在这里看到源码。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。