第四节:Vuejs组件及组件之间的交互

 一. 组件及其交互

1.组件的注册

(1).全局注册

   Vue.component('组件名称', { }) 第1个参数是标签名称,第2个参数是一个选项对象。

选项参数包括

  data:必须是一个function,然后要return,在return里面声明变量。

  template: 用``符号包裹

  methods: 声明方法

注意事项:

  A. 模板必须是单个根元素

  B. 如果使用驼峰式命名组件,那么在使用组件的时候,只能在另一个组件字符串模板中用驼峰的方式使用组件,在普通标签中直接使用的话,必须加短横线。如: HelloWord模板,在body里用的时候必须<hello-word>,而在btn-counter组件中,则可以直接使用<HelloWord>

总之:不推荐使用驼峰命名,建议小写+短横线。

       Vue.component('HelloWord', {
                template: `<div>我是HelloWord组件</div>`
            });
            Vue.component('btn-counter', {
                data: function() {
                    return {
                        count: 0
                    }
                },
                template: `
                    <div>
                      <div>{{count}}</div>
                      <button @click="handle">点击了{{count}}次</button>
                      <HelloWord></HelloWord>
                    </div>
                `,
                methods: {
                    handle: function() {
                        this.count += 3;
                    }
                }
            });
<p>1.全局组件</p>
<btn-counter></btn-counter>
<hello-word></hello-word>

(2).局部组件

  在Vue实例中components进行声明局部组件,仅供该实例使用。

2.父组件向子组件传值

  父组件发送形式是以属性的形式绑定在子组件上,可以直接往里传值,也可以用:符号进行绑定变量。然后子组件用属性props接收,props是一个数组。

注意事项:

  A.在props使用驼峰形式,在页面中需要使用短横线的形式字符串, 而在字符串模板中则没有这个限制。

  PS:这里面不演示了,总之在vue中不建议使用驼峰命名。

  B.比如p3是props里声明的一个属性,在使用的时候 p3:'true' 这种情况p3是string类型; 而 :p3:'true',这种情况p3是布尔类型。

3.子组件向父组件传值

  子组件用 $emit() 触发事件,第一个参数为 自定义的事件名称 第二个参数为需要传递的数据(这里最多只能传递一个参数了),父组件用v-on(或者@) 监听子组件的事件,这里用固定命名 $event 来获取子组件传递过来的参数。

详细案例如下

4.兄弟组件之间的交互

  兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据,提供事件中心 var hub = new Vue()。

  (1).传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据),这里可以传递多个数据哦

  (2).接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名,这里可以接收多个数据哦

  (3).销毁事件 通过hub.$off()方法名销毁之后无法进行传递数据

5.插槽

  组件的最大特性就是复用性,而用好插槽能大大提高组件的可复用能力,在template中使用<slot>标签

(1).匿名插槽

   使用时,组件标签中嵌套的内容(包含html)会替换掉slot; 如果不传值 ,则使用 slot 中的默认值。

(2).具名插槽

  使用时,通过slot属性来指定, 这个slot的值必须和下面slot组件得name值对应上 如果没有匹配到 则放到匿名的插槽中

特别注意:具名插槽的渲染顺序,完全取决于模板中的顺序,而不是取决于父组件中元素的顺序!

(3).作用于插槽

  A. 作用域插槽使用场景

    a.父组件对子组件加工处理

    b.既可以复用子组件的slot,又可以使slot内容不一致

  B.作用域插槽的使用

    a.子组件模板中,<slot>元素上有一个类似props传递数据给组件的写法msg="xxx

    b.插槽可以提供一个默认内容,如果如果父组件没有为这个插槽提供了内容,会显示默认的内容。 如果父组件为这个插槽提供了内容,则默认的内容会被替换掉

完整代码如下:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="utf-8">
  5         <title>06-组件及交互</title>
  6         <style type="text/css">
  7             p {
  8                 font-size: 20px;
  9                 color: #0000FF;
 10                 font-weight: bold;
 11             }
 12             .current {
 13               color: orange;
 14             }
 15         </style>
 16     </head>
 17     <body>
 18         <div id="myApp">
 19             <p>1.全局组件</p>
 20             <btn-counter></btn-counter>
 21             <hello-word></hello-word>
 22             <p>2.局部组件</p>
 23             <ypfzj1></ypfzj1>
 24             <p>3.父组件向子组件传值</p>
 25             <father-child p1="ypf1" :p2="p2" p3="true"></father-child>
 26             <father-child p1="ypf1" :p2="p2" :p3="true"></father-child>
 27             <p>4.子组件向父组件传值</p>
 28             <div :style="{fontSize:myFontSize+'px'}">我是内容,等着被控制</div>
 29             <child-father @exchangebig='handle1($event)'></child-father>
 30             <p>5.兄弟组件相互交互</p>
 31             <brother-one></brother-one>
 32             <brother-two></brother-two>
 33             <button @click="destoryHandle">销毁事件</button>
 34             <p>6.1 匿名插槽</p>
 35             <my-tips1>您超标了</my-tips1>
 36             <my-tips1>用户名不正确</my-tips1>
 37             <my-tips1></my-tips1>
 38             <p>6.2 具名插槽</p>
 39             <my-tips2>
 40                 <div slot='header'>我是header</div>
 41                 <div>我是内容1</div>
 42                 <div>我是内容2</div>
 43                 <div slot='footer'>我是footer</div>
 44             </my-tips2>
 45             <my-tips2>
 46                 <div slot='footer'>我是footer</div>                
 47                 <div>我是内容1</div>
 48                 <div slot='header'>我是header</div>
 49                 <div>我是内容2</div>            
 50             </my-tips2>
 51             <p>6.3 作用域插槽</p>
 52             <my-tips3 :list='list'>
 53              <template slot-scope='slotProps'>
 54                 <strong v-if='slotProps.info.id==3' class="current">{{slotProps.info.name}}</strong>
 55                 <span v-else>{{slotProps.info.name}}</span>
 56               </template>
 57             </my-tips3>
 58         </div>
 59 
 60         <script src="js/vue.min.js" type="text/javascript" charset="utf-8"></script>
 61         <script type="text/javascript">
 62             //全局组件
 63             Vue.component('HelloWord', {
 64                 template: `<div>我是HelloWord组件</div>`
 65             });
 66             Vue.component('btn-counter', {
 67                 data: function() {
 68                     return {
 69                         count: 0
 70                     }
 71                 },
 72                 template: `
 73                     <div>
 74                       <div>{{count}}</div>
 75                       <button @click="handle">点击了{{count}}次</button>
 76                       <HelloWord></HelloWord>
 77                     </div>
 78                 `,
 79                 methods: {
 80                     handle: function() {
 81                         this.count += 3;
 82                     }
 83                 }
 84             });
 85             //父组件向子组件中传值
 86             Vue.component('father-child', {
 87                 props: ['p1', 'p2', 'p3'],
 88                 data: function() {
 89                     return {
 90                         msg: '我是用来看父组件向子组件中传值的'
 91                     }
 92                 },
 93                 template: `
 94                     <div>
 95                         <div>{{msg+"--"+p1+"--"+p2+"--"+p3}}</div>
 96                         <div>p3的类型为:{{typeof p3}}</div>
 97                     </div>                `
 98             });
 99             
