• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

<component :is=“ “/>动态组件在 el-tab-pane里的应用

武飞扬头像
明长歌
帮助1

添加新需求时翻到了以前的代码,之前选项卡有2项,就不辞辛苦的直接写template里了。这次又新增了两个选项卡页面。于是将以前的结构翻出来直接写循环了。代码在最后面,没什么参考价值可以忽略。

本篇的目的:主要是写完后,发现此页面还有一个选项卡页面,用来切换不同的组件。(后期又被需求拿掉了,但是页面上没删。)本着代码一致的原则,就手贱的改了下。这个项目用的是element UI。在用 el-tabs数据循环的时候,如果不在el-tab-pane的结构中写DOM,最后输出的是一个字符串。尝试了一些方法后,最后用<component :is="item.content" />解决了。具体代码如下图。vue 动态组件

  1.  
    <template>
  2.  
    <div class="app-container">
  3.  
    <section v-if="false">
  4.  
    <h2 id="tab" class="trendTitle">辅助分析工具</h2>
  5.  
    <el-tabs v-model="activeName" type="card" @tab-click="handleClick">
  6.  
    <template v-for="item in auxiliaryTool">
  7.  
    <!-- 额外增加v-if="true",不加:key标红 -->
  8.  
    <el-tab-pane v-if="true" :key="item.name" :label="item.title" :name="item.name">
  9.  
    <div v-if="item.isShow">
  10.  
    <component :is="item.content" />
  11.  
    </div>
  12.  
    </el-tab-pane>
  13.  
    </template>
  14.  
    </el-tabs>
  15.  
    </section>
  16.  
    </div>
  17.  
    </template>
  18.  
     
  19.  
    <script>
  20.  
    import CrossArea from '@/views/smart/crossarea/crossarea';
  21.  
    import Inout from '@/views/smart/inout/inout';
  22.  
    import Quadif from '@/views/smart/quadif/quadif';
  23.  
     
  24.  
    export default {
  25.  
    name: 'Trend',
  26.  
    components: {
  27.  
    CrossArea,
  28.  
    Inout,
  29.  
    Quadif,
  30.  
    BasisStructure,
  31.  
    TermStructure,
  32.  
    },
  33.  
    data() {
  34.  
    return {
  35.  
    activeName: '',
  36.  
    auxiliaryTool: [
  37.  
    {
  38.  
    title: '跨1',
  39.  
    name: 'crossArea',
  40.  
    content: CrossArea,
  41.  
    isShow: false,
  42.  
    },
  43.  
    {
  44.  
    title: '内2',
  45.  
    name: 'inout',
  46.  
    content: Inout,
  47.  
    isShow: false,
  48.  
    },
  49.  
    {
  50.  
    title: '品3',
  51.  
    name: 'quadif',
  52.  
    content: Quadif,
  53.  
    isShow: false,
  54.  
    },
  55.  
    ],
  56.  
    };
  57.  
    },
  58.  
    methods: {
  59.  
    handleClick(val) {
  60.  
    this.auxiliaryTool = this.auxiliaryTool.map(item => {
  61.  
    if (item.name === val.name) {
  62.  
    item.isShow = true;
  63.  
    } else {
  64.  
    item.isShow = false;
  65.  
    }
  66.  
    return item;
  67.  
    });
  68.  
    this.$nextTick(() => {
  69.  
    document.getElementById('tab').scrollIntoView({
  70.  
    behavior: 'smooth',
  71.  
    block: 'start',
  72.  
    });
  73.  
    });
  74.  
    },
  75.  
    },
  76.  
    };
  77.  
    </script>

本文完,以下纯记录,懒得开新文了。 

