Vue基础知识之组件机制(非单文件组件、动态组件、缓存组件keep-alive、单文件组件)(五)

系列文章目录

第一章:Vue基础知识笔记(模板语法、数据绑定、事件处理、计算属性)(一)
第二章:Vue基础知识(计算属性、监视属性、computed和watch之间的区别、绑定样式)(二)
第三章:Vue基础知识(条件渲染、列表渲染、收集表单数据、过滤器)(三)
第四章:Vue基础知识(内置指令、自定义指令、Vue生命周期)(四)
第六章:Vue创建脚手架(六)
第七章:Vue使用脚手架(ref、props、mixin、插件、scoped)(七)
第八章:Vue组件通信(组件的自定义事件、全局事件总线、消息订阅与发布、插槽、props)(八)
第九章:Vue使用脚手架(nextTick、Vue封装的过度与动画、vue脚手架配置代理)(九)
第十章:Vuex(十)
第十一章:vue-router(基本使用、路由重定向、多级路由、路由命名、路由的query和params参数、路由的props配置)(十一)
第十二章:vue-router(路由的两种工作模式、router-link的replace属性、编程式路由导航、缓存路由组件keep-alive、路由守卫【全局路由守卫、独享路由守卫、组件内路由守卫】)(十二)
第十三章:Vue组件通信二&数据同步(v-model、属性修饰符.sync、 a t t r s 与 attrs与 attrslisteners、refs. c h i l d r e n 与 r e f s . children与refs. childrenrefs.parent、provide与inject )(十三)


一、使用组件的步骤

1、定义组件(创建组件)
2、注册组件
3、使用组件(写组件标签)

1、如何定义一个组件

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

2、如何注册组件

  • 局部注册: 靠new Vue的时候传入components选项
  • 全局注册:Vue.component('组件名',组件)

3、如何使用组件

编写组件标签:<school></school>
注:以下创建的为非单文件组件

综合案例:

<body>
	<div id="root">
        <h1>{{msg}}</h1>
        <hr>
        <!--第三步:编写组件标签-->
        <hello></hello>
        <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',
    })

运行结果:
在这里插入图片描述

二、关于组件使用的几个注意点

1.关于组件名

  • 一个单词组成:
    第一种写法(首字母小写):school
    第二种写法(首字母大写):School

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

2.关于组件标签

第一种写法:<school></school>
第二种写法:<school/>
备注: 不用使用脚手架时,<school/>会导致后续组件不能渲染。

3.一个简写方式

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

三、组件模板分离写法

我们在注册组件的时候,我们能将其中的template模板中的HTML分离出来写,然后挂载到对应的组件上,必然结构会变得非常清晰。

