Vue_2 --- 组件化编程
1. 模块与组件
1.1 模块化编写应用
向外提供特定功能的js程序,一般就是一个js文件,也就是一个模块

存在的问题
- 依赖关系混乱,不好维护
 - 代码复用率不高
 
1.2 组件化编写引用
组件 --- 实现应用中局部功能代码和资源的集合


优点
- 好维护
 - 代码复用率高
 
2. 非单文件组件
一个文件中包含多个组件
1. 创建组件(局部注册)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>{{msg}}</h1>
    <!-- 4. 使用 school 组件 -->
    <School></School>
    <hr>
    <!-- 4. 使用 student 组件,两个单词组成的需要用 - 连接 -->
    <student-msg></student-msg>
    <!-- 可以用自闭合标签,但是要再vue脚手架中使用 -->
    <student-msg/>
</div>
</body>
<script>
    Vue.config.productionTip = false
    // 1. 创建组件
    // 创建 school 组件,组件名首字母大写
    const School = Vue.extend({
        // el:"#root",  // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
        // 定义组件内的模板
        name:"School",  // 可以定义组件在开发者工具中的名字
        template: `
          <div>
            <h1>学校名称: {{ schoolName }}</h1>
            <h1>学校地址: {{ address }}</h1>
          </div>
        `,
        data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
            return {
                schoolName: "实验中学",
                address: "北京",
            }
        }
    })
    // 创建 student 组件,组件名首字母大写
    const StudentMsg = Vue.extend({
        // el:"#root",  // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
        // 定义组件内的模板
        template: `
          <div>
            <h1>学生名称: {{ studentName }}</h1>
            <h1>学生年龄: {{ age }}</h1>
          </div>
        `,
        data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
            return {
                studentName: "张三",
                age: 18
            }
        }
    })
    // 2. 创建Vue对象
    new Vue({
        el: '#app',
        data: {
            msg: "Vue实例"
        },
        // 3. 注册组件(局部注册)
        components: {
            School,
            StudentMsg
        }
    })
</script>
</html>
定义组件的简写方式
<script>
    // 内部会有判断,如果是对象,会自动调用 Vue.extend()
	const StudentMsg = {
        // el:"#root",  // 组件定义时,一定不要写el配置项,因为最终所有的组件爱你都要被vm管理,由vm决定服务于哪个容器节点
        // 定义组件内的模板
        template: `
          <div>
            <h1>学生名称: {{ studentName }}</h1>
            <h1>学生年龄: {{ age }}</h1>
          </div>
        `,
        data() { // 组件中的data定义为函数形式,是为了不会当其中一个组件修改了data中的数据从而影响其他组件中的数据,因为data()返回的都是一个新的对象
            return {
                studentName: "张三",
                age: 18
            }
        }
    }
</script>
2. 创建组件(全局注册)
<script>
    Vue.config.productionTip = false
    
    // 创建 School组件
     const School = Vue.extend({
        template: `
          <div>
            <h1>学校名称: {{ schoolName }}</h1>
            <h1>学校地址: {{ address }}</h1>
          </div>
        `,
        data() { 
            return {
                schoolName: "实验中学",
                address: "北京",
            }
        }
    })
    
    // 注册组件(全局注册)
	Vue.component("School",school)
    
    new Vue({
        el: '#app',
    })
</script>
3. 组件嵌套
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>{{msg}}</h1>
    <!-- 4. 使用 school 组件 -->
    <School></School>
    <hr>
    <!-- 4. 使用 student 组件 -->
</div>
</body>
<script>
    Vue.config.productionTip = false
    // 1. 创建组件
    // 创建 student 组件
    const StudentMsg = Vue.extend({
        template: `
          <div>
            <h1>学生名称: {{ studentName }}</h1>
            <h1>学生年龄: {{ age }}</h1>
          </div>
        `,
        data() {
            return {
                studentName: "张三",
                age: 18
            }
        }
    })
    // 创建 school 组件,并在其中嵌套 student 组件
    const School = Vue.extend({
        template: `
          <div>
            <h1>学校名称: {{ schoolName }}</h1>
            <h1>学校地址: {{ address }}</h1>
            <student-msg></student-msg>   <!-- school 组件中 写 student 组件的标签 -->
          </div>
        `,
        data() {
            return {
                schoolName: "实验中学",
                address: "北京",
            }
        },
        // 在 school 组件中注册 student 组件
        components: {
            StudentMsg
        }
    })
    // 2. 创建Vue对象
    new Vue({
        el: '#app',
        // 3. 注册组件(局部注册)
        components: {
            School,
        }
    })
</script>
</html>
4. 组件标准化开发
以后标准化开发过程中,会由 vm 只管理 一个 app 这个顶层组件, app中再管理着多个子组件和子嵌套组件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
</head>
<body>
<!-- 空容器,由vm将app组件放到容器 -->
<div id="app">
</div>
</body>
<script>
    Vue.config.productionTip = false
    // 1. 创建组件
    // 创建 student 组件
    const StudentMsg = Vue.extend({
        template: `
          <div>
            <h1>学生名称: {{ studentName }}</h1>
            <h1>学生年龄: {{ age }}</h1>
          </div>
        `,
        data() {
            return {
                studentName: "张三",
                age: 18
            }
        }
    })
    // 创建 school 组件,并在其中嵌套 student 组件
    const School = Vue.extend({
        template: `
          <div>
            <h1>学校名称: {{ schoolName }}</h1>
            <h1>学校地址: {{ address }}</h1>
            <student-msg></student-msg>   <!-- school 组件中 写 student 组件的标签 -->
          </div>
        `,
        data() {
            return {
                schoolName: "实验中学",
                address: "北京",
            }
        },
        // 在 school 组件中注册 student 组件
        components: {
            StudentMsg
        }
    })
    // 创建app组件
    const app = Vue.extend({
        template: `<school></school>`,
        components: {
            School,
        }
    })
    // 2. 创建Vue对象
    new Vue({
        el: '#app',
        template: `<app></app>`,
        // 3. 注册 app 组件(局部注册)
        components: {
            app,
        }
    })
