1.组件化概念

在开发中,我们将页面的某一部分功能编写成一个组件,以后直接在页面中引用即可,如导航栏,轮播图,等,封装成一个个的组件,以后直接使用即可

Vue的官方也推荐我们组件化开发,即一个组件就是一个vue文件

组件化的特点:

  • 组件化可以将功能实现模块化,奖该组件需要的html,js,csss代码集中在一起
  • 有利于代码的重用性
  • 提高开发效率

vue插件组织架构 vue如何进行组件化开发_html

 

 

2.局部组件和全局组件

2.1 局部组件

局部组件只能在当前页面使用,其他组件是无法使用的,建议在开发中尽可能的使用全局组件,也就是单页面开发(一个文件只有一个组件)

局部组件定义在当前组件的components中

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入vue.js-->
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <!--    局部组件只能在定义的当前文件中使用-->
    <navbar></navbar>

</div>
</body>
<script>
    new Vue({
        // vue管理的区域,所有的vue语法仅在该区域内生效
        el: '#app',
        data: {},
        // 定义局部组件
        components: {
            navbar: {
                template: `
                  <div>我是一个局部组件{{ name }}
                  <button @click="handler">点我</button>
                  </div>`,

                data() {
                    return {
                        name: 'kunmzhao'
                    }
                },
                methods: {
                    handler() {
                        alert('hello')
                    }
                }
            }
        }
    })
</script>
</html>

 

2.2 全局组件

全局组件定义之后,在任意的vue文件中都可以直接使用,就像html中的div标签一样使用

vue插件组织架构 vue如何进行组件化开发_vue.js_02

vue插件组织架构 vue如何进行组件化开发_html_03

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 引入vue.js-->
 7     <script src="js/vue.js"></script>
 8 </head>
 9 <body>
10 <div id="app">
11     <!--    全局组件的使用-->
12     <navbar></navbar>
13 
14 </div>
15 </body>
16 <script>
17     // 定义一个全局组件
18     Vue.component('navbar', {
19         template: `
20           <div>我是一个全局组件{{ name }}
21           <button @click="handler">点我</button>
22           </div>`,
23         // 组件大data必须是一个函数,返回的是一个对象
24         data() {
25             return {
26                 name: 'kunmzhao'
27             }
28         },
29         methods: {
30             handler() {
31                 alert('hello')
32             }
33         }
34     })
35     new Vue({
36         // vue管理的区域,所有的vue语法仅在该区域内生效
37         el: '#app',
38         data: {},
39     })
40 </script>
41 </html>

View Code

vue插件组织架构 vue如何进行组件化开发_Vue_04

3.组件间的通信

各个组件之间数据,方法都是隔离的,因此我们不同担心组件之间存在变量或者方法重名的方法,vue中组件之间的通信方式主要有以下3种

3.1 自定义属性实现父传子

该方式可以是全局组件,也可以是局部组件和父组件之间的通信

通信步骤

  • 父组件将数据传递给子组件的自定义属性中
  • 子组件接收自定义的属性
  • 子组件使用自定义的属性
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入vue.js-->
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <!-- 全局组件的使用: 将父组件的name传递给子组件自定义的属性 myname -->
    <navbar :myname="name"></navbar>

</div>
</body>
<script>
    // 定义一个全局组件
    Vue.component('navbar', {
        template: `
          <div>我是一个全局组件{{ myname }}</div>`,
        props: ['myname']

    })
    new Vue({
        el: '#app',
        data: {
            name: 'Victor'
        },
    })
</script>
</html>

 

3.2 自定义事件实现子传父

有一点需要特别注意,自定义的事件不能使用驼峰命名!!!,最好都用小写

通信步骤:

  • 子组件将需要发送的数据通过emit发送给指定的事件
  • 父组件注册事件
  • 父组件接收到事件之后,执行对应的函数
  • 父组件接收数据

vue插件组织架构 vue如何进行组件化开发_vue.js_02

vue插件组织架构 vue如何进行组件化开发_html_03

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 引入vue.js-->
 7     <script src="js/vue.js"></script>
 8 </head>
 9 <body>
