Vue.js 从零开:v-bind:is 动态元件

如果要控制元件出现或是消失,依照之前讨论的章节,会使用到v-ifv-show的指令来完成,但当你的元件较多时,写的code会看起来很多,这时可以使用:is来优化,下面用tab功能来当范例。


分页功能 v-if

<div id="app">
  <button v-for="item in tab" :key="item" @click="click(item)">
    {{ item }}
  </button>
  <tab-one v-if="title === 'One'">{{ item }}</tab-one>
  <tab-two v-if="title === 'Two'"></tab-two>
</div>
const app = Vue.createApp({
  data() {
    return {
      title: 'One',
      tab: ['One', 'Two']
    }
  },
  methods: {
    click(e){
      this.title = e;
    }
  },
});
app.component('tab-one',{
  template: `<div>one-component</div>`
});
app.component('tab-two',{
  template: `<div>two-component</div>`
});

app.mount('#app');
  1. 注册两个内层元件tab-onetab-two
  2. 外层元件html模组,增加内层元件v-if判断。
  3. 透过@click="click(item)"改变外层元件的data,做到切换分页功能。

目前子元件只有两个用v-if来写还看不差异,数量较多就可以改为:is方式来处理。


分页功能 v-bind:is

<div id="app">
    <button v-for="item in tabs" :key="item" @click="titleTab = item">
        {{ item }}
    </button>
    <!-- titleTab的值有变化,元件跟着切换 -->
    <component :is="tabComponent">
</div>
const app = Vue.createApp({
  data() {
    return {
      titleTab: 'One',
      tabs: ['One','Two','Three','Four','Five','six'],
    };
  },
  computed: {
    tabComponent() {
      // 转成小写并回传 ,符合相对应的component名称,就会显示。
      return `tab-${ this.titleTab.toLowerCase() }`
    }
  }
});
app.component("tab-one", {
  template: `<div class="tab">One component</div>`
});
app.component("tab-two", {
  template: `<div class="tab">Two component</div>`
});
app.component("tab-three", {
  template: `<div class="tab">three component</div>`
});
app.component("tab-four", {
  template: `<div class="four">four component</div>`
});
app.component("tab-five", {
  template: `<div class="tab">five component</div>`
});
app.component("tab-six", {
  template: `<div class="tab">six component</div>`
});
app.mount("#app");

新增了六个子元件,在外层元件模板使用v-if就要写六次。

  1. 这边改写为<component :is="tabComponent">
  2. 增加computed属性,如果titleTab的值有变化,元件跟着切换,并改变computedName

目前分页功能可以正常运作,如果在每个子元件都放一个input输入框,观察里面值的变化。


改写上一个范例的Js

const app = Vue.createApp({
  data() {
    return {
      titleTab: 'One',
      tabs: ['One','Two','Three'],
    };
  },
  computed: {
    tabComponent() {
      // 转成小写并回传 ,符合相对应的component名称,就会显示。
      return `tab-${ this.titleTab.toLowerCase() }`
    }
  }
});
app.component("tab-one", {
  template: `<div class="tab">One component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第一个子元件"
    }
  }
});
app.component("tab-two", {
  template: `<div class="tab">Tow component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第二个子元件"
    }
  }
});
app.component("tab-three", {
  template: `<div class="tab">Tow component</div>
  <input type="text" v-model="text">`,
  data() {
    return {
      text: "第三个子元件"
    }
  }
});
app.mount("#app");

修改输入框的文字,再切换其他分页,会发现修改後的值,不会被留存,为了解决这个问题Vue.js提供了<keep-alive>元素,来改善这个问题。


<keep-alive>

将要保留的元件,放在<keep-alive>元素即可:

<keep-alive>
    <component :is="tabComponent">
</keep-alive>

参考资料

重新认识 Vue.js
:is
keep-alive


<<:  Day 27 颁奖与仪式

>>:  Day 26 [Python ML、资料清理] 资料缩放以及标准化

英雄列表范例:修改英雄

为了让使用者更直觉的修改,我希望能直接点英雄的名字就切换成可修改的输入元件,修改完後就直接存回後端。...

【JavaScript】解构赋值

【前言】 本系列为个人前端学习之路的学习笔记,在过往的学习过程中累积了很多笔记,如今想藉着IT邦帮忙...

Outstanding ecommerce website design

只要编固定预算金额(不用一项一项说明),不要超过,如果可以省下的话,当福利金或拿去吃大餐,至少我们都...

[Day7]2 the 9s

上一篇介绍了Back to High School Physics,是一个简单的距离公式,主要是英文...

D16 - 彭彭的课程# Python Module 模组的载入与使用(1)

今天又迎来周末了~ 真是很棒祝大家周末愉快 btw 10/1 流感疫苗开打家里有65岁以上的人可以去...