记录v-for循环el-tab-pane代码

  1.  
    <template>
  2.  
    <div class="app-container">
  3.  
    <section v-loading="loading">
  4.  
    <el-row :gutter="20">
  5.  
    <el-col :span="activeChart === 'first' || activeChart === 'second' ? 16 : 24">
  6.  
    <h3 class="chartTitle">{{ chartTitle }}</h3>
  7.  
    <el-tabs v-model="activeChart" type="card" @tab-click="handleClick2">
  8.  
    <template v-for="item in tabs">
  9.  
    <el-tab-pane v-if="item.hasOwnProperty('isPer') ? item.isPer : true" :key="item.name" :label="item.title" :name="item.name">
  10.  
    <div v-if="activeChart === item.name">
  11.  
    <line-chart v-show="ChartBoxShow" :chart-data="lineChartData" :height="chartHeight" />
  12.  
    <el-empty v-show="!ChartBoxShow" description="暂无数据" />
  13.  
    </div>
  14.  
    </el-tab-pane>
  15.  
    </template>
  16.  
    </el-tabs>
  17.  
    </el-col>
  18.  
    <el-col v-if="activeChart === 'first' || activeChart === 'second'" v-hasPermi="['price:trend:query']" :span="8">
  19.  
    <div v-dompurify-html.trim="coalAnalyze" class="artitle" :style="{ height: chartHeight }" />
  20.  
    </el-col>
  21.  
    <el-col v-if="activeChart === 'first' || activeChart === 'second'" v-hasPermi="['price:trend:query']" :span="24" class="explainBox">
  22.  
    <div v-dompurify-html.trim="coalExplain" class="artitle" />
  23.  
    </el-col>
  24.  
    </el-row>
  25.  
    </section>
  26.  
    </div>
  27.  
    </template>
  28.  
     
  29.  
    <script>
  30.  
    import LineChart from '@/components/Echarts/LineCharts';
  31.  
    import { coalIndex, getGraph, getGraph2, getPreIindex, getReport } from '@/api/trend';
  32.  
    import { debounce, getTime, setMyOpts, sortSeriesByMaxValue } from '@/utils/global.js';
  33.  
     
  34.  
    export default {
  35.  
    name: 'Trend',
  36.  
    components: {
  37.  
    LineChart,
  38.  
    },
  39.  
    data() {
  40.  
    return {
  41.  
    loading: true, // 遮罩层
  42.  
    isPer: false, //判断是否具有某个权限
  43.  
    // 图表
  44.  
    chartTitle: '标题',
  45.  
    chartHeight: '0', //设置图表高度
  46.  
    lineChartData: {}, // 图表数据
  47.  
    ChartBoxShow: true, //图表有无数据,是否显示
  48.  
    // 解释文字/后台输出的文字内容
  49.  
    coalAnalyze: '',
  50.  
    coalExplain: '',
  51.  
    // 选项卡
  52.  
    activeChart: this.isPer ? 'second' : 'three',
  53.  
    tabs: [
  54.  
    {
  55.  
    title: '总预测趋势图',
  56.  
    name: 'first',
  57.  
    isPer: false,
  58.  
    },
  59.  
    {
  60.  
    title: '区间预测图',
  61.  
    name: 'second',
  62.  
    isPer: false,
  63.  
    },
  64.  
    {
  65.  
    title: '预测指数图',
  66.  
    name: 'three',
  67.  
    },
  68.  
    {
  69.  
    title: '周环比分析图',
  70.  
    name: 'four',
  71.  
    },
  72.  
    ],
  73.  
    };
  74.  
    },
  75.  
    computed: {
  76.  
    permissions() {
  77.  
    return this.$store.getters.permissions;
  78.  
    },
  79.  
    },
  80.  
    watch: {
  81.  
    isPer: {
  82.  
    handler: function(newVal) {
  83.  
    this.tabs = this.tabs.map(item => {
  84.  
    if (item.hasOwnProperty('isPer')) {
  85.  
    item['isPer'] = newVal;
  86.  
    }
  87.  
    return item;
  88.  
    });
  89.  
    },
  90.  
    deep: true,
  91.  
    },
  92.  
    },
  93.  
    created() {
  94.  
    this.isPer = this.permissions.some(permission => {
  95.  
    return '*:*:*' === permission || ['price:trend:query'].includes(permission);
  96.  
    });
  97.  
    this.activeChart = this.isPer ? 'second' : 'three';
  98.  
    // 设置图表高度
  99.  
    this.setChartHeight();
  100.  
    // 提交表单
  101.  
    this.getSubmit(this.queryParams);
  102.  
    this.getSubmit = debounce(function(data) {
  103.  
    this.handleClick2({ name: this.activeChart });
  104.  
    getReport().then(res => {
  105.  
    this.coalExplain = res.data
  106.  
    .map(item => {
  107.  
    if (!item.title.includes('分析')) {
  108.  
    return `
  109.  
    <h3>${item.title.includes('、') ? item.title.split('、')[1] : item.title}</h3>
  110.  
    <p>${item.desc.replace(/\r\n/gm, '<br/>')}</p>
  111.  
    `;
  112.  
    }
  113.  
    })
  114.  
    .join('');
  115.  
    this.coalAnalyze = res.data
  116.  
    .map(item => {
  117.  
    if (item.title.includes('分析')) {
  118.  
    return `
  119.  
    <h3>${item.title.includes('、') ? item.title.split('、')[1] : item.title}</h3>
  120.  
    <p>${item.desc.replace(/\r\n/gm, '<br/>')}</p>
  121.  
    `;
  122.  
    }
  123.  
    })
  124.  
    .join('');
  125.  
    });
  126.  
    });
  127.  
    },
  128.  
    methods: {
  129.  
    handleClick2(val) {
  130.  
    let obj = {
  131.  
    first: {
  132.  
    title: '1',
  133.  
    api: getGraph,
  134.  
    },
  135.  
    second: {
  136.  
    title: '1',
  137.  
    api: getGraph2,
  138.  
    },
  139.  
    three: {
  140.  
    title: '2',
  141.  
    api: getPreIindex,
  142.  
    },
  143.  
    four: {
  144.  
    title: '3',
  145.  
    api: getPreIindex,
  146.  
    },
  147.  
    // four: () => {
  148.  
    // return new Promise(async resolve => {
  149.  
    // this.chartTitle = '周环比分析';
  150.  
    // this.loading = true;
  151.  
    // let res = getPreIindex();
  152.  
    // resolve(res);
  153.  
    // });
  154.  
    // },
  155.  
    };
  156.  
    if (!obj[val.name].title || !obj[val.name].api) {
  157.  
    return;
  158.  
    }
  159.  
    this.getCharts(obj[val.name].title, obj[val.name].api).then(({ res, title }) => {
  160.  
    this.loading = false;
  161.  
    this.chartTitle = title;
  162.  
    this.ChartBoxShow = res['data'] ? true : false;
  163.  
    if (this.ChartBoxShow) {
  164.  
    let myChart = this.$store.state.echarts.init[0];
  165.  
    const customObj = {
  166.  
    first: {
  167.  
    title: {
  168.  
    subtext: '',
  169.  
    },
  170.  
    legend: {
  171.  
    top: '34px',
  172.  
    right: 'auto',
  173.  
    orient: 'horizontal',
  174.  
    },
  175.  
    grid: {
  176.  
    width: '72%',
  177.  
    top: '76px',
  178.  
    left: '38',
  179.  
    },
  180.  
    series: item => {
  181.  
    if (item.type === 'scatter') {
  182.  
    if (typeof item.label.formatter == 'string') {
  183.  
    return {
  184.  
    color: 'rgb(231,90,110)',
  185.  
    label: {
  186.  
    backgroundColor: 'rgba(231,90,110,.3)',
  187.  
    },
  188.  
    labelLayout: {
  189.  
    with: 160,
  190.  
    x: myChart.getWidth() - 120,
  191.  
    draggable: true,
  192.  
    verticalAlign: 'middle',
  193.  
    },
  194.  
    markPoint: null,
  195.  
    markLine: null,
  196.  
    };
  197.  
    }
  198.  
    return {
  199.  
    labelLayout() {
  200.  
    return {
  201.  
    width: typeof item.label.formatter == 'string' ? 160 : 140,
  202.  
    x: myChart.getWidth() - 120,
  203.  
    draggable: true,
  204.  
    verticalAlign: 'middle',
  205.  
    };
  206.  
    },
  207.  
    markPoint: null,
  208.  
    markLine: null,
  209.  
    };
  210.  
    } else {
  211.  
    if (item.name.includes('动力煤连续合约')) {
  212.  
    return {
  213.  
    markLine: null,
  214.  
    markPoint: {
  215.  
    symbol: 'circle',
  216.  
    symbolSize: 10,
  217.  
    label: {
  218.  
    show: false,
  219.  
    },
  220.  
    },
  221.  
    };
  222.  
    }
  223.  
    return {
  224.  
    markPoint: null,
  225.  
    markLine: null,
  226.  
    };
  227.  
    }
  228.  
    },
  229.  
    },
  230.  
    second: {
  231.  
    legend: {
  232.  
    top: '48px',
  233.  
    right: 'auto',
  234.  
    orient: 'horizontal',
  235.  
    },
  236.  
    grid: {
  237.  
    width: '72%',
  238.  
    top: '76px',
  239.  
    left: '38',
  240.  
    },
  241.  
    series: item => {
  242.  
    if (item.type === 'scatter') {
  243.  
    if (typeof item.label.formatter == 'string') {
  244.  
    return {
  245.  
    color: 'rgb(231,90,110)',
  246.  
    label: {
  247.  
    backgroundColor: 'rgba(231,90,110,.3)',
  248.  
    },
  249.  
    labelLayout: {
  250.  
    with: 160,
  251.  
    x: myChart.getWidth() - 120,
  252.  
    draggable: true,
  253.  
    verticalAlign: 'middle',
  254.  
    },
  255.  
    markPoint: null,
  256.  
    markLine: null,
  257.  
    };
  258.  
    }
  259.  
    return {
  260.  
    labelLayout: {
  261.  
    with: 140,
  262.  
    x: myChart.getWidth() - 120,
  263.  
    draggable: true,
  264.  
    verticalAlign: 'middle',
  265.  
    },
  266.  
    markPoint: null,
  267.  
    markLine: null,
  268.  
    };
  269.  
    } else {
  270.  
    if (item.name.includes('动力煤连续合约')) {
  271.  
    return {
  272.  
    markLine: null,
  273.  
    markPoint: {
  274.  
    symbol: 'circle',
  275.  
    symbolSize: 10,
  276.  
    label: {
  277.  
    show: false,
  278.  
    },
  279.  
    },
  280.  
    };
  281.  
    }
  282.  
    if (item.name.includes('预测值上限') || item.name.includes('预测值下限')) {
  283.  
    return {
  284.  
    itemStyle: {
  285.  
    color: '#aaaaaa',
  286.  
    borderColor: '#aaaaaa',
  287.  
    },
  288.  
    lineStyle: {
  289.  
    color: '#aaaaaa',
  290.  
    },
  291.  
    markPoint: null,
  292.  
    markLine: null,
  293.  
    };
  294.  
    }
  295.  
    return {
  296.  
    markPoint: null,
  297.  
    markLine: null,
  298.  
    };
  299.  
    }
  300.  
    },
  301.  
    },
  302.  
    three: {
  303.  
    legend: {
  304.  
    top: '48px',
  305.  
    right: 'auto',
  306.  
    orient: 'horizontal',
  307.  
    },
  308.  
    grid: {
  309.  
    width: '96%',
  310.  
    top: '76px',
  311.  
    left: '38',
  312.  
    },
  313.  
    yAxis: [
  314.  
    {
  315.  
    name: '',
  316.  
    },
  317.  
    ],
  318.  
    series: item => {
  319.  
    if (item.type === 'scatter') {
  320.  
    return {
  321.  
    labelLayout: {
  322.  
    with: 140,
  323.  
    x: myChart.getWidth() - 120,
  324.  
    draggable: true,
  325.  
    verticalAlign: 'middle',
  326.  
    },
  327.  
    markPoint: null,
  328.  
    markLine: null,
  329.  
    };
  330.  
    } else {
  331.  
    return {
  332.  
    markPoint: null,
  333.  
    markLine: null,
  334.  
    };
  335.  
    }
  336.  
    },
  337.  
    },
  338.  
    four: {
  339.  
    legend: {
  340.  
    top: '48px',
  341.  
    right: 'auto',
  342.  
    orient: 'horizontal',
  343.  
    },
  344.  
    grid: {
  345.  
    width: '96%',
  346.  
    top: '76px',
  347.  
    left: '38',
  348.  
    },
  349.  
    yAxis: [
  350.  
    {
  351.  
    name: '',
  352.  
    },
  353.  
    ],
  354.  
    series: item => {
  355.  
    if (item.type === 'scatter') {
  356.  
    return {
  357.  
    labelLayout: {
  358.  
    with: 140,
  359.  
    x: myChart.getWidth() - 120,
  360.  
    draggable: true,
  361.  
    verticalAlign: 'middle',
  362.  
    },
  363.  
    markPoint: null,
  364.  
    markLine: null,
  365.  
    };
  366.  
    } else {
  367.  
    return {
  368.  
    markPoint: null,
  369.  
    markLine: null,
  370.  
    };
  371.  
    }
  372.  
    },
  373.  
    },
  374.  
    };
  375.  
    let custom = customObj[val.name];
  376.  
    this.lineChartData = setMyOpts(sortSeriesByMaxValue(res['data']), custom);
  377.  
    }
  378.  
    });
  379.  
    },
  380.  
    getCharts(title, api) {
  381.  
    return new Promise(async resolve => {
  382.  
    if (typeof api == 'function') {
  383.  
    this.loading = true;
  384.  
    let res = await api();
  385.  
    resolve({ res, title });
  386.  
    }
  387.  
    });
  388.  
    },
  389.  
    setChartHeight() {
  390.  
    // 设置图表高度
  391.  
    let halfWidth = (document.documentElement.clientWidth / 2) * 0.74;
  392.  
    this.chartHeight = (halfWidth / 4) * 3 'px';
  393.  
    window.onresize = () => {
  394.  
    return (() => {
  395.  
    halfWidth = (document.documentElement.clientWidth / 2) * 0.74;
  396.  
    this.chartHeight = (halfWidth / 4) * 3 'px';
  397.  
    })();
  398.  
    };
  399.  
    },
  400.  
    },
  401.  
    };
  402.  
    </script>
  403.  
    <style lang="scss" scoped>
  404.  
    @import '@/assets/styles/explain.scss';
  405.  
    .chartTitle {
  406.  
    text-align: center;
  407.  
    @include themeify {
  408.  
    color: themed('main-font-color');
  409.  
    }
  410.  
    }
  411.  
    .formBox {
  412.  
    margin: 0 0 30px;
  413.  
    }
  414.  
    .explainBox {
  415.  
    margin-top: 30px;
  416.  
    }
  417.  
    ::v-deep .artitle {
  418.  
    margin-top: 0;
  419.  
    font-size: 16px;
  420.  
    }
  421.  
    ::v-deep .artitle h3 {
  422.  
    margin: 6px auto 14px;
  423.  
    text-indent: 0;
  424.  
    font-size: 24px;
  425.  
    // font-weight: normal;
  426.  
    }
  427.  
    ::v-deep .artitle p {
  428.  
    width: 98%;
  429.  
    line-height: 2;
  430.  
    margin: 10px auto;
  431.  
    text-indent: 0;
  432.  
    }
  433.  
    .trendTitle {
  434.  
    margin: 50px 0 20px;
  435.  
    text-align: left;
  436.  
    @include themeify {
  437.  
    color: themed('main-font-color');
  438.  
    }
  439.  
    }
  440.  
    .rangeSeparator {
  441.  
    display: inline-block;
  442.  
    height: 100%;
  443.  
    padding: 0 5px;
  444.  
    margin: 0;
  445.  
    text-align: center;
  446.  
    line-height: 32px;
  447.  
    font-size: 14px;
  448.  
    width: 5%;
  449.  
    @include themeify {
  450.  
    color: themed('main-font-color');
  451.  
    }
  452.  
    }
  453.  
    </style>

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhkifee
系列文章
更多 icon
同类精品
更多 icon
继续加载