使用provide 与 inject实现aside切换

88 阅读1分钟

使用provide 与 inject实现aside切换

1.在app中定义一个变量menuVisible,用provide标记为所有后代都可以使用

<template>
  <router-view/>
</template>

<script lang="ts">
import { ref, provide } from 'vue'
export default {
    name: 'App',
    setup(){
        const menuVisible = ref(false)
        provide('xxx',menuVisible) // set
        // 标记为所有组件可以使用
    }
}
</script>

接下来
(2个子组件去获取,分别用topnav获取'xxx',doc获取'xxx')
2.topnav中inject

<template>
    <div>
        <div class="topnav">
            <div class="logo" @click="toggleMenu">LOGO</div>
            <ul class="menu">
                <li>菜单1</li>
                <li>菜单2</li>
            </ul>
        </div>
    </div>
</template>
<script lang="ts">
import { inject, Ref } from 'vue'
export default {
    setup(){
        const menuVisible = inject<Ref<boolean>>('xxx') // get 这里用inject获取
        console.log('topnav 获取的menuVisible为:'+ menuVisible.value);
        const toggleMenu = () => {
            menuVisible.value = !menuVisible.value  // 当用户点击logo时,toggleMenu获取相反的逻辑值,这个也会致使doc中的v-if的menuVisible改变,menuVisible一变,视图展示的就是显示隐藏
        }
        return {toggleMenu}
    }
}
</script>
<style lang="scss" scoped>
.topnav{
    background: pink;
    display: flex;
    padding: 16px;
    position: relative; // 解决logo遮挡
    z-index: 10; // 解决logo遮挡
    > .logo {
        max-width: 6em;
        margin-right: auto;
    }
    > .menu {
        display: flex;
        white-space: nowrap;
        flex-wrap: nowrap;
        > li {
            margin: 0 1em;
        }
    }
}
</style>
  1. doc组件中inject 使用v-if控制显示隐藏
<template>
    <div>
        <Topnav />
        <div class="content">
            <aside v-if="menuVisible">
                <h2>组件列表</h2>
                <ol>
                    <li>
                        <router-link to="/doc/switch">Switch 组件</router-link>
                    </li>
                    <li>
                        <router-link to="/doc/button">Button 组件</router-link>
                    </li>
                    <li>
                        <router-link to="/doc/dialog">Dialog 组件</router-link>
                    </li>
                    <li>
                        <router-link to="/doc/tabs">Tab 组件</router-link>
                    </li>
                </ol>
            </aside>
            <main>主内容</main>
        </div>

    </div>
</template>
<script lang="ts">
import { inject, Ref } from 'vue'
import Topnav from '../components/Topnav.vue'
export default {
    components: {Topnav},
    setup(){
        const menuVisible = inject<Ref<boolean>>('xxx')
        console.log('Doc aside 获取的menuVisible为:'+ menuVisible.value);
        return {menuVisible}
    }
}
</script>
<style lang="scss" scoped>
aside {
  background: lightblue;
  width: 150px;
  padding: 16px;
  position: fixed;
  top: 0;
  left: 0;
  padding-top: 70px; // 解决蓝色部分遮挡
//   height: 100%; 
  > h2 {
    margin-bottom: 4px;
  }
  > ol {
    > li {
      padding: 4px 0;
    }
  }
}
</style>

点击logo之前 image.png 点击logo之后 image.png