Vue.js 实战系列之实现视频类WebApp的项目开发——3. 底部状态栏TabBar的实现(实现原生APP底部导航栏)

如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发。

项目仓库地址,欢迎 Star


实现效果

在这里插入图片描述


模块开发

  1. 路由配置

    当我们在创建一个复杂应用的时候,最开始应该做的不是具体业务功能,而是先捋顺整个应用的结构和思路,从路由入手就是一个很好的选择。

    根据项目需求得知,该 WebApp 底部有5个 TabBar 组成,所以我们需要构建5个页面,分别是首页、朋友、发布、消息、我的。而且底部 TabBar 在每个页面都有,所以我的做法是创建一个根页面,在这个页面通过子路由的方式加载各个主页。

    修改 router/index.js 文件进行路由配置:

    import Vue from 'vue';
    import VueRouter from 'vue-router';
    import Home from '../views/Home.vue';
    
    Vue.use(VueRouter);
    
    const routes = [
      {
           
        path: '/',
        redirect: 'index',
      },
      {
           
        path: '/',
        name: 'Home',
        component: Home,
        children: [
          {
           
            path: '/index',
            name: 'index',
            component: () => import(/* webpackChunkName: "index" */ '../views/index/index.vue'),
          },
          {
           
            path: '/friends',
            name: 'friends',
            component: () => import(/* webpackChunkName: "friends" */ '../views/friends/index.vue'),
          },
          {
           
            path: '/news',
            name: 'news',
            component: () => import(/* webpackChunkName: "news" */ '../views/news/index.vue'),
          },
          {
           
            path: '/mine',
            name: 'mine',
            component: () => import(/* webpackChunkName: "mine" */ '../views/mine/index.vue'),
          },
        ],
      },
      {
           
        path: '/release',
        name: 'release',
        component: () => import(/* webpackChunkName: "release" */ '../views/release/index.vue'),
      },
    ];
    
    const router = new VueRouter({
           
      mode: 'history',
      base: process.env.BASE_URL,
      routes,
    });
    
    export default router;
    

    路由配置解释:

    1. 查看上面的路由配置可知:发布页面的路由并没有添加到主页的子路由中,这是因为发布页面不需要展示底部 TabBar 组件。
    2. 路由采用懒加载的方式引入
    3. 引入路由时有: /* webpackChunkName: "index" */,这个的作用就是修改打包之后的js文件名。
    4. 为什么使用嵌套路由?
      很多时候我们的页面结构决定了我们可能需要嵌套路由,比如我们的当前项目,在进入主页之后有多个功能页面,然后当选择其中一个功能页面之后进入对应的页面,这个时候我们就可以用到嵌套路由。
      官方文档中给我们提供了一个 children 属性,这个属性是一个数组类型,里面实际放着一组路由;这个时候父子关系结构就出来了,所以 children 属性里面的是路由相对来说是 children 属性外部路由的子路由。
    5. 注意:以上路由配置的页面需提前创建好,否则会有报错。
  2. 底部导航栏TabBar实现

    新建 Tabbar.vue 组件文件:

    common/components/tab/Tabbar.vue

    <template>
      <div class="tab-bar">
        <div class="item" @click="changTab(0)">
          <router-link to="/index" tag="span" :class="tabIndex === 0 ? 'active' : ''">首页</router-link>
        </div>
        <div class="item" @click="changTab(1)">
          <router-link to="/friends" tag="span" :class="tabIndex === 1 ? 'active' : ''">朋友</router-link>
        </div>
        <div @click="changTab(0)">
          <router-link to="/release" tag="span">
            <img class="dy-btn" src="@/assets/images/dy-btn.png" alt="" />
          </router-link>
        </div>
        <div class="item" @click="changTab(3)">
          <router-link to="/news" tag="span" :class="tabIndex === 3 ? 'active' : ''">消息</router-link>
        </div>
        <div class="item" @click="changTab(4)">
          <router-link to="/mine" tag="span" :class="tabIndex === 4 ? 'active' : ''">我的</router-link>
        </div>
      </div>
    </template>
    
    <script>
    export default {
           
      name: 'Tabbar',
      data() {
           
        return {
           
          tabIndex: 0,
        };
      },
    
      methods: {
           
        changTab(i) {
           
          this.tabIndex = i;
        },
      },
    };
    </script>
    
    <style lang="less" scoped>
    .tab-bar {
           
      background: #000000;
      height: 50px;
      width: 100%;
      line-height: 50px;
      position: fixed;
      bottom: 0;
      left: 0;
      display: flex;
      justify-content: space-around;
      color: #cccccc;
      font-size: 16px;
      .item {
           
        flex: 1;
        text-align: center;
        font-weight: 500;
      }
      .active {
           
        color: #ffff;
        font-weight: 600;
      }
      .dy-btn {
           
        width: 50px;
        height: 30px;
        margin: 10px;
      }
    }
    </style>
    
  3. 封装TabBar组件

    我们将上面的 Tabbar 组件进行拆分,使他变成一个复用性更高的组件。

    先对 Tabbar 进行拆分,拆分成 TabBar 和 TabItem 两部分:
    Vue.js 实战系列之实现视频类WebApp的项目开发——3. 底部状态栏TabBar的实现(实现原生APP底部导航栏)_第1张图片

    1. TabItem:作为 TabBar 的单个 tab,可以实现较高的复用性。

      组件封装主要利用了 vue 的两个属性:
      props: 接收父组件给子组件的传值;
      computed:计算属性(当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值)

      <template>
        <div class="item" @click="itemClick">
          <router-link
            :to="navPath"
            tag="span"
            :class="isActive ? 'active' : ''"
          >
            {
               {
                tabTitle }}
            <slot></slot>
          </router-link>
        </div>
      </template>
      
      <script>
      export default {
               
          props: {
               
              tabTitle: {
               
                  type: String,
                  default: '',
              },
              navPath: {
               
                  type: String,
                  default: '/index',
              },
          },
          computed: {
               
              isActive() {
               
                  return this.$route.path === this.navPath;
              },
          },
          methods: {
               
              itemClick() {
               
                  console.log(this.$route.path);
              },
          },
      };
      </script>
      
      <style lang="less" scoped>
      .item {
               
        flex: 1;
        text-align: center;
        font-weight: 500;
      }
      .active {
               
        color: #ffff;
        font-weight: 600;
      }
      </style>
      
    2. TabBar :作为 TabItem 的父组件,对其进行使用。

      <template>
        <div class="tab-bar">
          <TabItem tab-title="首页" nav-path="/index"></TabItem>
          <TabItem tab-title="朋友" nav-path="/friends"></TabItem>
          <TabItem nav-path="/release">
            <img class="dy-btn" src="@/assets/images/dy-btn.png" alt="" />
          </TabItem>
          <TabItem tab-title="消息" nav-path="/news"></TabItem>
          <TabItem tab-title="我的" nav-path="/mine"></TabItem>
        </div>
      </template>
      
      <script>
      import TabItem from './TabItem.vue';
      
      export default {
               
        name: 'Tabbar',
        components: {
               
          TabItem,
        },
      };
      </script>
      
      <style lang="less" scoped>
      .tab-bar {
               
        background: #000000;
        height: 50px;
        width: 100%;
        line-height: 50px;
        position: fixed;
        bottom: 0;
        left: 0;
        display: flex;
        justify-content: space-around;
        color: #cccccc;
        font-size: 16px;
        .dy-btn {
               
          width: 50px;
          height: 30px;
          margin: 10px;
        }
      }
      </style>
      

