从零开始的移动商城(2)

文举
• 阅读 1716

前言

本章只介绍添加 tabbar 页面。

新建 tab 页

在 views 目录下创建几个 tab 页:

从零开始的移动商城(2)

添加路由

tabbar

在 router 目录创建 tabbar.js:

从零开始的移动商城(2)

内容如下:

const Home = () => import(/* webpackChunkName: "index" */ "@/views/index/index.vue");
const Category = () => import(/* webpackChunkName: "index" */ "@/views/category/category.vue");
const Cart = () => import(/* webpackChunkName: "index" */ "@/views/cart/cart.vue");
const User = () => import(/* webpackChunkName: "index" */ "@/views/user/user.vue");

const tabbar = [
    {
        path: "/",
        name: "home",
        component: Home,
        meta: {
            title: "精选",
            tabbar: true,
            icon: "home-o",
            tabName: "精选",
            index: 1
        }
    },
    {
        name: "category",
        path: "/category",
        component: Category,
        meta: {
            title: "分类",
            tabbar: true,
            icon: "bag-o",
            tabName: "分类",
            index: 2
        }
    },
    {
        name: "cart",
        path: "/cart",
        component: Cart,
        meta: {
            title: "购物车",
            tabbar: true,
            icon: "cart-o",
            tabName: "购物车",
            index: 3
        }
    },
    {
        name: "user",
        path: "/user",
        component: User,
        meta: {
            title: "个人中心",
            tabbar: true,
            icon: "user-o",
            tabName: "我",
            index: 4
        }
    }
];


export default tabbar;

其中:

webpackChunkName:会将名字相同的打包到一起
tabbar:路由数组,其中

1、name:路由的名字
2、path:路由的 history 路径,即 url
3、component:组件,使用的模板页面
4、meta:自定义数据,这里 title 后续用来修改浏览器标题,tabbar,用来区分是否是 tabbar 页,icon 和 tabName 和 index 用来辅助展示 tabbar

index

修改 router 下的 index.js,为路由的入口配置,引入 tabbar.js,详细内容如下:

import Vue from "vue";
import VueRouter from "vue-router";
import Tabbar from "./tabbar.js";

Vue.use(VueRouter);

const routes = [
  ...Tabbar
];

/**如果路径不存在,就按照/ + name 驼峰转斜杠,来填充 */
routes.forEach(route => {
  route.path = route.path || "/" + (route.name.replace(/([A-Z])/g, "/$1").toLowerCase() || "");
});

const router = new VueRouter({
  mode: "history",
  base: process.env.BASE_URL,
  routes
});

/**路由进入前回调 */
router.beforeEach((to, from, next) => {
  // 修改浏览器页面标题
  const title = to.meta && to.meta.title;
  if (title) {
    document.title = title;
  }
  next();
});

export default router;

修改容器页面

修改 public 目录下的 index.html,修改 viewport,如果没有就添加:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no,viewport-fit=cover">
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no,viewport-fit=cover">
    <link rel="icon" href="<%= BASE_URL %>favicon.png">
    <title>微商城</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but wxshop doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

其中 width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no 是初始化页面缩放大小,并禁止用户对页面缩放,后面那个 viewport-fit=cover 是辅助 ios 安全距离使用的:

从零开始的移动商城(2)

修改入口 App

这才是真正的添加 tabbar,修改 App.vue:

<template>
  <div id="app">
    <!-- 内容 -->
    <transition :name="transitionName" mode="out-in" >
      <!-- keep-alive 标签会缓存页面,缓存所有模板名称以KeepAlive结尾的页面或组件 -->
      <keep-alive :include="/KeepAlive$/">
        <router-view />
      </keep-alive>
    </transition>
    <!-- tabbar -->
    <van-tabbar route safe-area-inset-bottom>
      <van-tabbar-item
        v-for="(tab, index) in tabbar"
        :key="index"
        :to="tab.path"
        :icon="tab.meta.icon"
      >{{tab.meta.tabName}}</van-tabbar-item>
    </van-tabbar>
  </div>
</template>

<script>
import { Tabbar, TabbarItem } from "vant";
import TabbarRoute from "@/router/tabbar.js";
export default {
  name: "App",
  components: {
    [Tabbar.name]: Tabbar,
    [TabbarItem.name]: TabbarItem
  },
  data() {
    return {
      transitionName: "fade",
      tabbar: TabbarRoute
    };
  },

  watch: {
    $route(to, from) {
      if (from.name) {
        /**不是初始页面 */
        if (to.meta.tabbar) {
          const toDepth = to.meta.index;
          const fromDepth = from.meta.index;
          this.transitionName =
            toDepth < fromDepth ? "slide-right" : "slide-left";
        } else {
          const toDepth = to.path.split("/").length;
          const fromDepth = from.path.split("/").length;
          this.transitionName =
            toDepth < fromDepth ? "slide-right" : "slide-left";
        }
      } else {
        /**初始页面,from.name一定没有值 */
        this.transitionName = "fade";
      }
    }
  }
};
</script>

