一. 组件及其交互
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>
运行效果:
!
- 作 者 : Yaopengfei(姚鹏飞)
- 博客地址 : http://www.cnblogs.com/yaopengfei/
- 声 明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
- 声 明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。