动态切换组件 问题解决方案。

本文分享了在Vue.js项目中解决动态切换子组件并结合路由跳转的问题,通过编程式导航和组件间的通信实现从其他页面跳转并自动切换到指定子组件的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于昨天求助的动态切换子组件之后 怎么跳转到该页面切换指定子组件的问题 在大神的劝告下 今天上午我还是走了老办法,把问题解决了,特此小编在这里把代码粘贴出来供大家知道。

问题求助帖子地址: https://blog.csdn.net/Leon_940002463/article/details/103478501

问题是这样的:

这个父组件的代码:

其他代码 不怎么重要 主要是把从其他页面接受到的 active 值接收到 传递给 flow 这个模板组件 以便后续再flow 里面判断 从而实现 进入这个页面切换到指定子组件

<!-- ---------------------
  -- 充值主页面模板
  -- @auther:  Leon
  -- --------------------- -->
<template>
    <z-flow :steps="steps" :aStep="active" /> //  这个是自己写的模板组件  在下面有介绍
</template>

<script>
  import * as log from 'loglevel'
  import Flow from '../../layout/flow.vue'
  import vEvents from '../../utils/v_events'
    // 引入内容子 组件
  import CertType from './steps/cert_type.vue' // 选卡类型
  import ReadIdCard from '../common/read_id_card.vue'  // 读身份证
  import ReadShiBaoCard from '../common/red_she_bao_card.vue' // 读社保卡
  import InputChongZhiCount from './steps/chong_zhi_input.vue' // 输入充值金额
  import InputMiMa from './steps/input_mi_ma.vue'  //  输入密码
  import ShowBalance from './steps/show_blance.vue'  // 展示余额
  import ReadBankCard from '../common/read_bank_card.vue' // 读银行卡
  import ReadHisCard from '../common/read_his_card.vue'  // 读就诊卡
  import VerifyHisCard from '../common/verify_his_card.vue'  // 读卡后显示 卡片信息-----核对信息
  import PayType from './steps/pay_type.vue'   //  选择支付方式
  import MoneyReceiver from '../common/money_receiver.vue' // 现金支付 投币动画
  import VerifyMoney from './steps/xianshijine.vue' // 显示投币金额
  
  import WechatSao from './steps/wechat_sao.vue' // 显示微信扫码 
  import WechatBeiSao from './steps/pay_bei-sao.vue' //  显示微信被扫动画
  import AlipaySao from './steps/alipay_receiver.vue' // 支付宝扫码
  import AlipayBeiSao from './steps/alipay_bei_sao.vue' //  支付宝被扫





  export default {
    name: 'steps-pay',

    components: {
      'z-flow': Flow
    },

    data () {
      return {
        active: '',
      steps: [{  //  这个是传给 模板组件的数组
          id: 'z-cert-type',
          name: '证件类型',
          component: CertType
        }, {
          id: 'z-read-id-card',
          name: '读取证件',
          component: ReadIdCard
        }, {
          id: 'z-verify-id-card',
          name: '核对信息',
          component: VerifyHisCard
        }, {
          id: 'z-pay-type',
          name: '支付方式',
          component: PayType
        }, {
          id: 'z-money',
          name: '现金支付',
          component: MoneyReceiver
        }, {
          id: 'z-verify-money',
          name: '核对金额',
          component: VerifyMoney
        }, {
          id: 'z-show-balance',
          name: '充值成功',
          component: ShowBalance
        }]
      }
    },

    created () {
        //  在这里接受其他页面传递过来的 值 
     this.active = this.$route.query.active 
     log.info('active-------是否充值页面',this.active)
      
    },

    mounted () {

      // 监听事件 
      vEvents.$on('cert-type', this.onCertChanged)  //  读卡方式
      vEvents.$on('pay-type', this.onPayChanged)  //  支付方式
    },

    beforeDestroy () {
      vEvents.$off('cert-type', this.onCertChanged)
      vEvents.$off('pay-type', this.onPayChanged)
    },

    methods: {
      // 卡类型
      onCertChanged (t) {
        log.info('--> card type: ', t)
        switch (t) {
          case 'id':
            this.steps.splice(1, 1, { // splice (开始索引,删除个数,替换值)  //  读身份证
              id: 'z-read-id-card',
              name: '读取证件',
              component: ReadIdCard
            })
            break
          case 'ssc':
            this.steps.splice(1, 1, {
              id: 'z-read-she-bao-card',
              name: '读取证件',
              component: ReadShiBaoCard
            })
            break
          default:
            this.steps.splice(1, 1, {
              id: 'z-read-his-card',
              name: '读取证件',
              component: ReadHisCard
            })
            break
        }
      },

      // 支付类型
      onPayChanged (p) {
         log.info('--> pay type: ', p)
         switch (p) {
          case 'bill': //  现金支付
            this.steps = [{
                id: 'z-cert-type',
                name: '证件类型',
                component: CertType
              }, {
                id: 'z-read-id-card',
                name: '读取证件',
                component: ReadIdCard
              }, {
                id: 'z-verify-id-card',
                name: '核对信息',
                component: VerifyHisCard
              }, {
                id: 'z-pay-type',
                name: '支付方式',
                component: PayType
              }, {
                id: 'z-money',
                name: '现金支付',
                component: MoneyReceiver
              }, {
                id: 'z-verify-money',
                name: '核对金额',
                component: VerifyMoney
              }, {
                id: 'z-show-balance',
                name: '充值成功',
                component: ShowBalance
              }]
            break
          case 'bank-card': // 银行卡支付
               this.steps = [{
                id: 'z-cert-type',
                name: '证件类型',
                component: CertType
              }, {
                id: 'z-read-id-card',
                name: '读取证件',
                component: ReadIdCard
              }, {
                id: 'z-verify-id-card',
                name: '核对信息',
                component: VerifyHisCard
              }, {
                id: 'z-pay-type',
                name: '支付方式',
                component: PayType
              }, {
              id: 'z-input-count',
              name: '输入金额',
              component: InputChongZhiCount
            }, {
              id: 'z-bank',
              name: '银联支付',
              component: ReadBankCard
            },{
              id: 'z-input-mi',
              name: '输入密码',
              component: InputMiMa
            }, {
                id: 'z-show-balance',
                name: '充值成功',
                component: ShowBalance
              }]
            break
          case 'wechat': // 微信支付
             this.steps = [{
                id: 'z-cert-type',
                name: '证件类型',
                component: CertType
              }, {
                id: 'z-read-id-card',
                name: '读取证件',
                component: ReadIdCard
              }, {
                id: 'z-verify-id-card',
                name: '核对信息',
                component: VerifyHisCard
              }, {
                id: 'z-pay-type',
                name: '支付方式',
                component: PayType
              }, {
                id: 'z-input-count',
                name: '输入金额',
                component: InputChongZhiCount
              }, {
                id: 'z-wechat-sao',
                name: '微信支付',
                component: WechatSao
              }, {
                id: 'z-wechat-bei-sao',
                name: '微信支付-被扫',
                component: WechatBeiSao
              }, {
                id: 'z-show-balance',
                name: '充值成功',
                component: ShowBalance
              }]
            break
          default:  //  支付宝支付
              this.steps = [{
                id: 'z-cert-type',
                name: '证件类型',
                component: CertType
              }, {
                id: 'z-read-id-card',
                name: '读取证件',
                component: ReadIdCard
              }, {
                id: 'z-verify-id-card',
                name: '核对信息',
                component: VerifyHisCard
              }, {
                id: 'z-pay-type',
                name: '支付方式',
                component: PayType
              }, {
                id: 'z-input-count',
                name: '输入金额',
                component: InputChongZhiCount
              }, {
                id: 'z-alipay',
                name: '支付宝支付',
                component: AlipaySao
              }, {
                id: 'z-alipay-bei-sao',
                name: '支付宝支付-被扫',
                component: AlipayBeiSao
              }, {
                id: 'z-show-balance',
                name: '充值成功',
                component: ShowBalance
              }]
            break
        }
      }
    }
  }