<style lang="scss">
html,
body,
#app {
  background: #ededed;
  height: 100%;
  margin: 0;
  padding: 0;
}
html,
body,
div,
p,
ul,
li,
img,
h1,
h2,
h3,
h4,
h5,
h6 {
  box-sizing: border-box;
}
img {
  max-width: 100%;
  display: inline-block;
}
</style>

<style>
/* 切换动画 */
.slide-right-leave-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-left-enter-active {
  transition: all 0.3s;
}

.slide-right-enter {
  opacity: 1;
  transform: translateX(-100%);
}
.slide-right-leave-to {
  opacity: 0;
  transform: translateX(100%);
}
.slide-left-enter {
  opacity: 1;
  transform: translateX(100%);
}
.slide-left-leave-to {
  opacity: 0;
  transform: translateX(-100%);
}

.fade-leave-active,
.fade-enter-active {
  transition: opacity 0.2s;
}
.fade-enter,.fade-leave-to{
  opacity: 0;
}
</style>

其中:
1、keep-alive 缓存页面作用,一个商品列表,滑动三页,打开一个商品详情,点击返回,能否回到第三页浏览的位置?,如果列表页面加了缓存,会回到原来的位置,否则就会重新加载页面。
3、tabbar 使用 vant 的组件,route 属性表示根据路由改变 tabbar,safe-area-inset-bottom 属性表示开启 ios 的安全距离(需要viewport-fit=cover才起作用)。
4、transition 动画,用来使页面产生过度效果。
5、watch 监听路由变化,用来确定使用的过度动画,这里设计了三种动画,fade、slide-right、slide-left。
6、添加动画样式

测试

在管理后台点击运行启动:

从零开始的移动商城(2)

点击切换是否有特效,我这边是有的,测试成功。

调整 tabbar

将 App.vue 中 tabbar 改为组件,在 components 文件夹下新建 tabbar.vue 组件,内容如下:

从零开始的移动商城(2)

代码:

  <van-tabbar route safe-area-inset-bottom>
      <van-tabbar-item
        v-for="(tab, index) in tabbar"
        :key="index"
        :to="tab.path"
        :icon="tab.meta.icon"
      >{{tab.meta.tabName}}</van-tabbar-item>
    </van-tabbar>
</template>

<script>
import { Tabbar, TabbarItem } from "vant";
import TabbarRoute from "@/router/tabbar.js";
export default {
  name: "tabbar",
  components: {
    [Tabbar.name]: Tabbar,
    [TabbarItem.name]: TabbarItem
  },
  data(){
    return {
      tabbar: TabbarRoute
    }
  }
};
</script>

修改 tabbar 路由:

从零开始的移动商城(2)

代码:

const Home = () => import(/* webpackChunkName: "index" */ "@/views/index/index.vue");
const Category = () => import(/* webpackChunkName: "index" */ "@/views/category/category.vue");
const Cart = () => import(/* webpackChunkName: "index" */ "@/views/cart/cart.vue");
const User = () => import(/* webpackChunkName: "index" */ "@/views/user/user.vue");
const Tabbar = () => import(/* webpackChunkName: "index" */ "@/components/tabbar.vue");

const tabbar = [
    {
        path: "/",
        name: "home",
        components: {
            default: Home,
            tabbar: Tabbar
        },
        meta: {
            title: "精选",
            tabbar: true,
            icon: "home-o",
            tabName: "精选",
            index: 1
        }
    },
    {
        name: "category",
        path: "/category",
        components: {
            default: Category,
            tabbar: Tabbar
        },
        meta: {
            title: "分类",
            tabbar: true,
            icon: "bag-o",
            tabName: "分类",
            index: 2
        }
    },
    {
        name: "cart",
        path: "/cart",
        components: {
            default: Cart,
            tabbar: Tabbar
        },
        meta: {
            title: "购物车",
            tabbar: true,
            icon: "cart-o",
            tabName: "购物车",
            index: 3
        }
    },
    {
        name: "user",
        path: "/user",
        components: {
            default: User,
            tabbar: Tabbar
        },
        meta: {
            title: "个人中心",
            tabbar: true,
            icon: "user-o",
            tabName: "我",
            index: 4
        }
    }
];


export default tabbar;

修改 App.vue:

从零开始的移动商城(2)

代码:

