[TOC]

非单文件组件:一个文件中包含有 n 个组件
单文件组件:一个文件中只包含有 1 个组件
特点:

  1. 模板编写没有提示
  2. 没有构建过程, 无法将 ES6 转换成 ES5
  3. 不支持组件的 CSS
  4. 真正开发中几乎不用

    2.1 基本使用

    Vue 中使用组件的三大步骤

  5. 定义组件

    1. 使用**Vue.extend(options)**创建,其中optionsnew Vue(options)时传入的**options**几乎一样,但也有点区别
      1. **el**不要写,因为最终所有的组件都要经过一个vm的管理,由vm中的el才决定服务哪个容器
      2. **data**必须写成函数,避免组件被复用时,数据存在引用关系

备注:使用template可以配置组件结构。

  1. 注册组件
    1. 局部注册:**new Vue()**的时候**options**传入**components**选项
    2. 全局注册:**Vue.component('组件名',组件)**
  2. 使用组件
    编写组件标签如 **<school></school>**

    代码演示

    template里的data必须写成函数形式,再由函数返回一个对象。
  • 如果是对象形式,其他地方应用了这个对象,只要有一个地方改变了对象的值,所有地方的值都会改变。
  • 如果是函数形式,无论多少个地方应用,他们各自改变函数里对象的值,其他地方互不影响,保证数据的独立性。用函数返回一个对象,因为其他地方调用这个函数,函数里都是返回一个全新的对象,所有互不影响。

    <!DOCTYPE html>
    <html>
      <head>
          <meta charset="UTF-8" />
          <title>基本使用</title>
          <script type="text/javascript" src="../js/vue.js"></script>
      </head>
      <body>
          <!-- 准备好一个容器-->
          <div id="root">
              <hello></hello>
              <hr>
              <h1>{{msg}}</h1>
              <hr>
              <!-- 第三步:编写组件标签 -->
              <school></school>
              <hr>
              <!-- 第三步:编写组件标签 -->
              <student></student>
          </div>
    
          <div id="root2">
              <hello></hello>
          </div>
      </body>
    
      <script type="text/javascript">
          Vue.config.productionTip = false
    
          //第一步:创建school组件
          const school = Vue.extend({
              template:`
                  <div class="demo">
                      <h2>学校名称:{{schoolName}}</h2>
                      <h2>学校地址:{{address}}</h2>
                      <button @click="showName">点我提示学校名</button>    
                  </div>
              `,
              // el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,
        // 由vm决定服务于哪个容器。
              data(){
                  return {
                      schoolName:'尚硅谷',
                      address:'北京昌平'
                  }
              },
              methods: {
                  showName(){
                      alert(this.schoolName)
                  }
              },
          })
    
          //第一步:创建student组件
          const student = Vue.extend({
              template:`
                  <div>
                      <h2>学生姓名:{{studentName}}</h2>
                      <h2>学生年龄:{{age}}</h2>
                  </div>
              `,
              data(){
                  return {
                      studentName:'张三',
                      age:18
                  }
              }
          })
    
          //第一步:创建hello组件
          const hello = Vue.extend({
              template:`
                  <div>    
                      <h2>你好啊!{{name}}</h2>
                  </div>
              `,
              data(){
                  return {
                      name:'Tom'
                  }
              }
          })
    
          //第二步:全局注册组件
          Vue.component('hello',hello)
    
          //创建vm
          new Vue({
              el:'#root',
              data:{
                  msg:'你好啊!'
              },
              //第二步:注册组件(局部注册)
              components:{
                  school,
                  student
              }
          })
    
          new Vue({
              el:'#root2',
          })
      </script>
    </html>
    

    演示效果

    组件能够复用,互不影响
    image.png

    2.2 注意事项

  1. 关于组件名
    1. 一个单词组成:
      1. 第一种写法(首字母小写):school
      2. 第二种写法(首字母大写):School
    2. 多个单词组成:
      1. 第一种写法(kebab-case命名):my-school
      2. 第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
    3. 备注:
      1. 组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。
      2. 可以使用name配置项指定组件在开发者工具中呈现的名字。
  2. 关于组件标签:
    1. 第一种写法:<school></school>
    2. 第二种写法:<school/>
    3. 备注:不用使用脚手架时,<school/>会导致后续组件不能渲染。
  3. 一个简写方式

    1. const school = Vue.extend(options)可简写为:const school = options

      代码演示

      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8" />
        <title>几个注意点</title>
        <script type="text/javascript" src="../js/vue.js"></script>
      </head>
      <body>
        <!-- 准备好一个容器-->
        <div id="root">
            <h1>{{msg}}</h1>
            <school></school>
        </div>
      </body>
      
      <script type="text/javascript">
        Vue.config.productionTip = false
      
        //定义组件
        const s = Vue.extend({
            name:'atguigu',
            template:`
                <div>
                    <h2>学校名称:{{name}}</h2>    
                    <h2>学校地址:{{address}}</h2>    
                </div>
            `,
            data(){
                return {
                    name:'尚硅谷',
                    address:'北京'
                }
            }
        })
      
        new Vue({
            el:'#root',
            data:{
                msg:'欢迎学习Vue!'
            },
            components:{
                school:s
            }
        })
      </script>
      </html>
      

      2.3 组件的嵌套

      2 非单文件组件 - 图2

      代码演示

      定义一个app组件,用于管理所有组件,这是组件化的规范,便于组件的管理。

      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8" />
        <title>组件的嵌套</title>
        <!-- 引入Vue -->
        <script type="text/javascript" src="../js/vue.js"></script>
      </head>
      <body>
        <!-- 准备好一个容器-->
        <div id="root">
      
        </div>
      </body>
      
      <script type="text/javascript">
        Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
      
        //定义student组件
        const student = Vue.extend({
            name:'student',
            template:`
                <div>
                    <h2>学生姓名:{{name}}</h2>    
                    <h2>学生年龄:{{age}}</h2>    
                </div>
            `,
            data(){
                return {
                    name:'尚硅谷',
                    age:18
                }
            }
        })
      
        //定义school组件
        const school = Vue.extend({
            name:'school',
            template:`
                <div>
                    <h2>学校名称:{{name}}</h2>    
                    <h2>学校地址:{{address}}</h2>    
                    <student></student>
                </div>
            `,
            data(){
                return {
                    name:'尚硅谷',
                    address:'北京'
                }
            },
            //注册组件(局部)
            components:{
                student
            }
        })
      
        //定义hello组件
        const hello = Vue.extend({
            template:`<h1>{{msg}}</h1>`,
            data(){
                return {
                    msg:'欢迎来到尚硅谷学习!'
                }
            }
        })
      
        //定义app组件
        const app = Vue.extend({
            template:`
                <div>    
                    <hello></hello>
                    <school></school>
                </div>
            `,
            components:{
                school,
                hello
            }
        })
      
        //创建vm
        new Vue({
            template:'<app></app>',
            el:'#root',
            //注册组件(局部)
            components:{app}
        })
      </script>
      </html>
      

      2.4 VueComponent

  4. school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。

  5. 我们只需要写<school/><school></school>,Vue解析时会帮我们创建school组件的实例对象,即Vue帮我们执行的:new VueComponent(options)
  6. 特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!
  7. 关于this指向:
    1. 组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。
    2. new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。
  8. VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。

    1. Vue的实例对象,以后简称vm

      代码演示

      ```html <!DOCTYPE html>