<body>
  <div id="app">
  //使用组件
    <cpn></cpn>
  </div>

  <!-- 使用模板分离来创建组件的模板 -->
  <template id="cpn">
    <div>
      <h2>我是组件的标题</h2>
      <p>我是组件的内容</p>
      <h2>{{message2}}</h2>
    </div>![在这里插入图片描述](https://img-blog.csdnimg.cn/df4cedf408aa4b5f975632ba748f26af.png)

  </template>

  <script src="./js/vue.js"></script>
  <script>
    let app = new Vue({
      el: '#app',
      data: {
        
      },
      components:{
        // 注册一个局部组件
        cpn: {
          template: '#cpn',
           data() {
            // return 返回的对象 值一样 内存地址不一样
            return {
              message2: '我是组件自己的message'
            }
          },
          methods: {
            
          },
        }
      }
  })
  </script>
</body>

运行结果:
在这里插入图片描述

四、组件的嵌套

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

案例:

<body>
    <!-- 准备好一个容器-->
    <div id="root">
        <app></app>
    </div>

    <!-- 学生组件模板 -->
    <template id="student">
        <div>
            <h2>学生姓名:{{name}}</h2>	
            <h2>学生年龄:{{age}}</h2>	
        </div>
    </template>

    <!-- 学校组件模板 -->
    <template id="school">
        <div>
            <h2>学校名称:{{name}}</h2>	
            <h2>学校地址:{{address}}</h2>	
            <student></student>
        </div>
    </template>

    <!-- app组件模板 -->
    <template id="app">
        <div>	
            <school></school>
        </div>
    </template>
</body>


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

    //定义student组件
    const student = Vue.extend({
        name: 'student',
        template: "#student",
        data() {
            return {
                name: 'zs',
                age: 18
            }
        }
    })

    //定义school组件
    const school = Vue.extend({
        name: 'school',
        template: "#school",
        data() {
            return {
                name: '你猜',
                address: '你猜'
            }
        },
        //注册组件(局部)
        components: {
            student
        }
    })

    //定义app组件
    const app = Vue.extend({
        template: "#app",
        components: {
            school,
        }
    })

    //创建vm
    new Vue({
        el: '#root',
        //注册组件(局部)
        components: {
            app
        }
    })
</script>

运行结果
在这里插入图片描述

五、动态组件

可以使用<component :is="组件名"></>动态加载组件,但是每次切换组件都会销毁组件。
案例:

<body>
    <div id="app">
        <button @click="current=myA">个人</button>
        <button @click="current=myB">企业</button>
        
        <!-- 动态组件 is动态加载组件-->
        <component :is="current"></component>

    </div>
    <script>
        let myA = Vue.extend({
            name: 'myA',
            template: `
				<div>
					个人组件得内容
				</div>
			`,
            created() {
                console.log('实例A初始化完成');
            },
            destroyed() {
                console.log('实例A销毁完成');
            },

        });
        let myB = Vue.extend({
            name: 'myB',
            template: `
				<div>企业组件得内容</div>
			`,
            created() {
                console.log('实例B初始化完成');
            }
        });

        new Vue({
            components: {
                'my-a': myA,
                'my-b': myB
            },
            el: "#app",
            data: {
                current: myA
            },

        })
    </script>
</body>

运行结果:
在这里插入图片描述
当组件在切换的时候都会重新创建组件,但是有些时候我们希望组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 元素将其动态组件包裹起来。

六、缓存组件keep-alive

keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件链中。

  1. 作用: 缓存组件,很多时候我们不希望切换得组件得时候重新创建和销毁组件,可以使用keep-alive将第一次创建组件得时候缓存起来

  2. 新增生命周期:
    activated()–进入激活组件
    deactivated()–离开停用
    errorCaptured()–子组件/后代组件发生错误捕获错误
    初次进入时: created > mounted > activated;退出后触发 deactivated
    再次进入时: 直接触发activated

代码案例:

<body>
    <div id="app">
        <button @click="current=myA">个人</button>
        <button @click="current=myB">企业</button>

        <!-- 想要当前组件缓存起来 可以使用keep-alive包裹component -->
        <!-- <keep-alive>
            <component :is="current"></component>
        </keep-alive> -->
    </div>
    <script>
        let aChild = Vue.extend({
            name: 'aChild',
            template: `
				<div>
					A组件得子组件
					{{subMsg}}
				</div>
			`
        });

        let myA = Vue.extend({
            name: 'myA',
            template: `
				<div>
					个人组件得内容
					 <a-child></a-child>
				</div>
			`,
            components: {
                'a-child': aChild
            },
            created() {
                console.log('实例A初始化完成');
            },
            mounted() {
                console.log('实例挂载到页面完成')
            },
            // 激活组件 进入组件就会触发生命周期
            activated() {
                alert('进入A组件了');
            },
            // 捕获子组件/后代组件发生错误得生命周期
            errorCaptured() {
                console.log('子组件发生错误了');
            },
            // 离开当前组件触发 停用组件
            deactivated() {
                console.log('离开A组件了');
            },
            destroyed() {
                console.log('实例A销毁完成');
            },

        });
        let myB = Vue.extend({
            name: 'myB',
            template: `
				<div>企业组件得内容</div>
			`,
            created() {
                console.log('实例B初始化完成');
            }
        });

        new Vue({
            components: {
                'my-a': myA,
                'my-b': myB
            },
            el: "#app",
            data: {
                current: myA

            },

        })
    </script>
</body>

运行结果:
在这里插入图片描述

六、关于VueComponent

1.school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的。
2.我们只需要写<school/><school></school>,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。

七、一个重要的内置关系

1.一个重要的内置关系: VueComponent.prototype.__proto__ === Vue.prototype
2.为什么要有这个关系:组件实例对象(vc)可以访问到 Vue原型上的属性、方法
在这里插入图片描述

八、单文件组件

使用单文件组件非常的不利于,后期项目的管理以及代码可读性差,为了方便后期的管理,提高代码可读性,我们可以将每个组件封装到一个vue文件中。
注:单文件组件,需要在脚手架的环境下才能运行。

组件模板:

//1. 模板页面 
<template> 
页面模板 
</template>

//2. JS 模块对象 
<script> 
export default { 
data() {return {}}, 
methods: {},  
components: {} 
}
</script> 

//3. 样式
<style> 
样式定义 
</style>

使用模板:

<template>
	<div>
		//使用组件标签
		<School></School>
	</div>
</template>

<script>
	//引入组件
	import School from './School.vue'

	export default {
		name:'App',
		//注册组件
		components:{
			School
		}
	}
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值