10 <div id="app">
11     <!--    将子组件信息传递给父组件-->
12     <navbar @sendname="receiveName"></navbar>
13     <hr>
14     父组件接收来自子组件的信息 name:{{myname}}
15 </div>
16 </body>
17 <script>
18 
19     Vue.component('navbar', {
20         template: `
21           <div>
22           <span><input type="text" v-model="name"></span> ==>{{name}}
23           <br>
24           <button @click="handlerClick">点我,传递信息给父组件</button>
25 
26           </div>`,
27         data() {
28             return {
29                 name: ''
30             }
31         },
32         methods: {
33             handlerClick() {
34                 // 子组件发送事件
35                 this.$emit('sendname', this.name)
36             }
37         }
38 
39 
40     })
41     new Vue({
42         el: '#app',
43         data: {
44             myname: ''
45         },
46         methods: {
47             receiveName(name) {
48                 this.myname = name
49             }
50         }
51     })
52 </script>
53 </html>

View Code

vue插件组织架构 vue如何进行组件化开发_html_07

 

 

3.3 ref属性实现父子组件间通信

ref可以引用普通的标签,也可以引用自定义组件,引用普通标签可以在父组件中通过$refs获取标签的DOM 对象,引用组件则可以获取组件对象

在父组件中既然已经拿到组件或者标签的对象了,那我们就可以修改,获取内部数据,设置可以指定其内部方法

vue插件组织架构 vue如何进行组件化开发_vue.js_02

vue插件组织架构 vue如何进行组件化开发_html_03

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 引入vue.js-->
 7     <script src="js/vue.js"></script>
 8 </head>
 9 <body>
10 <div id="app">
11 
12     <hr>
13     <!--    ref引用自定义组件-->
14     <navbar ref="mynavbar"></navbar>
15     <hr>
16     <!--    ref引用普通组件-->
17     <input type="text" ref="myinput" v-model="myname">
18     <button @click="tosonclick">点我,将父组件消息传递给子组件</button>
19     <button @click="tofatherclick">点我,将子组件消息传递给父组件</button>
20 
21 </div>
22 </body>
23 <script>
24 
25     Vue.component('navbar', {
26         template: `
27           <div>
28           <span><input type="text" v-model="name"></span> ==>{{ name }}
29           <br>
30           </div>`,
31         data() {
32             return {
33                 name: ''
34             }
35         },
36         methods: {}
37 
38 
39     })
40     new Vue({
41         el: '#app',
42         data: {
43             myname: ''
44         },
45         methods: {
46             tosonclick() {
47                 // 将父组件数据传递给子组件
48                 this.$refs.mynavbar.name = this.myname
49             },
50             tofatherclick() {
51                 // 将子组件数据传递给父组件
52                 this.myname = this.$refs.mynavbar.name
53             }
54         }
55     })
56 </script>
57 </html>

View Code

 

3.4.写在本涨最后

该篇仅仅介绍了父子组件之间的通信方式,其实组件之间,或者嵌套很深的组件之间都是可以通信的,不过要借助Vuex第三方组件实现,后续补充

 

4. Vue内置组件

4.1 component组件

渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。is 的值是一个字符串,它既可以是 HTML 标签名称也可以是组件名称。

vue插件组织架构 vue如何进行组件化开发_vue.js_02

vue插件组织架构 vue如何进行组件化开发_html_03

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 引入vue.js-->
 7     <script src="js/vue.js"></script>
 8 </head>
 9 <body>
10 <div id="app">
11 
12     <ul>
13         <li @click="myname='input1'">输入框</li>
14         <li @click="myname='button1'">按钮</li>
15         <li @click="myname='navbar'">navbar</li>
16     </ul>
17     <!--    动态的显示某个组件-->
18     <component :is='myname'></component>
19 
20 </div>
21 </body>
22 <script>
23     // 组件1
24     Vue.component('input1', {
25         template: `
26           <div>
27           <input type="text">
28           </div>`,
29     })
30     // 组件2
31     Vue.component('button1', {
32         template: `
33           <div>
34           <button>点我</button>
35           </div>`,
36 
37     })
38     // 组件3
39     Vue.component('navbar', {
40         template: `
41           <div>
42           <span><input type="text" v-model="name"></span> ==>{{ name }}
43           <br>
44           </div>`,
45         data() {
46             return {
47                 name: ''
48             }
49         },
50         methods: {}
51 
52 
53     })
54     new Vue({
55         el: '#app',
56         data: {
57             myname: ''
58         },
59     })
60 </script>
61 </html>

