4.Vue组件
一、组件化开发概述
1.组件化开发思想
标准
分治:不同的功能分配到不同的组件中
重用:
组合
2.编程中的组件化思想体现
3.组件化规范:
Web Components
我们希望尽可能多的重用代码
自定义组件的方式不太容易(html、css和js)
多次使用组件可能导致冲突
Web Components通过创建封装好功能的定制元素解决上述问题
Vue部分实现了上述规范
不同的功能封装到不同的组件中,组件可以组合以形成完整的应用
二、组件的注册
2.1 全局组件注册语法
Vue.component(组件名称,{
data:组件数据,
template:组件模板内容
})
例:
2.3 组件注册注意事项 1.data必须是一个函数 分析函数与普通对象的对比 2.组件模板内容必须是单个的根元素 分析实际演示效果 3.组件模板内容可以是模板字符串 模板字符串需要浏览器提供支持(ES6语法) 4.组件的命名方式 短横线 Vue.component('my-component',{/*...*/}) 驼峰式 Vue.component('MyComponent',{/*...*/}) 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
2.4 局部组件注册 var ComponentA = { /* ... */} var ComponentB = { /* ... */} var ComponentC = { /* ... */} new Vue({ el:'#app', components:{ 'component-a':ComponentA, 'component-b':ComponentB, 'component-c':ComponentC, } })
3.1 调试工具安装 (1) 克隆仓库 (2) 安装依赖包 (3) 构建 (4) 打开Chrome扩展页面 (5) 选中开发者模式 (6) 加载已解压的扩展,选择shells/chrome 四、组件间数据交互 4.1 父组件向子组件传值 1.子组件中通过props接收父组件传递过来的内容,具体通过属性名来接收 2.父组件通过属性将值传递给子组件,属性绑定有两种方式,一是写死,二是动态绑定 3.属性可以传递多个,具体可以在props中多加参数
$event是固定的
2. 监听事件与销毁事件 eventHub.$on('add-todo',addTodo) eventHub.$off('add-todo')
3. 触发事件 eventHub.$emit('add-todo',id)hi ->
5.2 组件插槽的基本用法
1.插槽的位置
Vue.component('alert-box',{
template:`
Something bad happened
2.插槽内容
5.4 作用域插槽
应用场景:父组件对子组件内容进行加工处理
1 // 定义一个名为button-counter的组件 2 Vue.component('button-counter',{ 3 data:function(){ 4 return{ 5 count:0 6 } 7 }, 8 template:`` 9 });2.2 组件的用法
1 <div id="app"> 2 <button-counter>button-counter> 3 <button-counter>button-counter> 4 <button-counter>button-counter> 5 div>注:组件可以重用,且组件之间是相互独立的
2.3 组件注册注意事项 1.data必须是一个函数 分析函数与普通对象的对比 2.组件模板内容必须是单个的根元素 分析实际演示效果 3.组件模板内容可以是模板字符串 模板字符串需要浏览器提供支持(ES6语法) 4.组件的命名方式 短横线 Vue.component('my-component',{/*...*/}) 驼峰式 Vue.component('MyComponent',{/*...*/}) 如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件,但是在普通的标签模板中,必须使用短横线的方式使用组件
2.4 局部组件注册 var ComponentA = { /* ... */} var ComponentB = { /* ... */} var ComponentC = { /* ... */} new Vue({ el:'#app', components:{ 'component-a':ComponentA, 'component-b':ComponentB, 'component-c':ComponentC, } })
1 var HelloWorld = { 2 data:function(){ 3 return{ 4 msg:'Hello World' 5 } 6 }, 7 template:`注:局部组件只能在父组件中使用,不能在其他的组件中使用 三、Vue调试工具{{msg}}` 8 }; 9 10 var HelloTom = { 11 data:function(){ 12 return{ 13 msg:'Hello Tom' 14 } 15 }, 16 template:`{{msg}}` 17 }; 18 19 var HelloJerry = { 20 data:function(){ 21 return{ 22 msg:'Hello Jerry' 23 } 24 }, 25 template:`{{msg}}` 26 }; 27 var vm = new Vue({ 28 el:'#app', 29 data:{ 30 31 }, 32 components:{ 33 'hello-world':HelloWorld, 34 'hello-tom':HelloTom, 35 'hello-jerry':HelloJerry 36 } 37 })
3.1 调试工具安装 (1) 克隆仓库 (2) 安装依赖包 (3) 构建 (4) 打开Chrome扩展页面 (5) 选中开发者模式 (6) 加载已解压的扩展,选择shells/chrome 四、组件间数据交互 4.1 父组件向子组件传值 1.子组件中通过props接收父组件传递过来的内容,具体通过属性名来接收 2.父组件通过属性将值传递给子组件,属性绑定有两种方式,一是写死,二是动态绑定 3.属性可以传递多个,具体可以在props中多加参数
1 <div id="app"> 2 {{pmsg}} 3 <menu-item title='来自父组件的值'>menu-item> 4 <menu-item :title='ptitle' content='hello'>menu-item> 5 div>
1 Vue.component('menu-item',{ 2 props:['title','content'], 3 data:function(){ 4 return{ 5 msg:'子组件自身的数据' 6 } 7 }, 8 template:`4.2 props属性名规则 1.在props中使用驼峰的形式,模板中需要使用短横线的形式 2.字符串形式的模板中没有这个限制{{msg + '----' + title + '----' + content}}` 9 }) 10 var vm = new Vue({ 11 el:'#app', 12 data:{ 13 pmsg:'父组件中的内容', 14 ptitle:'父组件传向子组件的动态绑定的数据' 15 } 16 })
1 <div id="app"> 2 {{pmsg}} 3 <menu-item :menu-title='ptitle'>menu-item> 4 div>
1 Vue.component('third-com',{ 2 props:['testTitle'], 3 template:`4.3 props属性值类型 字符串 String 数值 Number 布尔值 Boolean 数组 Array 对象 Object 1<div id="app"> 2 9 <menu-item :pstr='pstr' :pnum='pnum' :pboo='pboo' :parr='parr' :pobj='pobj'>menu-item> 10 div>{{testTitle}}` 4 }) 5 Vue.component('menu-item',{ 6 props:['menuTitle'], 7 template:`{{menuTitle}}` 8 }) 9 var vm = new Vue({ 10 el:'#app', 11 data:{ 12 pmsg:'父组件中的内容', 13 ptitle:'动态绑定属性' 14 }, 15 })
1 Vue.component('menu-item',{ 2 props:['pstr','pnum','pboo','parr','pobj'], 3 template:`4.4 子组件向父组件传值 注:props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据 1. 子组件通过自定义事件向父组件传值 2. 父组件监听子组件事件4` 13 }) 14 var vm = new Vue({ 15 el:'#app', 16 data:{ 17 pmsg:'父组件中的内容', 18 pstr:'hello', 19 pnum:12, 20 pboo:true, 21 parr:['apple','orange','banana'], 22 pobj:{ 23 name:'lisi', 24 age:12 25 } 26 } 27 }){{"传递的是字符串" + pstr}}5{{"传递的是数字" + pnum}}6{{"传递的是布尔值" + pboo}}7数组:89
11- for='(item,index) in parr'>{{item}}
10{{"传递的是对象:"}}{{pobj.name}}{{pobj.age}}12
1 <div id="app"> 2 <div :style='{fontSize:fontSize + "px"}'>{{pmsg}}div> 3 <menu-item :parr='parr' @enlarge-text='handle'>menu-item> 4 div>
1 /* 2 props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据 3 */ 4 Vue.component('menu-item',{ 5 props:['parr'], 6 template:` 73. 子组件通过自定义事件向父组件传递消息 4. 父组件监听子组件的事件814 ` 15 }) 16 var vm = new Vue({ 17 el:'#app', 18 data:{ 19 pmsg:'父组件中内容', 20 parr:['apple','orange','banana'], 21 fontSize:10 22 }, 23 methods: { 24 handle:function(){ 25 // 扩大字体大小 26 this.fontSize += 5; 27 } 28 }, 29 })9
11 12 13- for='(item,index) in parr'>{{item}}
10
$event是固定的
1 <div id="app"> 2 <div :style='{fontSize:fontSize + "px"}'>{{pmsg}}div> 3 <menu-item :parr='parr' @enlarge-text='handle($event)'>menu-item> 4 div>
1 Vue.component('menu-item',{ 2 props:['parr'], 3 template:` 44.5 非父子组件间传值 1. 单独的事件中心管理组件间的通信 var eventHub = new Vue()512 ` 13 }) 14 var vm = new Vue({ 15 el:'#app', 16 data:{ 17 pmsg:'父组件中内容', 18 parr:['apple','orange','banana'], 19 fontSize:10 20 }, 21 methods: { 22 handle:function(val){ 23 // 扩大字体大小 24 this.fontSize += val; 25 } 26 }, 27 })6
8 9 10 11- for='(item,index) in parr'>{{item}}
7
2. 监听事件与销毁事件 eventHub.$on('add-todo',addTodo) eventHub.$off('add-todo')
3. 触发事件 eventHub.$emit('add-todo',id)
1 <div id="app"> 2 <div>父组件div> 3 <div><button @click='handle'>销毁事件button>div> 4 <test-tom>test-tom> 5 <test-jerry>test-jerry> 6 div>
1 // 提供事件中心 2 var hub = new Vue(); 3 4 Vue.component('test-tom',{ 5 data:function(){ 6 return{ 7 num:0 8 } 9 }, 10 template:` 11五、组件插槽 5.1 组件插槽的作用 父组件向子组件传递内容1217 `, 18 methods: { 19 handle:function(){ 20 // 触发兄弟组件的事件 21 hub.$emit('jerry-event',2); 22 } 23 }, 24 mounted:function(){ 25 // 监听事件 26 hub.$on('tom-event',(val) =>{ 27 this.num += val; 28 }); 29 } 30 }); 31 Vue.component('test-jerry',{ 32 data:function(){ 33 return{ 34 num:0 35 } 36 }, 37 template:` 38TOM:{{num}}1314 15163944 `, 45 methods: { 46 handle:function(){ 47 // 触发兄弟组件的事件 48 hub.$emit('tom-event',1); 49 } 50 }, 51 mounted:function(){ 52 // 监听事件 53 hub.$on('jerry-event',(val) =>{ 54 this.num += val; 55 }); 56 } 57 }); 58 59 var vm = new Vue({ 60 el:'#app', 61 data:{ 62 63 }, 64 methods: { 65 handle:function(){ 66 hub.$off('tom-event'); 67 hub.$off('jerry-event'); 68 } 69 }, 70 })JERRY:{{num}}4041 4243
Error!
`
})
2.插槽的位置
1 <div id="app"> 2 <alert-box>啦啦啦alert-box> 3 <alert-box>alert-box> 4 div>
1 Vue.component('alert-box',{ 2 template:` 35.3 具名插槽用法 1.插槽定义4 ERROR: 57 ` 8 }) 9 var vm = new Vue({ 10 el:'#app', 11 data:{ 12 13 } 14 })默认内容 6
标题内容
主要内容1
主要内容2
底部内容