第五节:插槽2-具名插槽特点与应用

167 阅读1分钟

具名slot

  • 用于有多个插槽,区分占位用的
    • 写法: 父组件一般用 template标签包裹,添加v-slot:age -> 缩写 #age
      • 默认插槽 其实也是 v-slot:default
    • 子组件预留的插槽: "<slot name="age"></slot>"
      • 这里可以写多个slot
<template>
  <div class="home">
    <my-button 
      @click="changeStatus"
      :disabled="isLoading"
      :loading-icon="true"
      :is-loading="isLoading"
    >
      <template #btn>
        {{ isLoading ? 'Loading...' : 'Click' }}
      </template>
    </my-button>
  </div>
</template>

<script>
import MyButton from "./MyButton.vue"
export default {
  name: 'Home',
  components: {
    MyButton
  },
  data() {
    return {
      isLoading: false
    }
  },
  methods: {
    changeStatus() {
      this.isLoading = true;
      setTimeout(() => {
        this.isLoading = false;
      }, 3000);
    }
  }
}
</script>
<template>
  <button type="button" @click="changeStatus">
    <my-icon :loading-icon="loadingIcon" :is-loading="isLoading"/>
    <slot name="btn"></slot>
  </button>
</template>

<script>
import MyIcon from "./MyIcon.vue";
export default {
  name: 'MyUiMybutton',
  components: {
    MyIcon
  },
  props: {
    loadingIcon: {
      type: Boolean
    },
    isLoading: {
      type: Boolean
    }
  },
  methods: {
    changeStatus() {
      this.$emit('click')
    }
  }
};
</script>
<template>
  <span v-if="loadingIcon && isLoading" class="fa fa-spinner fa-spin"></span>
</template>

<script>
export default {
  name: 'MyUiMyicon',
  props: {
    loadingIcon: {
      type: Boolean
    },
    isLoading: {
      type: Boolean
    }
  }
};
</script>

点击之前

image.png 点击之后

image.png

后台管理系统的布局

  • BaseLayout -> 基本布局
    • BaseHeader -> slot -> baseHeader
    • BaseFooter -> slot -> baseFooter
    • BaseSideBar -> slot -> baseSideBar
    • BaseMain -> slot -> baseMain
<template>
  <div class="home">
    <base-layout>
      <template #baseHeader>
        <h1 style="color: seashell;line-height: 60px;margin: 0;">LOGO</h1>
      </template>
      <template #baseFooter>
        <div style="text-align: center;line-height: 60px;">
          这是一个页脚-蒋小白
        </div>
      </template>
      <template #base-sidebar>
        <ul>
          <li>百度</li>
          <li>谷歌</li>
          <li>腾讯</li>
        </ul>
      </template>
      <template>
        <div>这是主内容区</div>
      </template>
    </base-layout>
  </div>
</template>

<script>
import BaseLayout from './components/BaseLayout/index.vue'
export default {
  name: 'Home',
  components: {
    BaseLayout
  }
}
</script>

<style scoped>
ul, li {
  margin: 0;
  padding: 0;
  list-style: none;
  text-align: center;
}
li {
  height: 50px;
  line-height: 50px;
  letter-spacing: 2px;
  color: aliceblue;
  cursor: pointer;
}
</style>
<template>
  <div class="container">
    <header class="base-header">
      <slot name="baseHeader">
        HEADER
      </slot>
    </header>
    <footer class="base-footer">
      <slot name="baseFooter">FOOTER</slot>  
    </footer>
    <aside class="base-sidebar">
      <slot name="base-sidebar">SIDEBAR</slot>
    </aside>
    <main class="base-main">
      <slot>Main</slot>
    </main>
  </div>
</template>

<script>
export default {
  name: 'BaseLayout',

  data() {
    return {
      
    };
  },
  methods: {
    
  },
};
</script>

<style scoped>
html,
body {
  margin: 0;
}
.base-header,
.base-footer,
.base-sidebar,
.base-main
{
  position: fixed;
  left: 0;
}

.base-header {
  width: 100%;
  top: 0;
  height: 60px;
  background: #000;
  z-index: 2;
}

.base-footer {
  bottom: 0;
  width: 100%;
  height: 60px;
  background: #ddd;
  z-index: 2;
}

.base-sidebar {
  top: 0;
  width: 200px;
  height: 100%;
  padding: 90px 30px;
  background: rebeccapurple;
  box-sizing: border-box;
  z-index: 1;
}

.base-main {
  top: 0;
  width: 100%;
  height: 100%;
  padding: 90px 30px 90px 230px;
  background-color: orange;
}
</style>

image.png