View Code

vue插件组织架构 vue如何进行组件化开发_html_12

 

4.2 keep-alive组件

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们,常搭配component使用

比如我们希望在某个组件输入框输入了内容,此时有切换到别的组件,当我们切回之间的输入框组件时,期望输入的内容保存,就可以使用该组件

vue插件组织架构 vue如何进行组件化开发_vue.js_02

vue插件组织架构 vue如何进行组件化开发_html_03

1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 引入vue.js-->
 7     <script src="js/vue.js"></script>
 8 </head>
 9 <body>
10 <div id="app">
11 
12     <ul>
13         <li @click="myname='input1'">输入框</li>
14         <li @click="myname='button1'">按钮</li>
15         <li @click="myname='navbar'">navbar</li>
16     </ul>
17     <!--    动态的显示某个组件并且缓存-->
18     <keep-alive>
19         <component :is='myname'></component>
20 
21     </keep-alive>
22 
23 </div>
24 </body>
25 <script>
26     // 组件1
27     Vue.component('input1', {
28         template: `
29           <div>
30           <input type="text">
31           </div>`,
32     })
33     // 组件2
34     Vue.component('button1', {
35         template: `
36           <div>
37           <button>点我</button>
38           </div>`,
39 
40     })
41     // 组件3
42     Vue.component('navbar', {
43         template: `
44           <div>
45           <span><input type="text" v-model="name"></span> ==>{{ name }}
46           <br>
47           </div>`,
48         data() {
49             return {
50                 name: ''
51             }
52         },
53         methods: {}
54 
55 
56     })
57     new Vue({
58         el: '#app',
59         data: {
60             myname: ''
61         },
62     })
63 </script>
64 </html>

View Code

 

vue插件组织架构 vue如何进行组件化开发_vue.js_15

4.3 slot组件

在前面定义的子组件中,我们没有好的办法可以实现向子组件添加内容,如

vue插件组织架构 vue如何进行组件化开发_html_16

 

 

 

但是通过slot就可以很好的实现这一功能

4.3.1 不具名插槽

在子组件中只有一个slot插槽,因此不需要指定名字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入vue.js-->
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">

    <navbar>
        <div>hello</div>
    </navbar>

</div>
</body>
<script>

    Vue.component('navbar', {
        template: `
          <div>
          <p>我是子组件</p>
          <!-- 在子组件中定义一个插槽-->
          <slot></slot>

          </div>`,
        data() {
            return {
                name: ''
            }
        },
        methods: {}


    })
    new Vue({
        el: '#app',
        data: {
            myname: ''
        },
    })
</script>
</html>

 

4.3.2 具名插槽

在子组件中有多个插槽,需要指定名字

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 引入vue.js-->
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">

    <navbar>
        <div slot="img"><img src="https://img0.baidu.com/it/u=284864485,3694629534&fm=253&fmt=auto&app=138&f=JPEG?w=333&h=500" alt=""></div>
        <div slot="button"><button>点我</button></div>
    </navbar>

</div>
</body>
<script>

    Vue.component('navbar', {
        template: `
          <div>
          <p>我是子组件</p>
          <!-- 在子组件中定义多个插槽-->
          <slot name="img"></slot>
          <slot name="button"></slot>

          </div>`,
        data() {
            return {
                name: ''
            }
        },
        methods: {}


    })
    new Vue({
        el: '#app',
        data: {
            myname: ''
        },
    })
</script>
</html>

4.3.3 具名插槽的+<template v-slot>使用

将4.3.2中的例子改进如下:

这样在浏览器熏染后的页面就少了一层div

<navbar>
    <template v-slot:img><img src="https://img0.baidu.com/it/u=284864485,3694629534&fm=253&fmt=auto&app=138&f=JPEG?w=333&h=500" alt=""></template>
    <template v-slot:button><button>点我</button></template>
  </navbar>