</script>

flow 模板组件 代码:

<!-- ---------------------
  -- 流程组件 模板 步骤条。左右按钮
  -- @author: Leon
  -- --------------------- -->
<template>
    <z-main-layout>
        <!-- 左边按钮 -->
        <template slot="left">
            <z-side-btn v-for="(btn, idx) in leftBtns" :key="'l-btn-' + idx"
                        pos="left" :text="btn.text" :icon="btn.icon"/>
            <z-side-btn @tapped="onPrev" :disabled="prevStopped" pos="left" text="上一步" icon="fa fa-fw fa-arrow-left"/>
        </template>

        <!-- 中间部分 -->
        <div class="panel">
            <!-- 步骤条 -->
            <div class="step-wrap">
                <el-steps id="steps" align-center :active="active - 1" finish-status="success">
                    <el-step v-for="(step, idx) in steps" :key="'step-' + idx" :title="step.name"/>
                </el-steps>
            </div>

            <!-- 可切换组件位置 -->  在这里显示主题内容  切换不同子组件
            <component :is="currentView" ref="jinE"  />
        </div>

        <!-- 右边按钮 -->
        <template slot="right">
            <z-side-btn v-for="(btn, idx) in rightBtns" :key="'r-btn-' + idx"
                        pos="right" :text="btn.text" :icon="btn.icon" @tapped="onTiaoZhuan(btn.text)" />

            <z-side-btn v-if="active != steps.length" :disabled="nextStopped" @tapped="onNext" pos="right" text="下一步"/>

        </template>
    </z-main-layout>
