zoukankan      html  css  js  c++  java
  • vue第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定)

    第十单元(动态组件 keep-alive(钩子函数) 递归组件(name) 组件命名约定)

    #课程目标

    1. 熟练掌握动态组件的实现
    2. 掌握keep-alive缓存组件,以及相应的钩子函数
    3. 熟练掌握递归组件,以及递归组件的实现原理
    4. 了解组件的命名约定

    #知识点

    #1.动态组件

    ​ 首先得明白什么叫做动态组件,让多个组件使用同一个挂载点,并动态切换,这就是动态组件。

    #1.1<component>元素

    在vue中,可以通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动态组件

    <template>
      <div>
      	<button @click="change">切换页面</button>
    	<!--保留component元素  使用is显示相应的组件 实现动态组件-->
      	<component :is="currentView"></component>
      </div>
    </template>
    <script>
    import Aa from '@/components/Aa'
    import Bb from '@/components/Bb'
    export default {
      name: 'Index',
      data () {
        return {
        	index:0,
            //将组件放进数组中
        	arr:[Aa,Bb],
        }
      },
      methods:{
      	change(){
          //改变index的值,在0和1中来回切换
          this.index = (++this.index)%2;
        }
      },
      computed:{
        //返回当前显示的数组
        currentView(){
            return this.arr[this.index];
        }
      }
    }
    </script>
    
     
    #1.2动态组件的缓存(<keep-alive>  )

    <keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中

    基础用法

    <template>
      <div>
      	<button @click="change">切换页面</button>
    	<!--keep-alive的使用方式,直接包在组件外面即可,里面的组件即可实现组件缓存-->
    	<keep-alive>
        	<!--保留component元素  使用is显示相应的组件 实现动态组件-->
      		<component :is="currentView"></component>
    	</keep-alive>
      </div>
    </template>
    <script>
    import Aa from '@/components/Aa'
    import Bb from '@/components/Bb'
    export default {
      name: 'Index',
      data () {
        return {
        	index:0,
            //将组件放进数组中
        	arr:[Aa,Bb],
        }
      },
      methods:{
      	change(){
          //改变index的值,在0和1中来回切换
          this.index = (++this.index)%2;
        }
      },
      computed:{
        //返回当前显示的数组
        currentView(){
            return this.arr[this.index];
        }
      }
    }
    </script>
    
     

    注意:既然是缓存,那么重新切换组件时,组件中相应的vue的生命周期函数,将不会再被触发(如:beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed)

    keep-alive元素中最后渲染的结果是,要求同时只有一个子元素被渲染(只能有一个根组件,和template元素类似),所以,我们也可以在keep-alive元素中写v-if判断组件的显示和隐藏:

    <template>
      <div>
      	<button @click="change">切换页面</button>
    	<!--keep-alive的使用方式,直接包在组件外面即可,里面的组件即可实现组件缓存-->
    	<keep-alive>
        	<Aa v-if="index==0"></Aa>
    		<Bb v-if="index==1"></Bb>
    	</keep-alive>
      </div>
    </template>
    <script>
    import Aa from '@/components/Aa'
    import Bb from '@/components/Bb'
    export default {
      name: 'Index',
      data () {
        return {
        	index:0,
            //将组件放进数组中
        	arr:[Aa,Bb],
        }
      },
      methods:{
      	change(){
          //改变index的值,在0和1中来回切换
          this.index = (++this.index)%2;
        }
      },
       components:{
    	Aa,Bb
       }
      }
    }
    </script>
    
     
    #1.3 缓存组件中的钩子函数activated 和 deactivated

    activated 和 deactivated 在 <keep-alive> 树内的所有嵌套组件中触发

    activated===>这个函数是在组件被切换显示的时候,触发该函数

    deactivated===>这个函数是在组件被切换隐藏的时候,触发该函数

    //Aa.vue组件  当这个组件显示或者隐藏时  会触发activated或者deactivated
    <template>
      <div>
      	{{msg}}
      </div>
    </template>
    
    <script>
    export default {
      name: 'Aa',
      data () {
        return {
        	msg:'我是Aa'
        }
      },
      //显示时触发该函数
      activated(){
      	console.log('a来了')
      },
      //隐藏时触发该函数
      deactivated(){
      	console.log('a走了')
      }
    }
    </script>
    
     
    #1.4组件有条件地缓存 includeexclude
    • include和 exclude属性允许组件有条件地缓存,见语义化命名,就知道前者是包含,后者则是排除。
    • 二者都可以用逗号分隔字符串、正则表达式或一个数组来表示 。
    • 匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称(父组件 components 选项的键值)。
    • 匿名组件不能被匹配。
    <!-- 逗号分隔字符串 -->
    <keep-alive include="Aa">
        <Aa v-if="index==0"></Aa>
    	<Bb v-if="index==1"></Bb>
    </keep-alive>
    
    <!-- 正则表达式 (使用 v-bind) -->
    <keep-alive :include="/Aa|Bb/">
        <Aa v-if="index==0"></Aa>
    	<Bb v-if="index==1"></Bb>
    </keep-alive>
    
    <!-- 数组 (使用 v-bind)  -->
    <keep-alive :include="['Aa', 'Bb']">
        <Aa v-if="index==0"></Aa>
    	<Bb v-if="index==1"></Bb>
    </keep-alive>
    
     

    #2.递归组件

    ​ 对于一些有规律的 dom 结构,我们可以通过递归方式来生成这个结构,那么在vue的模板中,我们能不能递归生成dom,答案是肯定的,在vue的组件中能够调用自己本身,不过它们只能通过 name 选项来做这件事。

    首先为了使用递归组件需要准备一份数据,既然要用递归组件,那么对我们的数据格式肯定是需要满足递归的条件的,就像下边这样,这是一个树状的递归数据。

      data () {
        return {
          list: [
            {
              name: '苹果',
              cList: [
                { name: '二级苹果1' },
                {
                  name: '二级苹果2',
                  cList: [
                    { name: '三级苹果1', cList: [{ name: '四级苹果1' }] }
                  ]
                }
              ]
            },
            { name: '香蕉' },
            {
              name: '西瓜',
              cList: [{ name: '二级西瓜1' }, { name: '二级西瓜2' }]
            }
          ]
        }
      }
    
     

    接下来,我们就用这个树状数据,做一个简单版的树状菜单。树状菜单,也是递归组件最常用的方法之一。

    首先,我们先创建一个tree组件,这个组件作为使用递归组件的父组件,我们来看下具体写法

    <template>
      <div>
        <my-trees :list="list"></my-trees>
      </div>
    </template>
    <script>
    import myTrees from './treeMenus'
    export default {
    	name:"Tree",
      components: {
        myTrees
      },
      data () {
        return {
          list: [
            {
              name: '苹果',
              cList: [
                { name: '二级苹果1' },
                {
                  name: '二级苹果2',
                  cList: [
                    { name: '三级苹果1', cList: [{ name: '四级苹果1' }] }
                  ]
                }
              ]
            },
            { name: '香蕉' },
            {
              name: '西瓜',
              cList: [{ name: '二级西瓜1' }, { name: '二级西瓜2' }]
            }
          ]
        }
      },
      methods: {}
      
    }
    </script>
    
     

    <my-trees />就是我们说的递归组件,当使用它时,只需要把上边我们定义好的数据通过props的方式传进去即可。

    接下来,递归组件接收到了父组件传递的数据,就可以进行递归啦,我们来看下边treeMenus.vue中的实现:

    <template>
      <ul>
        <li v-for="(item,index) in list " :key="index">
          <p>{{item.name}}</p>
          <tree-menus :list="item.cList"></tree-menus>
        </li>
      </ul>
    </template>
     <style>
       ul{
        padding-left: 20px!important;
       }
     </style>
    <script>
    	export default{
    		name:'treeMenus',
    		props:{
    			list: Array
    		}
    	}
    </script>
    
     

    注意一开始所说,name属性的使用,你可以把它当作从import导入了一个组件并注册,我们在temlpate可以使用<tree-menus></tree-menus>使用子组件自身进行递归了。

    #3.组件命名约定

    当注册组件(或者 props)时,可以使用 kebab-case ,camelCase ,或 TitleCase 。

    // 在组件定义中
    components: {
      // 使用 camelCase 形式注册
      'kebab-cased-component': { /* ... */ },
      'camelCasedComponent': { /* ... */ },
      'TitleCasedComponent': { /* ... */ }
    }
    
     

    在 HTML 模版中,请使用 kebab-case 形式:

    <!-- 在HTML模版中始终使用 kebab-case -->
    <kebab-cased-component></kebab-cased-component>
    <camel-cased-component></camel-cased-component>
    <title-cased-component></title-cased-component>
    
     

    当使用字符串模式时,可以不受 HTML 的 case-insensitive 限制。这意味实际上在模版中,你可以使用 camelCase 、 PascalCase 或者 kebab-case 来引用你的组件和 prop:

    <!-- 在字符串模版中可以用任何你喜欢的方式-->
    <my-component></my-component>
    <myComponent></myComponent>
    <MyComponent></MyComponent>
    


    如果组件未经 slot 元素传递内容,你甚至可以在组件名后使用 / 使其自闭合:

    <my-component/>
    
     

    当然,这只在字符串模版中有效。因为自闭的自定义元素是无效的 HTML ,浏览器原生的解析器也无法识别它。

    #授课思路

    #案例和作业

    使用递归组件方式完成如下图的多级菜单

  • 相关阅读:
    201623班《程序设计与数据结构》-第七周作业问题总结
    201623班《程序设计与数据结构》-第六周作业问题总结
    201623班《程序设计与数据结构》-第五周作业问题总结
    201623班《程序设计与数据结构》-第四周作业问题总结
    【不定期更新】201623班级代码量排行
    201623班《程序设计与数据结构》-第二和第三周作业问题总结
    【西北师大-20软工】第一次作业成绩汇总
    关于我和助教
    关于软件工程课程
    2019 SDN上机第4次作业
  • 原文地址:https://www.cnblogs.com/yzy521/p/14132044.html
Copyright © 2011-2022 走看看