vue keep-alive和component:is内部不能嵌套使用带有keep-alive和component:is的组件吗?

2个组件,A和B A组件的template标签下有如下代码

  <keep-alive>
        <component :is="radio1" :key="radio1" :message="message"></component>
      </keep-alive>

在A组件中导入B组件和其他组件,通过A组件template标签内配置的按钮组件或Checkobx组件和搭配keep-alive和component,切换显示B组件和其他组件。也就是tabs选项卡切换不同组件显示的功能

B组件内,也有如下代码

 <keep-alive>
  <component :is="activeName" :key="activeName" :message="page_message"></component>
 </keep-alive>

B组件要做和A组件差不多的事情,导入除了A组件的其他组件。也是借助按钮组件或Checkobx组件和keep-alive和component,切换显示其他组件,

调试运行时,在页面上,显示A组件,点击a组件内的选项卡,从其他组件切换显示B组件时,浏览器控制台抛出一大堆错误,然后浏览器页面内的vue程序运行就不正常了。比如A组件再也无法切换显示其他组件、点击vue的checkbox组件,无法取消勾选框,点击绑定vue事件的按钮没有任何效果

这是什么意思?难道keep-alive和component:is不能嵌套使用带有keep-alive和component:is的组件吗

详细相关部分代码,去除了一些无关js代码和css代码
app.vue(A组件)

<template>
  <div class="box">
    <div class="header">
      <div class="title">sss</div>
      <el-radio-group
        
        v-model="radio1"
        @input="radio_onchange"
      >
        <el-radio-button
          v-for="(item, index) in page_list"
          :key="index"
          :label="item.view_code"
          >{{ item.label }}</el-radio-button
        >
      </el-radio-group>
    </div>
    <div class="content5">
      <keep-alive>
        <component :is="radio1" :key="radio1" :message="message"></component>
      </keep-alive>
    </div>
    <div>123</div>
  </div>
</template>

<script>
import Vue from "vue";
import Test1 from "@/testComponent/test1.vue";
import TestAdmin from "@/test/testChild1.vue";

export default {
  data() {
    return {
      test: "123",
      radio1: "a1",
      message: undefined,
      page_list: [
        { seq: 1, view_code: "a1", label: "测试1", type: 1 },
        {
          seq: 3,
          view_code: "b0",
          label: "特定测试组件A",
          type: 2,
          message: "参数777",
          is_regist: false,
          view: Test1,
        },
        {
          seq: 4,
          view_code: "bc",
          label: "特定测试组件B",
          type: 2,
          message: "参数666",
          is_regist: false,
          view: Test1,
        },
        {
          seq: 4,
          view_code: "e0",
          label: "特定测试管理组件C",
          type: 2,
          message: "参数1234",
          is_regist: false,
          view: TestAdmin,
        },
        {
          seq: 5,
          view_code: "e1",
          label: "特定测试管理组件C",
          type: 2,
          message: "参数4567",
          is_regist: false,
          view: TestAdmin,
        },
      ],
    };
  },
  components: {
    a1: Test1,
  },

  methods: {
    radio_onchange(value) {
      var item = this.page_list.find((item) => item.view_code === value);
      if (item.type != 2) {
        return;
      }
      if (item.is_regist == false) {
        Vue.component(item.view_code, item.view);
        this.message = item.message;
        item.is_regist = true;
      }
    },
  },
};
</script>

test3.vue(其他组件)

<template>
    <div>
        First name: <input type="text" name="FirstName" value="555"><br>
        Last name: <input type="text" name="LastName" value="666"><br>
       参数内容:{{page_id}}
     </div>
   </template>
   <script>
   export default {
        props:[
            'message'
        ],
        data(){
          return {
            page_id:undefined,
          };
        },
        created(){
          this.page_id=this.message
        },
   }
   </script>

修改后的testChild1.vue(B组件),修改之前,在App.vue切换到该组件后,就出抛出浏览器控制台的错误了,测了几下,好像是el-tabs的v-model和component的is绑定同一个属性造成的,把el-tabs注释掉就没问题了。

以下是修改之后的,增加新的属性viewName,component的is和key绑定viewName,el-tabs的v-model就绑定activeName。点击菜单,给viewName和activeName赋同一个值

