vue 递归组件 (评论列表)


一、引入

最近某项目中,通过fbSdk实现了一种类似于微信朋友圈评论回复的功能。评论数据结构有几层未知,所以用到了递归。

递归组件,顾名思义,就是自己的内部实现又调用自己的组件。比如Vue官方给的treeView的例子,父目录下有子目录,子目录下还有子目录,子子孙孙,无穷尽也。就像俄罗斯套娃。

 

 

 

评论数据结构如上右图,层层嵌套。

封装递归组件👇

外部使用递归组件👇

 

 

 

 

二、应用场景

 除此之外,递归组件应用场景也有很多,比如导航菜单。

 

三、递归组件模版

// example组件的实现 

<template> 
    <div>
         ... 
        <Example></Example> 
         ... 
     </div> 
</template> 

<script> 
     export default { name: 'Example' // 重要 } 
</script>

 

 四、注意事项

 

除了前面所说的name选项是必须的之外,还有一点也是在实现递归组件要注意的,就是要防止无限递归,造成调用栈溢出。

上面说的子子孙孙,一直向下繁衍,可是浏览器受不了。这就要根据实际场景来分析递归的终止条件。

 

五、其他练习

 

接下来,我们来写一个递归组件。

下面的demo实现了一个模拟dom事件冒泡的操作,当点击中心圆时,事件逐级传递,然后改变div的颜色,直到冒泡到最顶层。

这里根据设置圆的数量进行递归,递归的终止条件是直到数量减到1。

 

<h3 style="text-align:center">点击中心圆查看效果</h3>
<div id="app">
 <colorful-circle :count="count"></colorful-circle>
</div>
<script type="text/x-template" id="circle-template">
  <div class="colorful" 
       :style="{
               width: count * 60 + 'px', 
               height: count * 60 + 'px',
               background: color
               }"
    @click="changeColor"
  >
    <colorful-circle 
         v-if="count > 1" 
         :count="count - 1"
         @colorChange="handleColor"
    ></colorful-circle>
  </div>
</script>

 

html,body{
  width: 100%;
  height: 100%;
}

.colorful{
  display:flex;
  margin: 0 auto;
  transition: all .3s ease;
  align-items: center;
  justify-content: center;
  min-width 10px;
  border-radius: 50%;
  min-height: 10px;
  border: 1px solid #eaeaea
}

 

var Color = net.brehaut.Color;

function randomColor() {
    function randomNum(max) {
        return Math.floor(max * Math.random());
    }
    return `rgb(${randomNum(256)},${randomNum(256)},${randomNum(256)})`;
}

Vue.component('colorful-circle', {
  data() {
    return  {
      color: ''
    }
  },
  props: {
    count: Number
  },
  template: '#circle-template',
  mounted() {
    if (this.count === 1) {
      this.changeColor();
    }
  },
  methods: {
    handleColor(c) {
      this.color = Color(c).darkenByAmount( .05 );
      setTimeout(() => {
        this.$emit('colorChange', this.color);
      },100);
    },
    changeColor(e) {
      e && e.stopPropagation();
      this.color = randomColor();
      setTimeout(() => {
        this.$emit('colorChange', this.color);
      },100)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    count: 7
  }
})

 

posted @ 2021-04-12 14:24  CatherLee  阅读(738)  评论(0)    收藏  举报