博客园 首页 新随笔 联系 订阅 管理
一、组件化开发概述
  1.组件化开发思想
    标准
    分治:不同的功能分配到不同的组件中
    重用:
    组合

 

  2.编程中的组件化思想体现

 

  3.组件化规范:
    Web Components
      我们希望尽可能多的重用代码
      自定义组件的方式不太容易(html、css和js)
      多次使用组件可能导致冲突

 

    Web Components通过创建封装好功能的定制元素解决上述问题

 

    Vue部分实现了上述规范

 

    不同的功能封装到不同的组件中,组件可以组合以形成完整的应用
 
二、组件的注册
 
  2.1 全局组件注册语法
    Vue.component(组件名称,{
      data:组件数据,
      template:组件模板内容
    })
 
  例:
1 // 定义一个名为button-counter的组件
2         Vue.component('button-counter',{
3             data:function(){
4                 return{
5                     count:0
6                 }
7             },
8             template:`<button @click='count++'>点击了{{count}}次</button>`
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:`<div>{{msg}}</div>`
 8         };
 9 
10         var HelloTom = {
11             data:function(){
12                 return{
13                     msg:'Hello Tom'
14                 }
15             },
16             template:`<div>{{msg}}</div>`
17         };
18 
19         var HelloJerry = {
20             data:function(){
21                 return{
22                     msg:'Hello Jerry'
23                 }
24             },
25             template:`<div>{{msg}}</div>`
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         })

 

    注:局部组件只能在父组件中使用,不能在其他的组件中使用
 
三、Vue调试工具

  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:`<div>{{msg + '----' + title + '----' + content}}</div>`
 9         })
10         var vm = new Vue({
11             el:'#app',
12             data:{
13                 pmsg:'父组件中的内容',
14                 ptitle:'父组件传向子组件的动态绑定的数据'
15             }
16         })

    

   4.2 props属性名规则
     1.在props中使用驼峰的形式,模板中需要使用短横线的形式
     2.字符串形式的模板中没有这个限制   
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:`<div>{{testTitle}}</div>`
 4         })
 5         Vue.component('menu-item',{
 6             props:['menuTitle'],
 7             template:`<div>{{menuTitle}}<third-com testTitle="啦啦啦"></third-com></div>`
 8         })
 9         var vm = new Vue({
10             el:'#app',
11             data:{
12                 pmsg:'父组件中的内容',
13                 ptitle:'动态绑定属性'
14             },
15 })
    4.3 props属性值类型
 
      字符串  String
      数值     Number
      布尔值  Boolean
      数组     Array
      对象     Object 1<div id="app"> 2<!--       
 3             字符串  String
 4             数值     Number
 5             布尔值  Boolean
 6             数组     Array
 7             对象     Object 
 8         -->
 9         <menu-item :pstr='pstr' :pnum='pnum' :pboo='pboo' :parr='parr' :pobj='pobj'></menu-item>
10     </div>

 

 1 Vue.component('menu-item',{
 2             props:['pstr','pnum','pboo','parr','pobj'],
 3             template:`<div>
 4                         <div>{{"传递的是字符串" + pstr}}</div>
 5                         <div>{{"传递的是数字" + pnum}}</div>
 6                         <div>{{"传递的是布尔值" + pboo}}</div>
 7                         <div>数组:</div>
 8                         <ul>
 9                             <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
10                         </ul>
11                         <div>{{"传递的是对象:"}}<span>{{pobj.name}}</span><span>{{pobj.age}}</span></div>
12                     </div>`
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         })

       

    4.4 子组件向父组件传值
 
      注:props传递数据原则: 单向数据流,只允许父组件向子组件传递数据,不允许子组件直接操作props的数据
 
      1. 子组件通过自定义事件向父组件传值
        <button v-on:click='$emit("enlarge-text")'>扩大字体</button>
 
      2. 父组件监听子组件事件
        <menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
 
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:`
 7                 <div>
 8                     <ul>
 9                         <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
10                     </ul>
11                     <button @click='parr.push("lemon")'>点击</button>
12                     <button @click='$emit("enlarge-text")'>扩大父组件中字体大小</button>
13                 </div>
14             `
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         })
      
      3. 子组件通过自定义事件向父组件传递消息
        <button v-on:click='$emit("enlarge-text",0.1)'>扩大字体</button>
 
      4. 父组件监听子组件的事件
        <menu-item v-on:enlarge-text='fontSize += $event'></menu-item>

        $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:`
 4                 <div>
 5                     <ul>
 6                         <li :key='index' v-for='(item,index) in parr'>{{item}}</li>
 7                     </ul>
 8                     <button @click='parr.push("lemon")'>点击</button>
 9                     <button @click='$emit("enlarge-text",5)'>扩大父组件中字体大小</button>
10                     <button @click='$emit("enlarge-text",10)'>扩大父组件中字体大小</button>
11                 </div>
12             `
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         })
 
 
    4.5 非父子组件间传值
      1. 单独的事件中心管理组件间的通信
        var eventHub = new Vue()

      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                 <div>
12                     <div>TOM:{{num}}</div>
13                     <div>
14                         <button @click='handle'>点击</button>
15                     </div>
16                 </div>
17             `,
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:`
38                 <div>
39                     <div>JERRY:{{num}}</div>
40                     <div>
41                         <button @click='handle'>点击</button>
42                     </div>
43                 </div>
44             `,
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         })

 

五、组件插槽
    5.1 组件插槽的作用
      父组件向子组件传递内容
      <alert-box>hi</alert-box> -> <slot></slot>
 
    
    5.2 组件插槽的基本用法
      1.插槽的位置
        Vue.component('alert-box',{
          template:`
            <div class="demo-alert-box">
            <strong>Error!</strong>
            <slot></slot>
            </div>
              `
        })
      2.插槽的位置
        <alert-box>Something bad happened</alert-box>       
1 <div id="app">
2         <alert-box>啦啦啦</alert-box>
3         <alert-box></alert-box>
4 </div>

    

 1 Vue.component('alert-box',{
 2             template:`
 3                     <div>
 4                         <strong>ERROR:</strong>
 5                         <slot>默认内容</slot>
 6                     </div>
 7             `
 8         })
 9         var vm = new Vue({
10             el:'#app',
11             data:{
12 
13             }
14         })

 

    5.3 具名插槽用法
      1.插槽定义
      <div class="container">
        <header>
          <slot name="header"></slot>
        </header>
 
        <main>
          <slot></slot>
        </main>
 
        <footer>
          <slot name="footer"></slot>
        </footer>
      </div>
      2.插槽内容
        <base-layout>
          <h1 slot="header">标题内容</h1>
          <p>主要内容1</p>
          <p>主要内容2</p>
          <p slot="footer">底部内容</p>
        </base-layout>
 
    5.4 作用域插槽
      应用场景:父组件对子组件内容进行加工处理
 
六、基于组件的案例 - 购物车

    6.1 按照组件化的方式实现业务需求
      根据业务功能进行组件化划分
        (1) 标题组件 展示文本
        (2) 列表组件 列表展示、商品数量变更、商品删除
        (3) 结算组件 计算商品总额

      实现整体布局和样式效果
        划分独立的功能组件
        组合所有的子组件形成整体结构
        逐个实现各个组件功能
        标题组件
        列表组件
        结算组件
      
posted on 2022-01-18 22:35  Computer_Science  阅读(34)  评论(0编辑  收藏  举报