vue.js学习之组件(下篇)

 本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星!

https://github.com/zwl-jasmine95/Vue_test

 以下所有知识都是基于vue.js 2.0版本


 

一、组件编译作用域

<child-component> {{ message }}child-component>

message 应该绑定到父组件的数据,组件作用域简单地说是:

父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

组件的模板是在其作用域内编译的,那么组件选项对象中的数据也应该是在组件模板中使用的。

 1     <div id="component-demo">
 2         
 3         <hello-component>hello-component>
 4     div>
 5 
 6 <script type="text/javascript">
 7     Vue.component('hello-component',{
 8         template:'

hello component!

' 9 }); 10 var vm = new Vue({ 11 el:'#component-demo' 12 }); 13 14 script>

在创建一个Vue实例时,除了将它挂载到某个HTML元素下,还要编译组件,将组件转换为HTML片段。
除此之外,Vue实例还会识别其所挂载的元素下的标签,然后将标签替换为HTML片段。

实际上浏览器仍然是不理解标签的,

vue.js学习之组件(下篇)_第1张图片

组件在使用前,经过编译已经被转换为HTML片段了,组件是有一个作用域的,那么组件的作用域可以将它理解为组件模板包含的HTML片段,组件模板内容之外就不是组件的作用域了。

例如,hello-component组件的作用域只是下面这个小片段:

通俗地讲,在子组件中定义的数据,只能用在子组件的模板。在父组件中定义的数据,只能用在父组件的模板。如果父组件的数据要在子组件中使用,则需要子组件定义props。

 


 

二、使用slot分发内容

 1、什么是“内容分发”?

在使用组件时,往往会这样:

<app>
  <app-header>app-header>
  <app-footer>app-footer>
app>

注意两点:

  1.  组件不知道它会收到什么内容。这是由使用  的父组件决定的。

  2.  组件很可能有它自己的模版。

为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发。Vue.js 实现了一个内容分发 API,参照了当前 Web 组件规范草案,使用特殊的  元素作为原始内容的插槽。

 

2、单个slot

 1 DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>单个slottitle>
 6     <script type="text/javascript" src="../lib/js/vue.js">script>
 7 head>
 8 <body>
 9     <div id="demo">
10         <h1>我是父组件h1>
11         <my-component>
12             <p>这是初始内容1p>
13             <p>这是初始内容2p>
14         my-component>
15     div>
16 
17     <template id="myComponent">
18         <div>
19             <h1>我是子组件的标题h1>
20             <slot>没有分发内容的时候才会显示slot>
21         div>
22     template>
23 
24     <script type="text/javascript">
25 
26         Vue.component('my-component',{
27             template:'#myComponent'
28         });
29 
30         var vm = new Vue({
31             el:'#demo'
32         });
33     script>
34 
35 body>
36 html>
View Code

结果:

vue.js学习之组件(下篇)_第2张图片

vue.js学习之组件(下篇)_第3张图片

 除非子组件模板包含至少一个  插口,否则父组件的内容将会被丢弃(其他情况2)当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。

最初在  标签中的任何内容都被视为备用内容。备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。

  •  其他情况1:删除父组件模板中的内容

vue.js学习之组件(下篇)_第4张图片     vue.js学习之组件(下篇)_第5张图片

  •  其他情况2:删除子组件模板里的

vue.js学习之组件(下篇)_第6张图片

  • 其他情况3:子组件里有多个

 vue.js学习之组件(下篇)_第7张图片vue.js学习之组件(下篇)_第8张图片

(当然,这里有两个匿名会有警告,应该用特殊的属性 name 来配置如何分发内容。详见第三节 具名slot)

 

 3、具名slot

 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。

 demo :

 1 DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>具名slottitle>
 6     <script type="text/javascript" src="../lib/js/vue.js">script>
 7 head>
 8 <body>
 9     <div id="demo">
10         <h1>我是父组件h1>
11         <my-component>
12             <h1 slot="header">这里可能是一个页面标题h1>
13             <p>主要内容的一个段落。p>
14             <p>另一个主要段落。p>
15             <p slot="footer">这里有一些联系信息p>
16         my-component>
17     div>
18 
19     <template id="myComponent">
20         <div class="container">
21             <header>
22                 <slot name="header">slot>
23             header>
24             <main>
25                 <slot>这里是匿名slotslot>
26             main>
27             <footer>
28                 <slot name="footer">slot>
29             footer>
30         div>
31     template>
32 
33     <script type="text/javascript">
34 
35         Vue.component('my-component',{
36             template:'#myComponent'
37         });
38 
39         var vm = new Vue({
40             el:'#demo'
41         });
42     script>
43 body>
44 html>
View Code

 vue.js学习之组件(下篇)_第9张图片

 

vue.js学习之组件(下篇)_第10张图片

 4、作用域插槽

2.1.0新增

 作用域插槽是一种特殊类型的插槽,用作使用一个 (能够传递数据到) 可重用模板替换已渲染元素。

 1   <div class="parent">
 2         <child>
 3             <template scope="props">
 4                 <span>hello from parentspan>
 5                 <span>{{ props.text }}span>
 6             template>
 7         child>
 8     div>
 9 
10     <template id="myComponent">
11         <div class="child">
12             <slot text="hello from child">没有分发内容的时候才会显示slot>
13         div>
14     template>
15 
16     <script type="text/javascript">
17         Vue.component('child',{
18             template:'#myComponent'
19         });
20         
21         var vm = new Vue({
22             el:'.parent'
23         });
24     script>

vue.js学习之组件(下篇)_第11张图片

 

 在子组件中,只需将数据传递到插槽,就像你将 props 传递给组件一样

在父级中,具有特殊属性 scope 的