100             //子组件向父组件传值
101             Vue.component('child-father', {
102                 props: [],
103                 data: function() {
104                     return {
105                         msg: '我是用来看父组件向子组件中传值的'
106                     }
107                 },
108                 template: `
109                     <div>
110                         <button @click='$emit("exchangebig",5)'>增大测试1</button>
111                         <button @click='$emit("exchangebig",10)'>增大测试2</button>
112                     </div>                `
113             });
114             //两个兄弟组件
115             //事件中心
116             var hub = new Vue();
117             Vue.component('brother-one', {
118                 data: function() {
119                     return {
120                         num: 0
121                     }
122                 },
123                 template: `
124                     <div>
125                         <div>borther1:{{num}}</div>
126                         <div>
127                             <button @click='handle'>控制兄弟brother2</button>
128                         </div>
129                     </div>
130                 `,
131                 methods: {
132                     handle: function() {
133                         //传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
134                         hub.$emit('yChild2Event', 2, 1);
135                     }
136                 },
137                 //Dom创建后
138                 mounted: function() {
139                     //接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名)
140                     hub.$on('yChild1Event', (val1, val2) => {
141                         this.num += val1 + val2;
142                     });
143                 }
144             })
145             Vue.component('brother-two', {
146                 data: function() {
147                     return {
148                         num: 0
149                     }
150                 },
151                 template: `
152                     <div>
153                         <div>borther2:{{num}}</div>
154                         <div>
155                             <button @click='handle'>控制兄弟brother1</button>
156                         </div>
157                     </div>
158                 `,
159                 methods: {
160                     handle: function() {
161                         //传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据) 触发兄弟组件的事件
162                         hub.$emit('yChild1Event', 4, 3);
163                     }
164                 },
165                 //Dom创建后
166                 mounted: function() {
167                     //接收数据方,通过mounted(){} 钩子中 触发hub.$on(方法名)
168                     hub.$on('yChild2Event', (val1, val2) => {
169                         this.num += val1 + val2;
170                     });
171                 }
172             })
173             //匿名插槽
174             Vue.component('my-tips1',{
175                 template:`
176                     <div>
177                       <strong>提醒:</strong>
178                       <slot>默认内容</slot>
179                       <slot>默认内容1</slot>
180                     </div>
181                 `,
182             })
183             //具名插槽
184             Vue.component('my-tips2', {
185               template: `
186                 <div>
187                     <div>我是具名插槽</div>
188                     <slot name='header'></slot>
189                     <slot></slot>
190                     <slot name='footer'></slot>
191                 </div>
192               `
193             });
194             //作用域插槽
195             Vue.component('my-tips3', {
196               props: ['list'],
197               template: `
198                 <div>
199                   <li :key='item.id' v-for='item in list'>
200                     <slot :info='item'>{{item.name}}</slot>
201                   </li>
202                 </div>
203               `
204             });
205             
206             //放在下面的局部组件里
207             var ypfzj1 = {
208                 data: function() {
209                     return {
210                         msg: '我是局部组件1'
211                     }
212                 },
213                 template: '<div>{{msg}}</div>'
214             };
215 
216             //Vm实例
217             var vm = new Vue({
218                 el: '#myApp',
219                 data: {
220                     p2: 'ypf2',
221                     myFontSize: 12,
222                     list: [{
223                       id: 1,
224                       name: 'apple'
225                     },{
226                       id: 2,
227                       name: 'orange'
228                     },{
229                       id: 3,
230                       name: 'banana'
231                     }]
232                 },
233                 methods: {
234                     handle1: function(val) {
235                         this.myFontSize += val;
236                     },
237                     //销毁事件
238                     destoryHandle: function() {
239                         hub.$off('yChild1Event');
240                         hub.$off('yChild2Event');
241                     }
242                 },
243                 components: {
244                     'ypfzj1': ypfzj1,
245                 }
246             });
247         </script>
248     </body>
249 </html>
View Code

运行效果:

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

猜你喜欢

转载自www.cnblogs.com/yaopengfei/p/12326466.html
今日推荐