vue组件的基本介绍

组件化简介

平时在浏览页面的时候会发现很多页面里面的内容是一样或者类似的,这些内容的代码只是写了一遍,而不是针对每个页面都写一遍。我们可以把一个页面中的内容拆分成多个块,每个块实现自己的功能,这些块就是组件了,即多个组件构成了一个页面,这样做的好处是增强了代码的复用性,便于后续功能的扩展和维护。

组件化是Vue.js中的重要思想,任何的应用都会被抽象成一颗组件树,如下图,左侧是一个完整的页面,该页面是由右侧多个组件构成的。

组件的基本使用

如果没有组件的话,写出来的代码可能是这样的:

<div id="app">
  <div>
    <span>111</span>
    <span>222</span>
    <span>333</span>
  </div>

  <div>
    <span>111</span>
    <span>222</span>
    <span>333</span>
  </div>

  <div>
    <span>111</span>
    <span>222</span>
    <span>333</span>
  </div>
</div>

如果有多个地方需要使用这个包含span的div的话,这段代码就像上面这样出现了多次,当其中span发生变化的话,要修改很多次。使用组件之后可以简化页面的管理和维护,提升了扩展性。

使用组件解决上面的问题,创建组件的步骤如下:

  • 1.通过Vue中的componet来注册组件。
  • 2.通过注册的组件名字来使用组件。

注意事项:组件名字必须要挂载到Vue实例下,即需要再Vue实例作用范围下使用组件,例如下面都写到了id=app的div里面。注意在template中使用的是“优雅的实现标签的拼接。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <div id="app">
            <div-span></div-span>
            <div-span></div-span>
            <div-span></div-span>
        </div>
        <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
        <script>
            //注册组件,div-span是组件的名字,直接写到html标签中即可
            Vue.component("div-span",{
               template:`
                <div>
                  <span>111</span>
                  <span>222</span>
                  <span>333</span>
                </div>
               `
             })
            const app = new Vue({
                el: '#app'
            })
        </script>
    </body>
</html>

全局组件和局部组件

上面创建的组件是全局组件,全局组件可以在任意Vue实例下使用,例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!--全局组件可以在任意vue实例下使用-->
<div id="app1">
    <div-span></div-span>
    <div-span></div-span>
    <div-span></div-span>
</div>
<div id="app2">
    <div-span></div-span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    //注册组件,div-span是组件的名字,直接写到html标签中即可
    Vue.component("div-span", {
        template: 
                `<div>
                  <span>111</span>
                  <span>222</span>
                  <span>333</span>
                </div>`
    })

    const app1 = new Vue({
        el: '#app1'
    })
    const app2 = new Vue({
        el: '#app2'
    })
</script>
</body>
</html>

倘若希望组件只能在某个vue实例中使用的话,全局组件就不合适了,此时可以注册局部组件,局部组件只能在他所在的vue实例中使用。通常在开发中使用较多的是局部组件,且只创建一个vue实例。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="app1">
    <div-span></div-span>
    <div-span></div-span>
    <div-span></div-span>
</div>
<div id="app2">
    <div-span></div-span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app1 = new Vue({
        el: '#app1',
        components:{
             //局部组件,只能在app1中使用
             "div-span": {
                 template:`<div>
                  <span>111</span>
                  <span>222</span>
                  <span>333</span>
                </div>`
             }
        }
    })
    const app2 = new Vue({
        el: '#app2'
    })
</script>
</body>
</html>

组件模板分离的写法

上面注册组件的时候要在js中编写很多html标签,写的痛苦,看的也难受,此时可以单独把组件抽出来放到html中编写,在html里面添加template标签,将组件中的标签全部放到这个template下面。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="app">
    <div-span></div-span>
    <div-span></div-span>
    <div-span></div-span>
</div>
<!--模板-->
<template id="div-span">
    <div>
        <span>111</span>
        <span>222</span>
        <span>333</span>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app1 = new Vue({
        el: '#app',
        components:{
             //局部组件,只能在app1中使用
             "div-span": {
                 template:"#div-span"
             }
        }
    })
</script>
</body>
</html>

组件中的data数据

组件是一个单独封装的功能模块,有自己保存数据的地方,组件中也可以定义方法。组件是不能直接访问Vue实例中的数据,试想下,如果组件中的数据全部放到Vue实例中,就会导致Vue实例非常臃肿了。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="app">
    <div-span></div-span>
</div>
<!--模板-->
<template id="div-span">
    <div>
        <span>{{name}}</span>
        <span>{{job}}</span>
        <!--组件不能直接访问Vue实例中的数据,这里访问的是组件自己的数据-->
        <span>{{address}}</span>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    const app1 = new Vue({
        el: '#app',
        data:{
          address:"北京"
        },
        components:{
             //局部组件
             "div-span": {
                 template:"#div-span",
                 //组件中的数据,注意这里是data()函数
                 data(){
                     return{
                         name:"paul",
                         job:"软件工程师",
                         address:"上海"
                     }
                 }
             }
        }
    })
</script>
</body>
</html>

注意上面组件中存放数据的地方是一个data()函数,并不是data属性,为什么这里是函数呢?因为属性是可以被共享的,多个组件来操作一个属性肯定会有问题,组件每次调用data()函数的时候都会获取一个新的对象,这样就解决了多个组件操作一个属性的问题。下面示例中当点击+或-的时候两个组件中的值都会发生变化,这显然不是我们想要的效果。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="app">
    <div-span></div-span>
    <div-span></div-span>
</div>
<!--模板-->
<template id="div-span">
    <div>
        <span>{{num}}</span>
       <button @click="add">+</button>
       <button @click="minus">-</button>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    //让所有组件共享该num数据
    let num = {
        num:0
    }
    const app1 = new Vue({
        el: '#app',
        data:{
          address:"北京"
        },
        components:{
             //局部组件
             "div-span": {
                 template:"#div-span",
                 //组件中的数据,注意这里是data()方法
                 data(){
                     return num
                 },
                 methods:{
                     add(){
                         this.num++;
                     },
                     minus(){
                         this.num--;
                     }

                 }

             }
        }
    })
</script>
</body>
</html>

正确的做法:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

<div id="app">
    <div-span></div-span>
    <div-span></div-span>
</div>
<!--模板-->
<template id="div-span">
    <div>
        <span>{{num}}</span>
       <button @click="add">+</button>
       <button @click="minus">-</button>
    </div>
</template>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>

    const app1 = new Vue({
        el: '#app',
        data:{
          address:"北京"
        },
        components:{
             //局部组件
             "div-span": {
                 template:"#div-span",
                 //组件中的数据,注意这里是data()方法
                 data(){
                     return {
                         num:0
                     }
                 },
                 methods:{
                     add(){
                         this.num++;
                     },
                     minus(){
                         this.num--;
                     }

                 }

             }
        }
    })
</script>
</body>
</html>