<template>
  <div id="app">
    <!-- 内容 -->
    <transition :name="transitionName" mode="out-in">
      <!-- keep-alive 标签会缓存页面,缓存所有模板名称以KeepAlive结尾的页面或组件 -->
      <keep-alive :include="/KeepAlive$/">
        <router-view />
      </keep-alive>
    </transition>
    <!-- tabbar -->
    <keep-alive>
      <router-view name="tabbar" />
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      transitionName: "fade"
    };
  },

  watch: {
    $route(to, from) {
      if (from.name) {
        /**不是初始页面 */
        if (to.meta.tabbar) {
          const toDepth = to.meta.index;
          const fromDepth = from.meta.index;
          this.transitionName =
            toDepth < fromDepth ? "slide-right" : "slide-left";
        } else {
          const toDepth = to.path.split("/").length;
          const fromDepth = from.path.split("/").length;
          this.transitionName =
            toDepth < fromDepth ? "slide-right" : "slide-left";
        }
      } else {
        /**初始页面,from.name一定没有值 */
        this.transitionName = "fade";
      }
    }
  }
};
</script>

<style lang="scss">
html,
body,
#app {
  background: #ededed;
  height: 100%;
  margin: 0;
  padding: 0;
  position: relative;
}
html,
body,
div,
p,
ul,
li,
img,
h1,
h2,
h3,
h4,
h5,
h6 {
  box-sizing: border-box;
}
img {
  max-width: 100%;
  display: inline-block;
}
.line1 {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  word-break: break-all;
}
.line2 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}
.line3 {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
</style>

<style>
/* 切换动画 */
.slide-right-leave-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-left-enter-active {
  transition: all 0.3s;
}

.slide-right-enter {
  opacity: 1;
  transform: translateX(-100%);
}
.slide-right-leave-to {
  opacity: 0;
  transform: translateX(100%);
}
.slide-left-enter {
  opacity: 1;
  transform: translateX(100%);
}
.slide-left-leave-to {
  opacity: 0;
  transform: translateX(-100%);
}

.fade-leave-active,
.fade-enter-active {
  transition: opacity 0.2s;
}
.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>

router-view 组件指定渲染的路由组件名称,详细说明查看官网文档

点赞
收藏
评论区
推荐文章
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
4年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Easter79 Easter79
4年前
sql注入
反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o
Easter79 Easter79
4年前
Vue+ElementUI 导航组件
创建导航页组件在components目录下新建一个navigation目录,在Navi目录中新建一个名为Navi.vue的组件。至此我们的目录应该是如下图所示: !(https://img2018.cnblogs.com/blog/1213900/201909/121390020190911165808209545381725
梦
4年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Wesley13 Wesley13
4年前
APP自动化测试,判断页面与预期是否相同
自动化测试中,有时需要验证页面跳转是否正常1、选择appium实现,因为要填写appPcakage和appActivity,只能验证一个单独的APP,在自身APP上各个页面是否跳转正常例如:焦点从APP中的【智能音箱】TAB移动到【历史】TAB后,可以通过try去判断“历史”页面是否存在应有的元素,若抛出异常说明跳转没有成功!(https:/
Wesley13 Wesley13
4年前
H5调取APP或跳转至下载
来源:  最近在配合移动端做几个详情页h5分享页面,需要调取App并跳转至app详情页,如果没有安装App,需要判断引导至下载页面。参考文档:https://juejin.im/post/5b7efb2ee51d45388b6af96c(https://www.oschina.net/action/GoToLink?u
Wesley13 Wesley13
4年前
Oracle中如何查询一个表的所有字段名和数据类型
Oracle中如何查询一个表的所有字段名和数据类型查询语法selectA.COLUMN_NAME,A.DATA_TYPEfromuser_tab_columnsAwhereTABLE_NAME'表名'查询例子selectA.COLUMN_NAME,A.DATA_TYPEfromuser_tab_
Wesley13 Wesley13
4年前
55 同一浏览器session会串的问题
E6是每新开一个窗口一个session,基本一定不会串IE7是同一个窗口里面多个Tab页共享一个Session,同窗口的会串IE8是所有窗口所有标签Tab页共享一个session,除非是用那个文件菜单新开会话打开窗口则独立sessionFireFox和Chrome则缺省就是所有窗口所有Tab共享一个S
Stella981 Stella981
4年前
Linux下的快捷键整理
20191026   00:37:25今天上网整理了相关资料,希望对大家有用:1.关于终端的快捷键:Tab:tab键是比较常用的一个快捷键,它的作用是补全文件名或者路径。举例来说,输入”cd /ho”在按一下tab键,终端里就会显示”cd /home”了。如果您的文件夹下,有两个名字开头部分相同的文件,比如