目录名称

第二章 Vue的组件化编程

1.模块与组件、模块化与组件化

1.1 模块

  1. 理解: 向外提供特定功能的 js 程序, 一般就是一个 js 文件

  2. 为什么: js 文件很多很复杂

  3. 作用: 复用 js, 简化 js 的编写, 提高 js 运行效率

1.2传统方式编写应用

在这里插入图片描述

1.3.组件化方式

在这里插入图片描述

组件的定义:

  1. 定义: 用来实现局部(特定)功能效果的代码集合(html/css/js/image…..)
  2. 为什么: 一个界面的功能很复杂
  3. 作用: 复用编码, 简化项目编码, 提高运行效率

1.4 组件化与模块化

模块化:当应用中的 js 都以模块来编写的, 那这个应用就是一个模块化的应用。

组件化:当应用中的功能都是多组件的方式来编写的, 那这个应用就是一个组件化的应用,。

2.非单文件组件

2.1 组件的基本使用

Vue中使用组件的三大步骤: 一、定义组件(创建组件) 二、注册组件 三、使用组件(写组件标签)

一、如何定义一个组件? 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的那个options几乎一样,但也有点区别; 区别如下: 1.el不要写,为什么? ——— 最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。 2.data必须写成函数,为什么? ———— 避免组件被复用时,数据存在引用关系。 备注:使用template可以配置组件结构。

二、如何注册组件? 1.局部注册:靠new Vue的时候传入components选项 2.全局注册:靠Vue.component('组件名',组件)

三、编写组件标签:

<!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:'B站',
               address:'中国'
            }
         },
         methods: {
            showName(){
               alert(this.schoolName)
            }
         },
      })

      //第一步:创建student组件
      const student = Vue.extend({
         template:`
            <div>
               <h2>学生姓名:{{studentName}}</h2>
               <h2>学生年龄:{{age}}</h2>
            </div>
         `,
         data(){
            return {
               studentName:'哆啦A梦',
               age:16
            }
         }
      })
      
      //第一步:创建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>

2.2 组件注意事项

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

2.关于组件标签: 第一种写法: 第二种写法: 备注:不用使用脚手架时,会导致后续组件不能渲染。

3.一个简写方式: 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:'bilibili',
         template:`
            <div>
               <h2>学校名称:{{name}}</h2> 
               <h2>学校地址:{{address}}</h2>  
            </div>
         `,
         data(){
            return {
               name:'B站',
               address:'北京'
            }
         }
      })

      new Vue({
         el:'#root',
         data:{
            msg:'欢迎学习Vue!'
         },
         components:{
            school:s
         }
      })
   </script>
</html>

2.3 组件的嵌套

开发中会定义一个 父组件来管理其他子组件

在这里插入图片描述

