vue递归组件实现子向父传值

本次需求:
实现每次点击折叠面板重新拿到高度
// 效果如下图:

vue递归组件实现子向父传值

所用框架:
antd+vue

难点:

  1. 折叠面板点击之后,直接调用获取高度的方法,高度是滞后的,每次拿到的都是点击之前的高度;
  2. 递归组件子向父传值,如果利用之前的 e m i t , emit, emit,on传值,子组件里又同时包含子和父,无法使用

解决办法:

  1. 高度滞后,设置一个定时器
  2. 使用eventBus传值

核心代码:

1. 在src目录下新加bus.js作为一个公共的实例

import Vue from 'vue'
export var bus = new Vue()

2. 父组件在created里面定义$on监听事件

import {bus} from '../../bus.js'

created() {
  bus.$on( 'getH', (res) => {
    this.getHeight()
  })
}

3. 在子组件中定义点击事件,调用父组件方法通过$emit将相应值传给父组件

import {bus} from '../../bus.js'

methods: {
  changeActive () {
    bus.$emit('getH', true)
  }
}

完整代码:

bus.js:

import Vue from 'vue'
export var bus = new Vue()

父组件:

<template>
  <div ref="colH">
    <a-row :gutter="24">
      <a-col :md="24">
        <a-card title="递归实验">
          <a-steps :current="current">
            <a-step v-for="(item, index) in dataSteps" :key="index" :title="item.name">
              <template slot="description" class="des-style">
                <div v-if="item.children.length === 0">
                  {{ item.name }}
                div>
                <div v-if="item.children.length > 0">
                  <a-collapse :bordered="false" @change="changeFatherH">
                    <a-collapse-panel>
                      <template slot="header">
                        {{ item.name }}
                      template>
                      <RecursionCom :children="item.children">RecursionCom>
                    a-collapse-panel>
                  a-collapse>
                div>
              template>
            a-step>
          a-steps>
        a-card>
      a-col>
    a-row>
  div>
template>

<script>
import RecursionCom from '@/components/RecursionCom'
import {bus} from '../../bus.js'
export default {
  name: 'DraggableTest',
  components: { RecursionCom },
  data () {
    return {
      current: 1,
      dataSteps: [
        {
          id: 'as',
          name: 'Amy',
          age: 12,
          children: [
            {
              id: 'aqs',
              name: 'Amy1',
              age: 11,
              children: []
            },
            {
              id: 'aqsq',
              name: 'Amy2',
              age: 10,
              children: [
                {
                  id: 'aqs1',
                  name: 'Amy22',
                  age: 17,
                  children: []
                },
                {
                  id: 'aqs2',
                  name: 'Amy23',
                  age: 10,
                  children: []
                }
              ]
            },
            {
              id: 'sq',
              name: 'Amy3',
              age: 13,
              children: []
            }
          ]
        },
        {
          id: 'bs',
          name: 'Bill',
          age: 18,
          children: [
            {
              id: 'bs1',
              name: 'Bill1',
              age: 17,
              children: []
            },
            {
              id: 'bs2',
              name: 'Bill2',
              age: 10,
              children: []
            }
          ]
        },
        {
          id: 'cs',
          name: 'Claire',
          age: 34,
          children: [
            {
              id: 'cs1',
              name: 'Claire1',
              age: 14,
              children: []
            },
            {
              id: 'cs2',
              name: 'Claire2',
              age: 45,
              children: [
                {
                  id: 'cs22',
                  name: 'Claire22',
                  age: 14,
                  children: []
                },
                {
                  id: 'cs23',
                  name: 'Claire23',
                  age: 14,
                  children: [
                    {
                      id: 'cs233',
                      name: 'Claire233',
                      age: 19,
                      children: []
                    },
                    {
                      id: 'cs234',
                      name: 'Claire234',
                      age: 10,
                      children: []
                    }
                  ]
                }
              ]
            }
          ]
        },
         {
          id: 'a5s',
          name: 'Damon',
          age: 12,
          children: [
            {
              id: 'dd3',
              name: 'Damon1',
              age: 11,
              children: []
            },
            {
              id: 'e4',
              name: 'Damon2',
              age: 10,
              children: [
                {
                  id: '3e',
                  name: 'Damon22',
                  age: 17,
                  children: []
                },
                {
                  id: 'r4',
                  name: 'Damon23',
                  age: 10,
                  children: []
                }
              ]
            },
            {
              id: 't5',
              name: 'Damon3',
              age: 13,
              children: []
            }
          ]
        }
      ]
    }
  },
  created() {
    bus.$on( 'getH', (res) => {
      this.getHeight()
    })
  },
  methods: {
    changeFatherH () {
      this.getHeight()
    },
    getHeight () {
      const _this = this
      setTimeout(() => {
        console.log('height:' + _this.$refs.colH.offsetHeight)
      }, 500)
    }
  }
}
script>
<style>
.ant-card-body .ant-steps-horizontal .ant-steps-item-description {
  max-width: 225px;
  min-width: 223px;
}
.ant-collapse-item  {
  border-bottom: none;
}
style>

递归子组件:

在components文件夹里新建一个文件夹:RecursionCom
新建RecursionCom.vue
代码如下:

<template>
  <ul style="padding-left: 20px;" class="des1-style">
    <li v-for="(item, index) in children" :key="index">
      {{ item.name }}
      <div v-if="item.children.length > 0">
        <a-collapse :bordered="false" @change="changeActive">
          <a-collapse-panel>
            <template slot="header">
              {{ item.name }}
            template>
            <RecursionCom :children="item.children">RecursionCom>
          a-collapse-panel>
        a-collapse>
      div>
    li>
  ul>
template>
<script>
import {bus} from '../../bus.js'
export default {
  name: 'RecursionCom',
  props: {
    children: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  methods: {
    changeActive () {
      bus.$emit('getH', true)
    }
  }
}
script>
<style scoped>
.ant-card-body .ant-steps-horizontal .ant-steps-item-description {
  max-width: 225px;
  min-width: 223px;
}
.ant-collapse-item  {
  border-bottom: none;
}
style>

RecursionCom文件夹里新建index.js
代码如下:

import RecursionCom from './RecursionCom'
export default RecursionCom


参考:
Vue 实现的递归组件如何向外传递事件和数据
vue递归组件如何传递事件给父组件

版权声明:如无特殊标注,文章均来自网络,本站编辑整理,转载时请以链接形式注明文章出处,请自行分辨。

本文链接:https://www.shbk5.com/dnsj/74367.html