Vue学习总结(十二)——组件化

本文详细介绍了Vue的组件化思想及其优势,包括组件的创建、注册(全局与局部)、父组件与子组件的关系,以及组件数据为什么必须是函数。通过实例展示了组件的使用,帮助理解组件的生命周期和数据管理。

1、什么是组件化

(1)组件化的思想:

  • 如果我们将页面中所有的逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
  • 但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。

(2)Vue组件化的思想

        组件化是Vue.js中的重要思想:

  • 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
  • 任何的应用都会被抽象成一颗组件树。 

(3)组件化思想的应用:

  • 有了组件化的思想,我们在之后的开发中就要充分的利用它。
  • 尽可能的将页面拆分成一个个小的、可复用的组件。
  • 这样让我们的代码更加方便组织和管理,并且扩展性也更强。

2、注册组件的基本步骤

(1)组件的使用分成三个步骤:

  • 创建组件构造器。
  • 注册组件(全局注册和局部注册)。
  • 使用组件。

(2)注册组件步骤解析

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件的使用-->
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
    <my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
    // 1.创建组件构造器对象
    const cpnC = Vue.extend({
        template: `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,哈哈哈哈</p>
                <p>我是内容,呵呵呵呵</p>
            </div>
        `
    })
    // 2.注册组件,两个参数,一个是组件的标签名,以什么样的名称使用组件
    Vue.component('my-cpn', cpnC)
    const app = new Vue({
        el: '#app',
        data: {
            names: ['why', 'kobe', 'gay yang', 'baby']
        }
    })
</script>
</body>

可以看到执行结果如下,我们使用4行代码就复用了四次组件:

上面代码中的步骤都代表什么含义呢? 

  

        1) Vue.extend():

  • 调用Vue.extend()创建一个组件构造器。
  • 通常在创建组件构造器时,传入template代表我们自定义组件的模板。
  • 该模板就是在使用到组件的地方,要显示的HTML代码。
  • 事实上,这种写法在Vue2.X的文档中几乎已经看不到了,它会直接使用到下面我们会讲到的语法糖,但是在很多资料中还是会提到这种方式,而且这种方式是学习后面方式的基础。

        2) Vue.component(): 

  • 调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。
  • 所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

        3) 组件必须挂载在某个Vue实例下,否则它不会生效。

3.全局组件和局部组件

(1)全局组件的创建和使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件的使用-->
    <my-cpn></my-cpn>
</div>
<div id="app2">
    <!--组件的使用-->
    <my-cpn></my-cpn>
</div>
<script src="../js/vue.js"></script>
<script>
    // 1.创建组件构造器对象
    const cpnC = Vue.extend({
        template: `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,哈哈哈哈</p>
                <p>我是内容,呵呵呵呵</p>
            </div>
        `
    })
    // 2.注册组件(全局组件,意味着可以在多个Vue的实例下面使用)
    Vue.component('my-cpn', cpnC)
    const app = new Vue({
        el: '#app',
        data: {
            names: ['why', 'kobe', 'gay yang', 'baby']
        }
    })
    const app2 = new Vue({
        el: '#app2'
    })
</script>
</body>

        执行结果如下: 

(2)局部组件的创建和使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件的使用-->
    <cpn></cpn>
</div>
<div id="app2">
    <!--此处组件应该不生效,因为是局部组件-->
    <cpn></cpn>
</div>
<script src="../js/vue.js"></script>
<script>
    // 1.创建组件构造器对象
    const cpnC = Vue.extend({
        template: `
            <div>
                <h2>我是标题</h2>
                <p>我是内容,哈哈哈哈</p>
                <p>我是内容,呵呵呵呵</p>
            </div>
        `
    })
    const app = new Vue({
        el: '#app',
        components:{
            //cpn使用组件时的标签名
            cpn: cpnC
        }
    })
    const app2 = new Vue({
        el: '#app2'
    })
</script>
</body>

        执行结果如下,可以看到在app2的Vue实例中组件是不生效的: 

4.父组件和子组件 

(1)在前面我们看到了组件树:

  • 组件和组件之间存在层级关系。
  • 其中一种非常重要的关系就是父子组件的关系。

(2)父子组件的错误用法:以子标签的形式在Vue实例中使用

  • 因为当子组件注册到父组件的components时,Vue会编译好父组件的模块
  • 该模板的内容已经决定了父组件将要渲染的HTML(相当于父组件中已经有了子组件中的内容了)
  • <cpn1></cpn1>是只能在父组件中被识别的
  • 类似这种用法,<cpn1></cpn1>是会被浏览器忽略的。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件的使用-->
    <cpn2></cpn2>
    <!--这么使用会报错,因为没有在vue组件中注册cpn1组件,组件是有作用域的
    <cpn1></cpn1>
    -->