问题记录

注意:由于我们使用了 Eslint 进行规范检查,所以在项目开发过程中一定要注意代码规范,下面我注意总结了在开发过程中会碰到的几个代码规范问题。

  1. Eslint 检测报错 error Expected linebreaks to be 'LF' but found 'CRLF' linebreak-style

    原因:
    项目代码做了 eslint 的规范检查,规定了换行需要以Lunix系统的换行方式,Linux下只有换行LF,而在 window 下换行默认是 CRLF。

    解决方案:
    .eslintrc 文件 rules 里面 配置 "linebreak-style": ["error", "windows"] 或者 linebreak-style': ["off", "windows"], 允许windows开发环境,记得重启项目。

  2. Eslint 提示 Newline required at end of file but not found

    原因:
    根据报错的字面意思就是文件的末尾需要有空的一行。

    解决方案:
    在最后加上一行空白就可以了。

  3. Eslint 提示 Trailing spaces not allowed no-trailing-spaces

    原因:
    空格多了,需删除多余空格。

    解决方案:
    删除多余的空格就可以了。


总结

  1. 本章节主要对底部状态栏TabBar进行组件开发,以及设置对应的路由配置。

  2. 对比模块开发中的第二、三部分 对TabBar实现 和 封装组件化处理,可以清晰的看出,使用组件化进行项目开发,可以简化代码以及提高代码的复用性,所以我们在项目开发中,应该尽可能的使用组件化进行开发。

  3. 总是提示错误,我们为什么还需要用 Eslint?

    在开始写这部分代码之前,一直没有注意到使用 Eslint 来进行代码规范,在后面的代码开发过程中,开始逐渐意识到代码规范的重要性,养成一个良好的代码规范可以让我们的代码减少不必要的错误。

    在团队协作时,良好的代码规范显得格外重要,因为这是保障一个团队代码风格相同、避免低级bug的途径之一。

    使用 EsLint 工具和代码风格检测工具,可以辅助编码规范执行,有效控制代码质量。

    关于 Eslint 具体的使用方法,请大家自行查阅。


上一章节: 2. 搭建项目基本骨架

下一章节: 4. 顶部导航条实现

项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)


项目仓库地址,欢迎 Star。

有任何问题欢迎评论区留言讨论。

你可能感兴趣的:(Vue,实战系列,vue,javascript,vue.js,node.js)