Vue(小码哥王洪元)笔记07路由案例tabbar
1、tabbar案例01
进行了简单的布局
- 1、创建一个样式文件base.css
body{margin:0; padding: 0;}
- 2、修改App.vue
<template><div id="app"><div id="tab-bar"><div class="tab-bar-item">首页</div><div class="tab-bar-item">分类</div><div class="tab-bar-item">购物车</div><div class="tab-bar-item">我的</div></div></div>
</template><script>
export default {name: 'App',}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
#tab-bar{display: flex; background-color: #f6f6f6; position: fixed; left:0; right: 0; bottom: 0; box-shadow: 0 -1px 1px rgba(100,100,100,0.3);}
.tab-bar-item{flex: 1; text-align: center; height: 49px;}
</style>
2、tabbar案例02
这一讲主要是对组件各种封装和嵌套,其中嵌套使用插槽的方式进行多重嵌套
模板层面(从大到小层面)
App.vue—>TabBar.vue—>TabBarItem
代码层面层面(从小到大层面)
TabBarItem.vue—>TabBar.vue—>App.vue
1、TabBarItem.vue
在tab-bar-item放入两个具名插槽(包含name属性)<slot name=“item-icon”>和<slot name=“item-text”>
<template><div class="tab-bar-item"><slot name="item-icon"></slot><slot name="item-text"></slot></div>
</template>
2、TabBar.vue
在TabBar中放入一个不具名插槽
<template><div id="tab-bar"><slot></slot></div>
</template>
2、App.vue
在最上层的模板中匹配所有插槽,注意,嵌套的div标签名是跟随id和class来的
<template><div id="app"><tab-bar><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar></div>
</template>
1、拷贝各种资源图标
将资源图标放在assets文件夹下的相关目录中2、创建最底层的组件页面TabBarItem.vue
在页面中同时设计插槽内插入标签的样式(实际插槽内的具体div标签都是写好的,等最顶层App.vue文件创建具体标签的时候,再拷贝过去就行)
TabBarItem.vue
<template><div class="tab-bar-item"><slot name="item-icon"></slot><slot name="item-text"></slot></div>
</template><script>
export default {name:'TabBarItem'
}
</script>
<style>
.tab-bar-item{flex: 1; text-align: center; height: 49px; font-size: 14px;}
.tab-bar-item img{ width: 24px; height: 24px; vertical-align: middle; margin-top: 2px;}
</style>
- 2、创建中间层的组件页面TabBar.vue
在这里放入一个插槽,用来防止整个导航条的插槽
TabBar.vue
<template><div id="tab-bar"><slot></slot></div>
</template>
<script>
export default {name:'TabBar'
}
</script>
<style>#tab-bar{display: flex; background-color: #f6f6f6; position: fixed; left:0; right: 0; bottom: 0; box-shadow: 0 -1px 1px rgba(100,100,100,0.3);}</style>
- 3、修改最顶层组件页面App.vue
在这一层,要匹配所有插槽
App.vue
<template><div id="app"><tab-bar><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar></div>
</template><script>
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
</style>
- 4、文件目录
- 4、本集效果
3、tabbar案例03插槽内容动态显示
- 1、在app.vue中给图片多添加一个备选标签img。用于动态(根据标签值匹配)匹配插槽
<template><div id="app"><tab-bar><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/homeactive.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/categoryactive.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/shopcartactive.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/profileactive.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar></div>
</template><script>
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
</style>
- 2、在TableBarItem.vue修改data和模板代码
数据部分
<script>
export default {name:'TabBarItem',data(){return{isActive:true}}
}
</script>
模板部分
添加一个插槽,同时由于动态显示的需要,一定要把插槽上层嵌套一个div
此外绑定class属性使用对象形式 :class="{ative:isActive}",这里类名为ative:isActive
<template><div class="tab-bar-item"><div v-if="!isActive" ><slot name="item-icon"></slot></div><div v-else><slot name="item-icon-active"></slot></div> <div :class="{ative:isActive}"><slot slot name="item-text"></slot></div></div>
</template>
完整代码
<template><div class="tab-bar-item"><div v-if="!isActive" ><slot name="item-icon"></slot></div><div v-else><slot name="item-icon-active"></slot></div> <div :class="{ative:isActive}"><slot slot name="item-text"></slot></div></div>
</template><script>
export default {name:'TabBarItem',data(){return{isActive:true}}
}
</script>
<style>
.tab-bar-item{flex: 1; text-align: center; height: 49px; font-size: 14px;}
.tab-bar-item img{ width: 24px; height: 24px; vertical-align: middle; margin-top: 2px;}
.ative{color:blue
}
</style>
效果:
4、tabbar案例04
在各个导航上添加导航跳转动作,通过路由跳转到不同的页面
- 1、创建不同的页面
在src目录中单独创建views目录,并在views目录下创建不同的页面(.vue)
<template><h2>分类</h2>
</template>
<script>
export default {name:'Category'
}
</script>
<style scoped></style>
- 2、在路由index.js中导入路由信息
首先要导入路由
其次在设置路由映射
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
//导入组件,使用懒加载的方式
const Home = () => import('../views/home/Home.vue');
const Category = () => import('../views/category/Category.vue');
const Profile = () => import('../views/profile/Profile');
const Shopcart = () => import('../views/shopcart/Shopcart');//使用路由对象
Vue.use(Router)export default new Router({routes: [{path: '/',redirect:'/Home'},{path: '/home',component:Home},{path: '/category',component:Category},{path: '/profile',component:Profile},{path: '/shopcart',component:Shopcart}],//设置路由显示模式,history直接显示路径,哈希模式会显示一个#mode:'history'
})
- 3、在TabeBarItem.vue中设置props用来向子组件传值
//创建一个父组件向子组件传值的propsprops:{//指定一个字符串型的link属性path:String},
在模板代码中添加跳转方法
<div class="tab-bar-item" @click="itemClick">
<script>
export default {name:'TabBarItem',//创建一个父组件向子组件传值的propsprops:{//指定一个字符串型的link属性path:String},data(){return{isActive:true,}},methods:{itemClick(){//路由跳转this.$router.replace(this.path)}}
}
</script>
完整代码
<template><div class="tab-bar-item" @click="itemClick"><div v-if="!isActive" ><slot name="item-icon"></slot></div><div v-else><slot name="item-icon-active"></slot></div> <div :class="{ative:isActive}"><slot slot name="item-text"></slot></div></div>
</template><script>
export default {name:'TabBarItem',//创建一个父组件向子组件传值的propsprops:{//指定一个字符串型的link属性path:String},data(){return{isActive:true,}},methods:{itemClick(){//解决两次点击报错问题,连续点击导致当前路由和点击的路由相同,导致重复替换if(this.$route.path==this.path){return}//路由跳转this.$router.replace(this.path)}}
}
</script>
<style>
.tab-bar-item{flex: 1; text-align: center; height: 49px; font-size: 14px;}
.tab-bar-item img{ width: 24px; height: 24px; vertical-align: middle; margin-top: 2px;}
.ative{color:blue
}
</style>
- 3、在App.vue总组件中为每个item设置path
这里的path值是要向props传递的值
<tab-bar-item path="/home">
完整代码
<template><div id="app"><tab-bar><tab-bar-item path="/home"><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/homeactive.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item path="/category"><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/categoryactive.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item path="/shopcart"><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/shopcartactive.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item path="/profile"><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/profileactive.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar><router-view></router-view></div>
</template><script>
//导入模块
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
</style>
5、tabbar案例05解决不同状态下不同导航图标样式的问题
需求1:不同样式不同文字颜色
需求2:动态封装样式
- 1、在文字颜色上使用动态样式绑定
使用计算属性(activeStyle)动态绑定文本的样式
<div :style="activeStyle"><slot slot name="item-text"></slot></div>
- 2、添加新的props属性
props:{//指定一个字符串型的link属性path:String,activeColor:{type:String,default:'blue'}},
- 3、添加新的计算属性activeStyle**
activeColor是通过app.vue的props传过来的
computed:{isActive(){//如果当前path在路由映射表内,则返回true(隐式返回),不在数组里,indexOf会返回-1,这是indexOf函数return this.$route.path.indexOf(this.path)!==-1},activeStyle(){//根据isActive计算属性的值,返回不同的color值return this.isActive?{color:this.activeColor}:{}}},
- 4、原有.active的演示文件不用了
/*
//由于在TabeBarItem文件里直接设置activColor,则不需要这个样式了
.ative{color:blue
}
*/
完整TabBarItem.vue文件
<template><div class="tab-bar-item" @click="itemClick"><div v-if="!isActive" ><slot name="item-icon"></slot></div><div v-else><slot name="item-icon-active"></slot></div> <div :style="activeStyle"><slot slot name="item-text"></slot></div></div>
</template><script>
export default {name:'TabBarItem',//创建一个父组件向子组件传值的propsprops:{//指定一个字符串型的link属性path:String,activeColor:{type:String,default:'blue'}},data(){return{//isActive:true,}},computed:{isActive(){//如果当前path在路由映射表内,则返回true(隐式返回),不在数组里,indexOf会返回-1,这是indexOf函数return this.$route.path.indexOf(this.path)!==-1},activeStyle(){//根据isActive计算属性的值,返回不同的color值return this.isActive?{color:this.activeColor}:{}}},methods:{itemClick(){//解决两次点击报错问题if(this.$route.path==this.path){return}//路由跳转this.$router.replace(this.path)}}
}
</script>
<style>
.tab-bar-item{flex: 1; text-align: center; height: 49px; font-size: 14px;}
.tab-bar-item img{ width: 24px; height: 24px; vertical-align: middle; margin-top: 2px;}
/*
//由于在TabeBarItem文件里直接设置activColor,则不需要这个样式了
.ative{color:blue
}
*/
</style>
- 5、App.vue模板中,把props的值传过去
<tab-bar-item path="/home" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/homeactive.svg"/><div slot="item-text" >首页</div></tab-bar-item>
完整代码:
<template><div id="app"><tab-bar><tab-bar-item path="/home" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/homeactive.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item path="/category" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/categoryactive.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item path="/shopcart" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/shopcartactive.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item path="/profile" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/profileactive.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar><router-view></router-view></div>
</template><script>
//导入模块
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
</style>
效果
6、整个项目完整代码
- 1、单个页面Category.vue
其他文件也一样,不再重复写
<template><h2>分类</h2>
</template>
<script>
export default {name:'Category'
}
</script>
<style scoped></style>
- 2、index.js(路由目录下)
import Vue from 'vue'
import Router from 'vue-router'
//导入组件,使用懒加载的方式
const Home = () => import('../views/home/Home.vue');
const Category = () => import('../views/category/Category.vue');
const Profile = () => import('../views/profile/Profile');
const Shopcart = () => import('../views/shopcart/Shopcart');//使用路由对象
Vue.use(Router)export default new Router({routes: [{path: '/',redirect:'/Home'},{path: '/home',component:Home},{path: '/category',component:Category},{path: '/profile',component:Profile},{path: '/shopcart',component:Shopcart}],//设置路由显示模式,history直接显示路径,哈希模式会显示一个#mode:'history'
})
- 3、TabVBar.vue
<template><div id="tab-bar"><slot></slot></div>
</template>
<script>
export default {name:'TabBar'
}
</script>
<style>#tab-bar{display: flex; background-color: #f6f6f6; position: fixed; left:0; right: 0; bottom: 0; box-shadow: 0 -1px 1px rgba(100,100,100,0.3);}</style>
- 4、TabVBarItem.vue
<template><div class="tab-bar-item" @click="itemClick"><div v-if="!isActive" ><slot name="item-icon"></slot></div><div v-else><slot name="item-icon-active"></slot></div> <div :style="activeStyle"><slot slot name="item-text"></slot></div></div>
</template><script>
export default {name:'TabBarItem',//创建一个父组件向子组件传值的propsprops:{//指定一个字符串型的link属性path:String,activeColor:{type:String,default:'blue'}},data(){return{//isActive:true,}},computed:{isActive(){//如果当前path在路由映射表内,则返回true(隐式返回),不在数组里,indexOf会返回-1,这是indexOf函数return this.$route.path.indexOf(this.path)!==-1},activeStyle(){//根据isActive计算属性的值,返回不同的color值return this.isActive?{color:this.activeColor}:{}}},methods:{itemClick(){//解决两次点击报错问题if(this.$route.path==this.path){return}//路由跳转this.$router.replace(this.path)}}
}
</script>
<style>
.tab-bar-item{flex: 1; text-align: center; height: 49px; font-size: 14px;}
.tab-bar-item img{ width: 24px; height: 24px; vertical-align: middle; margin-top: 2px;}
/*
//由于在TabeBarItem文件里直接设置activColor,则不需要这个样式了
.ative{color:blue
}
*/
</style>
- 5、App.vue
<template><div id="app"><tab-bar><tab-bar-item path="/home" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/home.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/homeactive.svg"/><div slot="item-text" >首页</div></tab-bar-item><tab-bar-item path="/category" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/category.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/categoryactive.svg"/><div slot="item-text">分类</div></tab-bar-item><tab-bar-item path="/shopcart" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/shopcart.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/shopcartactive.svg"/><div slot="item-text">购物车</div></tab-bar-item><tab-bar-item path="/profile" activeColor="blue"><img slot="item-icon" src="./assets/images/tabbar/profile.svg"/><img slot="item-icon-active" src="./assets/images/tabbar/profileactive.svg"/><div slot="item-text">我的</div></tab-bar-item></tab-bar><router-view></router-view></div>
</template><script>
//导入模块
import TabBar from './components/tabbar/TabBar';
import TabBarItem from './components/tabbar/TabBarItem';export default {name: 'App',components:{TabBar,TabBarItem}
}
</script><style>
/*引入样式文件*/
@import url('./assets/style/base');
</style>
- 6、目录结构
最终效果
Vue(小码哥王洪元)笔记07路由案例tabbar相关推荐
- Vue(小码哥王洪元)笔记06路由,url的hash,history,router-linke,路由跳转,动态路由,懒加载,路由嵌套,router参数传递,导航守卫
1.什么是路由 路由器提供了两种机制:路由和传送 路由:数据报从来源到目的地的路径 传输:将输入端的数据转移到合适的输出端 路由有一个非常重要的概念教路由表 路由表本质上就是一个映射表,决定了数据包的 ...
- 小码哥iOS学习笔记第二天: OC对象的分类
Objective-C中的对象, 简称OC对象, 主要可以分为3种 instance对象(实例对象) class对象(类对象) meta-class对象(元类对象) 一.instance instan ...
- 小码哥iOS学习笔记第十二天:Class结构
一.Class的结构 通过查看源码, 可以得出Class的底层结构如下图 一开始class_data_bits_t bits;指向ro, 在加载的过程中创建了rw, 此时的指向顺序是bits-> ...
- 小码哥iOS学习笔记第八天: block的底层结构
一.最简单的block 1.最简单的block结构 ^{NSLog(@"this is a block");NSLog(@"this is a block"); ...
- iOS-多线程-(小码哥底层原理笔记)
iOS中常见的多线程方案 GCD的常用函数 同步方式执行任务 dispatch_sync(dispatch_queue_t _Nonnull queue, ^(void)block) queue - ...
- naarray查询 swift_从入门到精通Swift编程(完整 未加密 小码哥) [16.3G]
目录:/从入门到精通Swift编程(完整 未加密 小码哥) [16.3G] : U! s1 a8 i- s+ O, c7 i ┣━━01-基础语法.汇编初探 [367.2M]# D% l* ...
- 零基础轻松学python pdf 小码哥_零基础轻松学Python
零基础轻松学Python电子书 Python之父Guido van Rossum力荐的Python门书.本书以通俗易懂的语言.好玩有趣的案例让读者轻轻松松.循序渐地从零始掌握Python 3 编程.本 ...
- 跟小甲鱼学Web开发笔记07
跟小甲鱼学Web开发笔记07 格式化大作战 加粗效果 strong元素 b元素 斜体效果 em元素 i元素 使用css代替b和i元素 久的不去新的不来 del和ins元素 s元素 u元素 mark元素 ...
- 百度松果 小码哥考研小技巧 (概率期望)
题目描述 要考研了,小码哥非常焦急,他要开始背英语单词,每个单词的长度是lil_ili ,小码哥有pipipi的概率认识这个单词,小码哥要从一个有nnn个单词的总清单里按顺序的背单词,小码哥有一个认 ...
最新文章
- Android架构详解
- CentOS转的服务器磁盘规划
- WEB前端 vue学习二 组件之间的数据传递
- Account mobile phone in CRM and C4C
- C++笔记-函数参数使用void *的野路子
- vimb java,我可以让vim接受\b而不是\lt;和\gt ;?
- 【英语学习】【Level 08】U03 My Choice L1 Good books are like good friends
- uc点网页显示服务器升级,让uc浏览器网页加载速度提升100%
- 给小白的 Nginx 30分钟入门指南
- java 实现敏感词汇的过滤
- 与朋友分享的生活日记
- python读取grd数据_ARWpost处理后的grd数据使用fortran来读取
- Unity 艺术字体制作
- 顶尖作者介绍 | 心理学领域研究“情绪”的大牛们有哪些?
- 25岁从零开始学习平面设计会不会晚
- 智能工厂具体的名词解释
- asterisk连接sip139网络电话
- python求列表list平均值的方法
- 国乒28人出战匈牙利公开赛 新增混双项目受关注
- unity3D游戏开发实战原创视频讲座系列13之帽子戏法游戏开发(预告)