</template>

<script>
                //  引入依赖
  import * as log from 'loglevel'
  import _ from 'lodash'  
  import vEvents from '../utils/v_events'
			// 引入组成flow 模板组件的 布局子组件跟咱问题无关的组件只是布局用
  import MainLayout from './main_layout.vue'
  import SideBtn from '../component/side_button.vue'
			// 引入硬件读卡js
   import CardMaker from '../hardware/card_maker'

  export default {
    name: 'flow',
    components: {
      'z-main-layout': MainLayout,
      'z-side-btn': SideBtn
    },

    props: {
      fromPath: {
        type: String,
        default: '/frame/home'
      },
      steps: {  // 这个就是上面父组件传入的 切换子组件的一个集合
        type: Array,
        required: true
      },
      aStep: {  //  这就是上面父组件里面接收到的 其他页面传过来的值 这个值就决定了自定切换到第几个子组件
        type: String,
        default: ''
      }
    },

    data () {
      return {
        active: 1,
        prevStopped: false,
        nextStopped: false
      }
    },

    // 计算属性
    computed: {
      // 获取当前步
      currentStep () {
        return this.steps[this.active - 1]
      },

      // 当前的事件源-当前子组件
      currentView () {
        return this.currentStep.component
      },

      leftBtns () {  //  左边动态生成按钮
        if (_.hasIn(this.currentStep, 'buttons.left')) {
          return this.currentStep.buttons.left
        } else {
          return null
        }
      },

      rightBtns () { // 右边动态生成按钮集
        if (_.hasIn(this.currentStep, 'buttons.right')) {
          return this.currentStep.buttons.right
        } else {
          return null
        }
      }
    },

    /* _.has(object, path)
      *检查 path 是否是object对象的直接属性
      * object (Object): 要检索的对象。path (Array|string): 要检查的路径path。
      * (boolean): 如果path存在,那么返回 true ,否则返回 false。
    */

    /* _.trimEnd([string=''], [chars=whitespace])
      *从string字符串中移除后面的 空格 或 指定的字符。
      *[string=''] (string): 要处理的字符串。[chars=whitespace] (string): 要移除的字符。
      *(string): 返回处理后的字符串。
    */
    created () {
      log.info('--> steps:', this.steps)
      this.basePath = this.$route.path
      log.info('this.basePath!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', this.basePath)
      if (_.has(this.$route.params, 'idx')) {  //  这一步就是用编程式导航切换组件  这是关键
        this.basePath = _.trimEnd(this.basePath, '/' + this.$route.params['idx'])
      }
      log.info('--> base path: ', this.basePath)
      
      vEvents.$on('next-step', this.onNext)
      vEvents.$on('prev-step', this.onPrev)
      vEvents.$on('prev-stopped', this.onPrevStopped)
      vEvents.$on('next-stopped', this.onNextStopped)

       if(this.aStep){  //  动态切换 子 组件
          log.info('存在存在存在存在存在存在存在',this.aStep)
          this.active = parseInt(this.aStep)
          this.onNext() // 下面定义好的方法  切换上下组件用
          
        } else {
          log.info(this.aStep,'aStepaStepaStepaStepaStep')
        }
    },

    beforeDestroy () {
      vEvents.$off('prev-step', this.onPrev)
      vEvents.$off('next-step', this.onNext)
      vEvents.$off('prev-stopped', this.onPrevStopped)
      vEvents.$off('next-stopped', this.onNextStopped)
    },

    methods: {

      // 上一步
      onPrev () {
        if (this.active > 1) {
          this.active -= 1
          this.$router.push(this.basePath + '/' + this.active)
        } else {
          this.$router.push(this.fromPath)
        }
        log.info('--> active: ', this.active)
      },

      onPrevStopped (v) { //  禁止点击上一步
        this.prevStopped = v
      },

      // 下一步
      onNext (step) {
        log.info(this.currentView.name, 'this.currentView.name')
        switch (this.currentView.name) {
          case 'bind-mobile-money':
            this.$refs.jinE.judgeValue()
            break
          case 'input-mi-ma':
            log.info('银联支付成功')
            this.$refs.jinE.zhifuqueren()
            break

          default:
            break
        }
       //  这个就是判断当前步 是不是最后一步   不是得话就往下切换组件  到这里整个 切换组件的操作就结束了  
        if (this.active < this.steps.length) {
          this.active += 1
          this.$router.push(this.basePath + '/' + this.active)
        }
        log.info('--> active: ', this.active, this.currentView)
      },
 
      onNextStopped (v) {  //  禁止点击下一步
        this.nextStopped = v
      },


     
      onTiaoZhuan (e) {  //  动态生成的按钮处理事件
        log.info(e,'动态生成的按钮处理事件----flow组件')
        switch (e) {
          case '充值':
            log.info('chongzhi')
            this.$router.push({path:'/frame/pay/steps/:1',query:{active: '3'}})
            break;
          case '取卡':
            log.info('quka')
            // TODO   其实在 办卡页面这个按钮处就会 自动退卡根本不需要 再 执行下面操作
              let cm = new CardMaker()
              cm.readTrack().then((result) => {
                this.sn = result.Track2
                return cm.move(100)
              }).catch((error) => {
                this.$notify.error({
                  title: '错误',
                  message: error.error_msg || error.error_code
                })
              })
            break;
          default:
            break;
        }
      }


    }
  }
