Vue 动态组件和keep-alive的使用

2022-01-12  本文已影响0人  coderhzc

一. component Vue 内置组件的基本使用 它提供了一个is属性,

<component  is="Left"></component >
<component  :is="comName"></component >
1. is有两种方法绑值,
       -- 直接写死的方式is="组件的名称"
       -- v-bind动态绑定的写法但是需要再data中定义一个变量 :is="comName"
2. is属性的值,表示要渲染的组件的名字

写死的写法:

image.png

动态的写法

image.png

需求: 点击Left就出现Left组件 点击Right出现Right组件

<template>
  <div id="app">
    <div class="title">
      <h1>App 根组件</h1>
      <hr />
    </div>

    <button @click="btn(1)">展示Left</button>
    <button @click="btn(2)">展示Right</button>
    <div class="comp-box">
      <!-- <Left></Left>
      <Right></Right> -->
      <!-- component Vue 内置组件的使用 -->

      <!-- 1.这种就写死了 -->
      <!-- <component is="Left"></component> -->

      <!-- 2.动态绑定的写法 -->
      <component :is="comName"></component>
    </div>
  </div>
</template>

<script>
import Left from "@/components/Left.vue";
import Right from "@/components/Right.vue";
export default {
  name: "App",
  data() {
    return {
      comName: "Left", // 表示要展示的名字
    };
  },
  components: {
    Right,
    Left,
  },
  methods: {
    btn(num) {
      num === 1 ? (this.comName = "Left") : (this.comName = "Right");
    },
  },
};
</script>

<style lang="less" scoped>
#app {
  .title {
    height: 60px;
    line-height: 60px;
    background-color: #ccc;
    text-align: center;
    padding: 20px 0;
    margin-bottom: 10px;
  }
  .comp-box {
    display: flex;
    justify-content: space-between;
  }
}
</style>

实际截图

image.png

一.二 动态组件之间的传值 和事件绑定发射问题

动态组件之间的传值,他绑定到<component></component>中的属性,对应的所有组件也会接受到传递过来的数据

component 动态组件的传递参数:

App.vue中的代码:
<template>
  <button
    v-for="item in tabs"
    :key="item"
    @click="btnClick(item)"
    :class="currentTitle === item ? 'active' : ''"
  >
    {{ item }}
  </button>

  <h1>{{ currentTitle }}</h1>

  <component :is="CpmName" :age="18" name="huzhenchu"></component>
</template>

<script>
import HomeCpn from "./pages/Home.vue";
import AboutCpn from "./pages/About.vue";
import CategoryCpn from "./pages/Category.vue";
export default {
  name: "AppCpn",
  components: {
    HomeCpn,
    AboutCpn,
    CategoryCpn,
  },
  data() {
    return {
      tabs: ["Home", "About", "Category"],
      currentTitle: "Home",
      CpmName: "HomeCpn",
    };
  },

  methods: {
    btnClick(item) {
      console.log(item);
      this.currentTitle = item;
      // if (item === "Home") {
      //   this.CpmName = 'HomeCpn'
      // }else if(item === "About") {
      //   this.CpmName = "AboutCpn"
      // }else if(item === "category") {
      //   this.CpmName = "CategoryCpn"
      // }
      switch (item) {
        case "Home":
          this.CpmName = "HomeCpn";
          break;
        case "About":
          this.CpmName = "AboutCpn";
          break;

        case "Category":
          this.CpmName = "CategoryCpn";
          break;
        default:
          break;
      }
    },
  },
};
</script>

<style lang="css" scoped>
.active {
  color: red;
}
</style>


/**********Home.vue子组件****************/
<template>
  <div class="home-box">
    <h3>Home:{{ name }} ---- {{ age }}</h3>
  </div>
</template>

<script>
export default {
  name: "HomeCpn",
  props: {
    name: {
      type: String,
      default: "",
    },
    age: {
      type: Number,
      default: 18,
    },
  },
};
</script>

<style lang="css" scoped>
.home-box {
  width: 400px;
  height: 400px;
  border: 1px solid red;
  margin-top: 20px;
  padding: 20px;
  box-sizing: border-box;
}
</style>

实际截图

image.png

component动态组件的事件传递(子组件向父组件传值)实际截图如下:

image.png

二.keep-alive的使用

二.一 keep-alive的基本使用

需求在第一个页面点击+ 1 然后去了别的页面浏览网页,再回来当前页,还要看到当前页的 + 1?

<template>
  <div id="app">
    <div class="title">
      <h1>App 根组件</h1>
      <hr />
    </div>

    <button @click="btn(1)" style="margin-right: 15px">展示Left</button>
    <button @click="btn(2)">展示Right</button>
    <div class="comp-box">
      <!-- <Left></Left>
      <Right></Right> -->
      <!-- component Vue 内置组件的使用 -->

      <!-- 1.这种就写死了 -->
      <!-- <component is="Left"></component> -->

      <!-- 2.动态绑定的写法 -->
      <keep-alive>
        <component :is="comName"></component>
      </keep-alive>
    </div>
  </div>
</template>

<script>
import Left from "@/components/Left.vue";
import Right from "@/components/Right.vue";
export default {
  name: "App",
  data() {
    return {
      comName: "Left", // 表示要展示的名字
    };
  },
  components: {
    Right,
    Left,
  },
  methods: {
    btn(num) {
      num === 1 ? (this.comName = "Left") : (this.comName = "Right");
    },
  },
};
</script>

<style lang="less" scoped>
#app {
  .title {
    height: 60px;
    line-height: 60px;
    background-color: #ccc;
    text-align: center;
    padding: 20px 0;
    margin-bottom: 10px;
  }
  .comp-box {
    display: flex;
    justify-content: space-between;
  }
}
</style>

这种就可以满足基本需求了

image.png

二.二 keep-alive对应的生命周期函数 deactivated activated

当组件被缓存时,会自动出发组件的deactivated生命周期函数

当组件被激活时,会自动出发组件的activated生命周期函数

image.png

二.三 keep-alive的两个属性

注意这两个组件是不可以同时使用的

1. include属性: 是表示哪些指定的组件可以被缓存(多个组件匹配的,以逗号分隔,但是中间不能有空格)
    -- 字符串分隔:
  <keep-alive include="a,b">
     <component :is="view"></component>
  </keep-alive>
    -- 正则 regex (使用v-bind)
    <keep-alive include="/a|b/">
     <component :is="view"></component>
  </keep-alive>
  -- Array (使用v-bind)
   <keep-alive :include="[a,b]">
     <component :is="view"></component>
  </keep-alive>
2. exclude属性:是表示哪些指定的组件不需要被缓存,用法同include
3. 注意这两个组件是不可以同时使用的
4. max属性: number|string.最多可以缓存多少组件实例,一旦达到这个数字,name缓存组件中最近没有被访问的实例会被销毁

实际截图

image.png

三. 组件的name名称:

当组件中添加了name属性的话,在做include和exclude属性匹配的时候你就不能直接用组件的名字取匹配了

image.png

三.一.总结:

1. 组件的"注册名称"的主要应用场景是:以标签的形式,把注册好的组件,渲染和使用到页面结构之中
2. 组件声明时候的"name",名称的主要应用场景:结合<keep-alive>标签实现缓存功能;一级在调试工具中看到组件的name名称
上一篇下一篇

猜你喜欢

热点阅读