</div>
<script src="../js/vue.js"></script>
<script>
    // 1.创建第一个组件构造器(子组件)
    const cpnC1 = Vue.extend({
        template: `
            <div>
                <h2>我是标题1</h2>
                <p>我是内容,哈哈哈哈</p>
            </div>
        `
    })
    // 2.创建第二个组件构造器(父组件)
    const cpnC2 = Vue.extend({
    template: `
        <div>
            <h2>我是标题2</h2>
            <p>我是内容,呵呵呵呵</p>
            <cpn1></cpn1>
        </div>
    `,
    // 在父组件里面定义子组件
    components: {
        cpn1: cpnC1
    }
    })
    // root
    const app = new Vue({
        el: '#app',
        components: {
            //cpn1使用组件时的标签名
            cpn2: cpnC2
        }
    })
</script>
</body>

执行结果如下:

 5.注册组件语法糖

使用Vue.extend(),Vue.component()注册组件的方式,可能会有些繁琐。

  • Vue为了简化这个过程,提供了注册的语法糖。
  • 主要是省去了调用Vue.extend()  的步骤,而是直接可以用一个对象来代替。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <!--组件的使用-->
    <my-cpn></my-cpn>
    <cpn2></cpn2>
</div>
<script src="../js/vue.js"></script>
<script>
    // 1.注册组件的语法糖方式--全局组件
    Vue.component('my-cpn', {
        template: `
            <div>
                <h2>我是标题1</h2>
                <p>我是内容,哈哈哈哈</p>
            </div>
        `
    })
    // 2.注册局部组件的语法糖形式 
    const app = new Vue({
        el: '#app',
        components: {
            'cpn2': {
                template: `
                    <div>
                        <h2>我是标题2</h2>
                        <p>我是内容,呵呵呵呵</p>
                    </div>
                `
            }
        }
    })
</script>
</body>

执行结果如下:

6、模板的分离写法

我们可以通过语法糖简化Vue组件的注册过程,另外还有一个地方的写法比较麻烦,就是template模块写法。
如果我们能将其中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。
Vue提供了两种方案来定义HTML模块内容:

  • 使用<script>标签
  • 使用<template>标签
<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <cpn></cpn>
  <cpn2></cpn2>
</div>
<!--1、script标签,注意:类型必须是text/x-template-->
<script type="text/x-template" id="cpn">
  <div>
    <h2>我是标题</h2>
    <h2>我是内容,呵呵呵</h2>
  </div>
</script>
<!--2、template标签-->
<template id="aaaa">
  <div>
    <h2>我是标题</h2>
    <h2>我是内容,哈哈哈</h2>
  </div>
</template>
<script src="../vue.js"></script>
<script>
    Vue.component('cpn', {
      template: '#cpn'
    })

    Vue.component('cpn2', {
      template: '#aaaa'
    })
    const app = new Vue({
      el: '#app',
      data: {
        message: '你好啊'
      }
    })
</script>
</body>

执行结果如下,可以看到两种方式的分离写法使用都是正常的:

7、为什么组件data必须是函数 

(1)组件可以访问Vue实例数据吗?

  • 组件是一个单独功能模块的封装:

        这个模块有属于自己的HTML模板,也应该有属性自己的数据data。

  • 组件中的数据是保存再哪里呢?组件能不能直接访问Vue实例中的data?

        不能访问,即使可以访问,如果所有数据都放在Vue实例中,Vue实例就会变得非常臃肿。

        Vue组件应该有自己保存数据的地方。

(2)组件的数据存放

  • 组件对象也有一个data属性(也可以有methods等属性)。
  • 只是这个data属性必须是一个函数。
  • 而且这个函数返回一个对象,对象内部保存着数据。
<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div id="app">
  <cpn></cpn>
</div>
<!--2、template标签-->
<template id="cpn">
  <div>
    <h2>{{title}}</h2>
    <h2>{{message}}</h2>
  </div>
</template>
<script src="../vue.js"></script>
<script>
    Vue.component('cpn', {
      template: '#cpn',
      // data必须是一个函数
      data() {
        return {
          message: '我是内容,哈哈哈',
          title: '组件中的数据存放'
        }
      }
    })

    const app = new Vue({
      el: '#app',
      data: {
      }
    })
</script>
</body>

(3)为什么组件data必须是一个函数?

        防止多个组件之间操作同一份数据,进行相互影响。每个组件应该维护自己的数据,不和其他组件共同使用同一份数据。

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--1、组件实例-->
<div id="app">
  <cpn></cpn>
  <cpn></cpn>
  <cpn></cpn>
</div>
<!--2、template标签-->
<template id="cpn">
  <div>
    <h2>当前计数: {{counter}}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>
<script src="../vue.js"></script>
<script>
   //1、注册全局组件
    Vue.component('cpn', {
      template: '#cpn',
      // data必须是一个函数,每次调用函数的时候return一个新的对象。
      // 可以有效避免多个组件操作一个对象进行相互影响。
      data() {
        return {
          counter: 0,
          title: '组件中的数据存放'
        }
      },
      methods:{
        increment() {
          this.counter++
        },
        decrement() {
          this.counter--
        }
      }
    })

    const app = new Vue({
      el: '#app',
      data: {
      }
    })
</script>
</body>

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值