<!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:'B站',
               age:18
            }
         }
      })
      
      //定义school组件
      const school = Vue.extend({
         name:'school',
         template:`
            <div>
               <h2>学校名称:{{name}}</h2> 
               <h2>学校地址:{{address}}</h2>  
               <student></student>
            </div>
         `,
         data(){
            return {
               name:'B站',
               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

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

2.我们只需要写或,Vue解析时会帮我们创建school组件的实例对象, 即Vue帮我们执行的:new VueComponent(options)。

3.特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!!!!

4.关于this指向: (1).组件配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【VueComponent实例对象】。 (2).new Vue(options)配置中: data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是【Vue实例对象】。

5.VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)。 Vue的实例对象,以后简称vm。

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <title>VueComponent</title>
      <script type="text/javascript" src="../js/vue.js"></script>
   </head>
   <body>
      <!-- 准备好一个容器-->
      <div id="root">
         <school></school>
         <hello></hello>
      </div>
   </body>

   <script type="text/javascript">
      Vue.config.productionTip = false
      
      //定义school组件
      const school = Vue.extend({
         name:'school',
         template:`
            <div>
               <h2>学校名称:{{name}}</h2> 
               <h2>学校地址:{{address}}</h2>  
               <button @click="showName">点我提示学校名</button>
            </div>
         `,
         data(){
            return {
               name:'B站',
               address:'北京'
            }
         },
         methods: {
            showName(){
               console.log('showName',this)
            }
         },
      })

      const test = Vue.extend({
         template:`<span>atguigu</span>`
      })

      //定义hello组件
      const hello = Vue.extend({
         template:`
            <div>
               <h2>{{msg}}</h2>
               <test></test>  
            </div>
         `,
         data(){
            return {
               msg:'你好啊!'
            }
         },
         components:{test}
      })


      // console.log('@',school)
      // console.log('#',hello)

      //创建vm
      const vm = new Vue({
         el:'#root',
         components:{school,hello}
      })
   </script>
</html>

2.5 一个重要的内置关系

在这里插入图片描述

​ 1.一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype ​ 2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。

<!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">
         <school></school>
      </div>
   </body>

   <script type="text/javascript">
      Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
      Vue.prototype.x = 99

      //定义school组件
      const school = Vue.extend({
         name:'school',
         template:`
            <div>
               <h2>学校名称:{{name}}</h2> 
               <h2>学校地址:{{address}}</h2>  
               <button @click="showX">点我输出x</button>
            </div>
         `,
         data(){
            return {
               name:'B站',
               address:'北京'
            }
         },
         methods: {
            showX(){
               console.log(this.x)
            }
         },
      })

      //创建一个vm
      const vm = new Vue({
         el:'#root',
         data:{
            msg:'你好'
         },
         components:{school}
      })

      
      //定义一个构造函数
      /* function Demo(){
         this.a = 1
         this.b = 2
      }
      //创建一个Demo的实例对象
      const d = new Demo()

      console.log(Demo.prototype) //显示原型属性

      console.log(d.__proto__) //隐式原型属性

      console.log(Demo.prototype === d.__proto__)

      //程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
      Demo.prototype.x = 99

      console.log('@',d) */

   </script>
</html>

3.单文件组件

3.1 es6暴露方式

  1. 默认暴露

    导出:

    export default 对象

    导入:

    import 对象名 from 文件名

  2. 多行暴露

    导出:

    export default 对象1

    export default 对象2

    导入:

    import {对象1,对象2} from 文件名

  3. 统一暴露

    导出:

    export {对象1, 对象2}

    导入:

    import {对象1,对象2} from 文件名

3.2 单文件组件化实例

1.定义School子组件

<template>
  <div class="demo">
    <h1>学校名称:{{schoolName}}</h1>
    <h1>学校地址:{{schoolAddress}}</h1>
    <button @click="showName"> 点我显示学校名称</button>
  </div>
</template>
<script>
export default{
  name:"School",
  data(){
    return {
      schoolName:"B站",
      schoolAddress:"中国"
    }
  },
  methods:{
    showName(){
      alert(this.schoolName);
    }
  }
};
</script>
<style>
.demo{
  background-color: antiquewhite;
}
</style>

2.定义Student子组件

<template>
  <div class="demo">
    <h1>学校名称:{{studentName}}</h1>
    <h1>学生年龄:{{studentAge}}</h1>
    <button @click="showName"> 点我显示学生姓名</button>
  </div>
</template>
<script>
export default{
  name:"Student",
  data(){
    return {
      StudentName:"B站",
      StudentAge:18
    }
  },
  methods:{
    showName(){
      alert(this.studentName);
    }
  }
};
</script>
<style>
.demo{
  background-color: antiquewhite;
}
</style>
  1. 定义父组件App

    <template>
      <!--模板-->
    <div>
      <School></School>
      <Student></Student>
    </div>
    </template>
    <script>
    //引入组件
    import School from './School';
    import  Student from './Student'
    export default Vue.extend({
      name:"App",
      components:{
        School,
        Student
      }
    })
    </script>
    <style>
    /*样式*/
    </style>
    

    4.创建Vue实例对象

    import App from './App'
    new Vue({
        components:{
            App
        }
    });
    

    5.定义容器

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div id="root">
    <app></app>
    </div>
    <script type="text/javascript" src="../js/vue.js"></script>
    <script type="text/javascript" src="main.js"></script>
    </body>
    </html>