一篇看懂vue.js内容分发
cn889770
8年前
<p>vue.js内容分发把组件上下文的内容注入到组件。</p> <h2>定义解析</h2> <p>现在我们看一个架空的例子,帮助理解刚刚说过的严谨而难懂的定义。假设有一个组件名为my-component,其使用上下文如下:</p> <pre> <code class="language-javascript"><my-component> <p>hi,slots</p> </my-component></code></pre> <p>再假设此组件的模板为:</p> <pre> <code class="language-javascript"><div> <slot></slot> <div></code></pre> <p>那么注入后的组件HTML相当于:</p> <pre> <code class="language-javascript"><div> <p>hi,slots</p> <div></code></pre> <p>标签<slot>会把组件使用上下文的内容注入到此标签所占据的位置上。组件分发的概念简单而强大,因为它意味着对一个隔离的组件除了通过属性、事件交互之外,还可以注入内容。</p> <p>此案例变成可以执行的代码,就是这样的:</p> <pre> <code class="language-javascript"><script src="https://unpkg.com/vue/dist/vue.js"></script> <div class="" id="app"> <my-component> <p>hi,slots</p> </my-component> </div> <script> Vue.component('my-component', { template: ` <div> <slot></slot> <div> ` }); new Vue({ el: "#app" }); </script></code></pre> <p>一个组件如果需要外部传入简单数据如数字、字符串等等的时候,可以使用property,如果需要传入js表达式或者对象时,可以使用事件,如果希望传入的是HTML标签,那么使用内容分发就再好不过了。所以,尽管内容分发这个概念看起来极为复杂,而实际上可以简化了解为把HTML标签传入组件的一种方法。所以归根结底,内容分发是一种为组件传递参数的方法。</p> <h2>命名插槽</h2> <p>刚刚的案例通过slot标签,一股脑的把组件上下文的内容全部注入到组件内的规定位置。vue.js也提供了命名插槽(named slot)的技术,可以把上下文内的内容分成多个有名字的部分,然后插入到组件的不同位置:</p> <pre> <code class="language-javascript"><script src="https://unpkg.com/vue/dist/vue.js"></script> <div class="" id="app"> <my-component> <p slot='slot1'>hi,slot1</p> <p slot='slot2'>hi,slot2</p> </my-component> </div> <script> Vue.component('my-component', { template: ` <div> <slot name='slot1'></slot> <slot name='slot2'></slot> <div> ` }); new Vue({ el: "#app" }); </script></code></pre> <p>此案例使用了两个插槽分别为slot1,slot2,并且把它们放到组件的不同位置。</p> <h2>综合案例</h2> <p>现在我们看一个高级的案例,我来做一个即时贴(sticky)组件,用来显示一个有标题和主体的即时贴。组件会定义好即时贴的结构,外观,而具体的标题和内容,而使用内容分发技术传入的HTML标签:</p> <pre> <code class="language-javascript"><script src="https://unpkg.com/vue/dist/vue.js"></script> <div class="" id="app"> <sticky> <div slot="title"> <h3>Title</h3></div> <div slot="body"><p> Body foo bar baz ddd </p></div> </sticky> </div> <script> Vue.component('sticky', { template: ` <div> <div class="wrapper"> <div> <div class="title"> <slot name="title"></slot> </div> <div class="body"> <slot name="body"></slot> </div> </div> </div> </div>` }); new Vue({ el: "#app" }); </script> <style> .wrapper { display: flex; width: 180px; height: 150px; background: yellow; border-radius: 10px; } .title { border-bottom:1px solid red } .body { border-bottom:1px solid blue } </style></code></pre> <p>本案例内,使用上下文通过属性slot创建了两个插槽,分别为title和body,在组件的模板内(template成员)通过<slot>标签的name属性引用title和body,并把它注入且放入到合适的位置上。</p> <p> </p> <p> </p> <p>来自:https://segmentfault.com/a/1190000007591093</p> <p> </p>