</script>

<style scoped>
    .panel {
        display: flex;
        flex-direction: column;
        height: 75vh;
        overflow: hidden;
        color: #303133;
        background-color: #fff;
        border: 1px solid #ebeef5;
        border-radius: .75rem;
        box-shadow: 0 0 0.75rem 0.75rem rgba(12, 89, 209, 0.1), 0 0 0.75rem 0.75rem rgba(12, 89, 209, 0.1);
        transition: .3s;
    }

    .step-wrap {
        padding: 1rem 0;
        width: 100%;
        height: 4rem;
    }
</style>

从 其他页面跳转的代码:

 this.$router.push({path:'/frame/pay/steps/:1',query:{active: '3'}})  //  这里地址后面那个数字  是几都无所谓 只要有就会跳转到 这个页面  重要的是通过 穿过去的active 的值来切换子组件 传3  就会在跳转到该页面之后自动切换到第三个组件。

路由配置:

// router.js

const routes = [{
  path: '/',
  redirect: '/frame/home'
}, {
  path: '/frame',
  component: require('./layout/frame.vue').default,
  children: [{
    path: 'home',
    component: require('./view/home.vue').default
  }, {
    path: 'factory/login',
    component: require('./view/factory/login.vue').default
  }, { // 办卡
    path: 'card/steps/:idx',
    component: require('./view/card/steps_card.vue').default,
    props: true
  }, { // 签约
    path: 'sign/way/:idx',
    component: require('./view/sign/inser_cart.vue').default,
  }, { // 充值
    path: 'pay/steps/:idx',   //  这个就是跳转到的目标页面 路由
    component: require('./view/pay/steps_pay.vue').default,
    props: true
  },
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值