美文网首页
导航栏总结

导航栏总结

作者: Summerdise | 来源:发表于2021-07-01 16:11 被阅读0次

    这次所做的导航栏是为了练习components(组件)layout(布局)responsive(响应式)下拉框(collapse)

    导航栏的特点是:根据导航数据结构渲染,三层目录不定量选项卡,web端与mobile端自适应变化,mobile端导航栏特殊设计。

    重点学习的技术包含:组件获取数据的方法和不定项的渲染方法,响应式布局动画设计手风琴导航栏

    组件数据获取和渲染

    • 组件数据获取

    目前项目broading阶段,使用的数据是与后端沟通后的mock数据。组件获取数据的方法是创建时fetch获取,利用cms提供的获取方法,返回具体的Navigation数据。

      async fetch(): Promise<void> {
        this.navigationList = (await getNavigations()).data
      },
    
    • 内层组件数据获取

    在需要不定项获取时,利用v-for中传入列表数据来实现。通常列表中需要重新定义格式时,就在每一行li中加入一个代入数据的新的组件。

    <ul class="navbar-nav">
       <li v-for="item in navigationList.navigation" :key="item.id" class="alert-second-nav pl-5 nav-item active">
            <a :href="item.link.href" class="nav-link text-black-50">{{ item.link.label }}</a>
            <DropDown class="second-nav border-top border-bottom border-dark-50" :data="item.sections" />
            <div class="mask-bg w-100 h-100 m-0 p-0"></div>
        </li>
    </ul>
    

    其中DropDown就是新组件用于接收数据。

    具体的接收方法为:

    props: {
        data: {
          type: Array as PropType<NaviSectionEntity[]>,
          default(): NaviSectionEntity[] {
            return [] as NaviSectionEntity[]
          },
        },
      },
    
    • 数据渲染

    数据得到后的渲染中主要就是直接使用$props原型数据。

    特殊的需要注意,区分data数据与$props.data的区别。data数据可以方便的随时更改再获取,但原型不能更改。

    响应式布局

    这里说到的响应式主要是web端和mobile端的区别。

    响应式最重要的几个内容是1.不同端的具体布局2.屏幕大小的监听3.不同端内容的控制。

    • 屏幕大小的监听
    mounted() {
        window.onresize = () => {
          // 监听屏幕变化
          this.page_width()
        }
        this.page_width()
      }
    

    监听后对屏幕大小做一个规定,判定mobile端与web端的屏幕大小分界,根据分解转化为一个bool值。

    page_width() {
          // 获取屏幕宽度
          const screenWidth = document.body.clientWidth
          this.fullWidth = screenWidth >= 1000
        }
    
    • 内容显示的控制

    在不同端的布局上都加上v-show这个标签属性,该属性用于控制这个标签的内容是否显示。用屏幕的bool值来控制内容是否显示。

    <div v-show="fullWidth" id="navbarSupportedContent" class="collapse navbar-collapse">
      <ul class="navbar-nav">
      </ul>
    </div>
    

    特殊的:项目中移动端还会出现点击出现或显示的功能。

    <div v-show="!fullWidth && !disMenu" class="collapse navbar-collapse mobile-menu-open">
            <ul class="navbar-nav">
      </ul>
    </div>
    

    动画设计

    项目中暂时用到的动画设计只有从右边划入,向右边划出这种。

    设计方案就是针对需要使用动画的div外包裹一层transition标签。

    <transition name="mobile-menu-slide-fade">
      <div>
      </div>
    </transition>
    

    具体设计这个动画transition时,即在style中对该nameenter,leave属性进行修改。

    .mobile-menu-slide-fade-enter-active {
      transition: all 0.5s ease;
    }
    
    .mobile-menu-slide-fade-leave-active {
      transition: all 0.3s cubic-bezier(1, 0.5, 0.8, 1);
    }
    
    .mobile-menu-slide-fade-enter,
    .mobile-menu-slide-fade-leave-to {
      transform: translateX(300px);
      opacity: 0;
    }
    

    手风琴导航栏

    手风琴指的是列表中点击一行时,行内的下级列表内容全部显示,此时点击另一行时,会把之前全部内容隐藏,显示当前行下的下级列表内容。

    项目中用到的手风琴导航栏主要是在移动端的第二层菜单时,希望不再继续往下跳转。

    具体实现时的难点是:数据的传递和显示与隐藏的控制。

    数据传递和控制上需要注意的是v-for是可以获得index值的,通过index的值可以完成对具体某一行内容的操作与获取。

    具体的控制方法有两种实现:

    1. 对每一项数据内容中加入一个是否显示的字段,该字段中保证在一组同级数据下仅有一个true,代表为显示,每次点击事件发生时都会判断全部内容下的该字段,保证字段准确性。
    2. 在全局data中添加一个showIndex字段,初始值为-1,用于记录当前可以显示的某行,如果为-1则为都不显示。每次点击事件发生时都对showIndex字段进行更新。

    本项目因为原数据已经确定,所以使用的第二种实现方法。

    <template>
      <div>
        <ul class="list-unstyled">
          <li v-for="(item, index) in $props.data" :key="item.id" :class="[{ active: isShowing(index) }]">
            <div class="nav-link text-black-50">
              <p class="mb-0" @click="changeShowingIndex(index)">{{ item.title }}</p>
            </div>
            <ul v-show="isShowing(index)" class="list-unstyled pl-3">
              <li v-for="subItem in item.links" :key="subItem.id">
                <div class="nav-link text-black-50">
                  <p class="mb-0">{{ subItem.label }}</p>
                </div>
              </li>
            </ul>
          </li>
        </ul>
      </div>
    </template>
    
    <script lang="ts">
    import Vue, { PropType } from 'vue'
    import { NaviSectionEntity } from '~/apis/cms'
    
    type NaviData = {
      showingIndex: number
    }
    
    export default Vue.extend({
      name: 'MobileSecondNavi',
      props: {
        data: {
          type: Array as PropType<NaviSectionEntity[]>,
          default(): NaviSectionEntity[] {
            return [] as NaviSectionEntity[]
          },
        },
      },
      data(): NaviData {
        return {
          showingIndex: -1,
        }
      },
      methods: {
        changeShowingIndex(index) {
          if (this.showingIndex === index) {
            this.showingIndex = -1
          } else {
            this.showingIndex = index
          }
        },
        isShowing(index) {
          return this.showingIndex === index
        },
      },
    })
    </script>
    

    相关文章

      网友评论

          本文标题:导航栏总结

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