美文网首页
vue侧栏组件实现

vue侧栏组件实现

作者: 会飞的大象 | 来源:发表于2020-01-09 15:24 被阅读0次

    1.效果预览:

    效果图

    2. 已实现功能:

    1. 点击顶部工具栏,打开侧栏
    2. 点击关闭按钮,关闭侧栏
    3. 点击顶部不同工具栏,切换侧栏内容
    4. 箭头指向点击位置
    5. 侧栏入场和出场动画

    3. 功能分析

    3.1 遮罩效果

    将div的背景设置成黑色,透明度0.5,并设置z-index使其可以盖在主体页面之上

    .cover {
      position: fixed;
      left: 0;
      top: 50px;
      width: 100%;
      height: 100%;
      background: #000000;
      opacity: 0.5;
      z-index: 500;
    }
    

    3.2 箭头实现

    1. 通过css画一个白色背景到三角形
    2. 通过 :style="{right:position} 控制right的位置实现其移动
    3. 通过调用"openSlider('message','130px')" 传递合适的值
     <div class="pointer">
          <div ref="triangle" class="triangle" :style="{right:position}" />
     </div>
    
    <style lang="scss" scoped>
    .pointer {
      height: 14px;
      width: 100%;
      background: transparent;
      position: relative;
    }
    
    .triangle{
        width: 0;
        height: 0;
        border: 7px solid transparent;
        border-bottom-color: #fff ;
        position: absolute;
        top: 0;
    }
    </style>
    

    3.3 动画实现

    1. 通过 <transition> 标签将需要进行动画的元素进行包裹, vue会添加如下到class
    • v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
    • v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
    • v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。
    • v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
    • v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
    • v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

    name属性定义了需要调用动画到前置,如我这里设置了name = "my",那么相应的自定义动画将前缀v改成my

    @keyframes lightSpeedIn {
      from {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
    
      to {
        transform: none;
        opacity: 1;
      }
    }
    
    .my-enter-active  {
      transform-origin: left center;
       animation: lightSpeedIn 0.4s;
    }
    
    @keyframes lightSpeedOut {
      from {
        opacity: 1;
      }
    
      to {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
    }
    
    .my-leave-active {
      transform-origin: left center;
       animation: lightSpeedOut 0.4s;
    }
    

    3.4 侧栏内容切换

    通过v-show控制当前显示的组件

    <todo v-show="openIndex === 'todo'" />
    <message v-show="openIndex === 'message'" />
    

    4.代码展示

    rightslide.vue

    <template>
      <div>
        <div v-show="openIndex" class="cover" />
    
        <transition name="my">
          <div v-show="openIndex" class="slider-container">
            <div class="pointer">
              <div ref="triangle" class="triangle" :style="{right:position}" />
            </div>
            <div class="slider-content">
              <div>
                <span @click="closeSlide">X</span>
              </div>
              <todo v-show="openIndex === 'todo'" />
              <message v-show="openIndex === 'message'" />
            </div>
          </div>
        </transition>
      </div>
    </template>
    
    <script>
    import Todo from '@/views/todo'
    import Message from '@/views/message'
    export default {
      components: {
        Todo,
        Message
      },
      data() {
        return {
          show: true
        }
      },
      computed: {
        openIndex() {
          return this.$store.state.rightSlider.openIndex
        },
        position() {
          return this.$store.state.rightSlider.trianglePosition
        }
      },
      methods: {
        closeSlide() {
          this.$store.dispatch('closeSlide')
        },
        handleClick: function() {
          this.show = !this.show
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .cover {
      position: fixed;
      left: 0;
      top: 50px;
      width: 100%;
      height: 100%;
      background: #000000;
      opacity: 0.5;
      z-index: 500;
    }
    
    .slider-container {
      width: 506px;
      height: 100%;
      top: 36px;
      right: 0px;
      position: fixed;
      z-index: 1000;
    }
    
    .slider-content {
      background: #fff;
      height: 100%;
    }
    
    .pointer {
      height: 14px;
      width: 100%;
      background: transparent;
      position: relative;
    }
    
    .triangle{
        width: 0;
        height: 0;
        border: 7px solid transparent;
        border-bottom-color: #fff ;
        position: absolute;
        top: 0;
    }
    
    @keyframes lightSpeedIn {
      from {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
    
      to {
        transform: none;
        opacity: 1;
      }
    }
    
    .my-enter-active  {
      transform-origin: left center;
       animation: lightSpeedIn 0.4s;
    }
    
    @keyframes lightSpeedOut {
      from {
        opacity: 1;
      }
    
      to {
        transform: translate3d(100%, 0, 0);
        opacity: 0;
      }
    }
    
    .my-leave-active {
      transform-origin: left center;
       animation: lightSpeedOut 0.4s;
    }
    </style>
    
    

    vuex

    const state = {
        openIndex: '', // 标识侧栏显示的组件
        trianglePosition: '' // 侧栏指向按钮距离右边到距离
    }
    
    const mutations = {
      changeIndex(state, { index, position }) {
        state.openIndex = index
        state.trianglePosition = position
      },
      closeSlide(state) {
        state.openIndex = ''
      },
      setPosition(state, position) {
        state.trianglePosition = position
      }
    }
    
    const actions = {
      changeIndex({ commit }, { index, position }) {
        commit('changeIndex', { index, position })
      },
      closeSlide({ commit }) {
        commit('closeSlide')
      },
      setPosition({ commit }, { position }) {
        commit('setPosition', position)
      }
    }
    
    export default {
      state,
      mutations,
      actions
    }
    
    

    调用:

    <template>
    <div>
      <span @click="openSlider('message','130px')">消息中心</span>
        <span @click="openSlider('todo','210px')">待办事项</span>
    </div>
    </template>
    <script>
    methods: {
    openSlider(value, position) {
          this.$store.dispatch('changeIndex', { index: value, position: position })
        }
      }
    </script>
    

    相关文章

      网友评论

          本文标题:vue侧栏组件实现

          本文链接:https://www.haomeiwen.com/subject/govrnctx.html