<template>
  <div class="box">
    <div class="header">
      <el-button type="primary"   @click="collapsed = !collapsed" size="mini">
        <i class="el-icon-s-fold" v-show="collapsed" ></i>
        <i class="el-icon-s-unfold" v-show="collapsed==false" ></i>
      </el-button>
      {{page_id}}

    </div>
    <div class="content5">
      <div class="aside" v-show="collapsed===true">
        <el-menu
      default-active="2"
      class="el-menu-vertical-demo"
     
      background-color="#545c64"
      text-color="#fff"
      active-text-color="#ffd04b">

      <template v-for="(item,index) in menuItems">
        <el-menu-item v-if="item.menu_type==1" :index="item.sort_num+''" @click="MenuClick(item,item.sort_num+'')">{{item.label}}</el-menu-item>

        <el-submenu v-else-if="item.menu_type==2" :index="item.sort_num+''"  >
          <template slot="title">
          <span>{{item.label}}</span>
        </template>
          <template v-for="(childItem,childIndex) in item.children">
            <el-menu-item :index="item.sort_num+'-'+childItem.sort_num" @click="MenuClick(childItem,item.sort_num+'-'+childItem.sort_num)" >{{childItem.label}}</el-menu-item>
          </template>
        </el-submenu>

      </template>

        </el-menu>
      </div>
        <div class="tabs">
        <div class="tabHeader">
         <div>
       
          <el-tabs v-model="activeName" @tab-click="tabHeaderClick" @tab-remove="removeTab" >
            <el-tab-pane  v-for="(item) in tab_list" :label="item.label" :name="item.code" closable  >
              
            </el-tab-pane>
          </el-tabs>
         </div>
        </div>
        <div class="tabContent">
          <keep-alive>
            <component :is="viewName" :key="viewName" :message="page_message" ></component>
          </keep-alive>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import Vue from "vue";
import Test3 from "@/testComponent/test3.vue";

export default {
  props:['message'],
  data() {
    return {
      activeName: undefined,
     viewName:undefined,
      tab_list:[

      ],
      page_message:undefined,
      menuItems:[
        {menu_type:1,label:"菜单1",sort_num:1,id:"a1",view_type:1},
        {menu_type:2,label:"菜单2",sort_num:2,id:"a2",children:[
          {menu_type:1,label:"子菜单1",sort_num:1,id:"a3",view_type:2},
          {menu_type:1,label:"子菜单2",sort_num:2,id:"a4",view_type:1},
        ]},
        {menu_type:1,label:"菜单3",sort_num:3,id:"a5",view_type:2},
      ],
      page_id:undefined,
      collapsed: true,
      
    };
  },
  created(){
    this.page_id=this.message;
  },

  methods: {
   

    removeTab(val){
      var index = this.tab_list.findIndex((item) => item.code === val);
      if(index==-1){
        return;
      }
      this.tab_list.splice(index, 1);
    },

    tabHeaderClick(val){
      this.viewName=val.name;
    },

    MenuClick(item){
      var tabItem = this.tab_list.find((tabItem) => tabItem.code === item.id);
      if(tabItem!=undefined){
        this.activeName=tabItem.code;
        this.viewName=tabItem.code;
        return;
      }

      if(item.view_type==1){

        return;
      }else if(item.view_type==2){
        if(item.is_regist==undefined){
          Vue.component(item.id, Test3);
          this.page_message = item.id;
          item.is_regist=true;
        }
      }

      var obj={code:item.id,label:item.label};
      this.tab_list.push(obj);
      this.activeName=obj.code;
      this.viewName=obj.code;
    },



  },
};
</script>
阅读 1.8k
1 个回答

看起来不是不能嵌套的问题,而是标签名有错误,不是一个有效的HTML元素名。
检查一下看看业务代码,可能是由于你的 is 绑定的自定义组件有问题,或者因为其他原因的导致渲染出错了。

我看OP一直修改问题描述,我还是贴一个我现在用的 component:is 的样例代码吧:

<template>
  <div class="demo">
    <div class="demo-step">
      <el-steps simple>
        <el-step v-for="(step,index) in stepList" :key="step.key" :title="step.label" :status="step.status" @click.native="gotoStep(step.key)" />
      </el-steps>
    </div>
    <div class="demo-container">
      <components :is="currentStepComponent" ref="stepForm" :data="reportData" />
    </div>
  </div>
</template>
<script>
import step1Comp from './components/step1content'
import step2Comp from './components/step2content'
import step3Comp from './components/step3content'

export default {
  name: 'xxxxx',
  data() {
    return {
      data: {},
      activeStep: "step1",
      stepList:[
        { label: '步骤1', component: step1Comp, key: 'step1', status: 'process' },
        { label: '步骤2', component: step2Comp, key: 'step2', status: 'process' },
        { label: '步骤3', component: step3Comp, key: 'step3', status: 'process' },
      ]
    }
  },
  computed: {
    // 当前组件
    currentStepComponent() {
      const currentStep = this.stepList.find(item=>item.key === this.activeStep)
      return currentStep.component
    }
  },
}
</script>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题