</script>
</html>
5. VueComponent --- 组件实例对象
- 组件的本质是一个名为
VueComponent的构造函数,且不是程序员定义的,是Vue.extend()生成的 - 我们只需要写
<school/>或<school></school>,Vue解析模板时会帮我们创建组件的实例对象,即Vue执行的:new VueComponent(options) - 特别注意: 每次调用
Vue.extend(),返回的都是一个全新的VueComponent实例对象 - 关于this指向:
- 组件的
{}对象配置中:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this均是VueComponent 实例对象 new Vue(options)中的options配置中的:data函数,methods中的函数,watch中的函数,computed中的函数,他们的this均是Vue 实例对象
 - 组件的
 VueComponent的实例对象,简称vc,Vue的实例对象,简称vm,vc 和vm 的功能差不多,也有数据监视和数据代理,vm实例中的$children是个数组,存储着一个一个的vc,每个vc的$children也是个数组,存储着一个一个的嵌套组件vc,但是vc不能写el配置项,data必须写成函数形式return一个对象
6. 内置关系
1. 原型对象的概述(类继承)
// 定义一个构造函数
function Demo(){
    this.a = 1
    this.b = 2
}
// 创建一个实例
const d = new Demo()
console.log(Demo.prototype)    // 显式原型属性
console.log(d.__proto__)      // 隐式原型属性
// 它们两个所指向的都是同一个对象: 原型对象
// 程序员通过显式原型属性操作原型对象,设置一个属性x,值是99
Demo.prototype.x = 99
// 调用d.x时,d身上没有x这个属性,自动顺着隐式原型属性找原型对象身上有没有x属性
console.log(d.x)   // 其本质是 d.__proto__.x  通过隐式原型属性调用x,可以省略
2. 对象的指向关系

3. 结论
- 内置关系: 
VueComponent.prototype.__proto__ === Vue.prototype - 为什么要有这个关系: 让组件实例对象(vc)可以访问到Vue原型上的属性、方法
 
3. 单文件组件(常用)
一个文件中只包含一个组件,以.vue结尾的文件
1. 文件结构
<template>  <!-- template 标签是不参与编译的,即最终呈现在浏览器中的结构不会出现template这个标签 -->
  <!-- 组件的标签结构 -->
</template>
<script>
// 组件交互相关的代码(数据,方法)
</script>
<style>
/* 组件的样式 */
</style>
2. 对外暴露方式
1. 分别暴露
<template>
  <div class="demo">
    <h1>学校名称: {{ name }}</h1>
    <h1>学校地址: {{ address }}</h1>
  </div>
</template>
<script>
// 对外暴露组件的方式一: 分别暴露
export const school = {
  name: "School",  
  data() {
    return {
      name: "实验中学",
      address: "北京",
    }
  }
}
</script>
<style>
.demo {
}
</style>
外部的引用方式
import {school} from "文件路径"
2. 统一暴露
<template>
  <div class="demo">
    <h1>学校名称: {{ name }}</h1>
    <h1>学校地址: {{ address }}</h1>
  </div>
</template>
<script>
const school = {
  name: "School",
  data() {
    return {
      name: "实验中学",
      address: "北京",
    }
  }
}
// 对外暴露组件的方式一: 统一暴露
export {school}
</script>
<style>
.demo {
}
</style>
外部的引用方式
import {school} from "文件路径"
3. 默认暴露(常用)
<template>
  <div class="demo">
    <h1>学校名称: {{ name }}</h1>
    <h1>学校地址: {{ address }}</h1>
  </div>
</template>
<script>
export default {
  name: "School",
  data() {
    return {
      name: "实验中学",
      address: "北京",
    }
  }
}
// 对外暴露组件的方式三: 默认暴露
</script>
<style>
/* 组件的样式 */
.demo {
}
</style>
外部的引用方式
import school from "文件路径"
3. 目录结构
1. School 组件
<template>
  <div class="demo">
    <h1>学校名称: {{ name }}</h1>
    <h1>学校地址: {{ address }}</h1>
  </div>
</template>
<script>
export default {
  name: "School",
  data() {
    return {
      name: "实验中学",
      address: "北京",
    }
  }
}
// 对外暴露组件的方式三: 默认暴露
</script>
<style>
/* 组件的样式 */
.demo {
}
</style>
2. App.vue
<template>
  <!-- 2. 使用组件 -->
  <div>
    <School/>
  </div>
</template>
<script>
// 1. 引入组件
import School from "./School.vue";
export default {
  name: "App",
  components: {School},
  data() {
    return {}
  }
}
</script>
<style>
</style>
3. main.js
import App from "./App.vue";
new Vue({
    el: "#root",
    template: `<App/>`,   // 将 App 组件放入root 的模板中
    components: {App}
})
4. index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单文件组件</title>
</head>
<body>
<!-- 1. 创建容器 -->
<div id="root"></div>
<!-- 2. 引入 vue.js -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.js"></script>
<!-- 3. 引入 main.js  -->
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
    python防脱发技巧

                
            
        
浙公网安备 33010602011771号