本节包含如下三部分内容
为什么移动端CSS里面写了1px,实际上看起来比1px粗;是因为UI设计师要求的1px是指设备的物理像素,而CSS里记录的项目是逻辑像素,他们之间存在一个比例关系,我利用媒体查询来解决1像素的问题,如下是我写的移动端一像素边框,可以直接放到项目中使用
@charset "utf-8";
.border,
.border-top,
.border-right,
.border-bottom,
.border-left,
.border-topbottom,
.border-rightleft,
.border-topleft,
.border-rightbottom,
.border-topright,
.border-bottomleft {
position: relative;
}
.border::before,
.border-top::before,
.border-right::before,
.border-bottom::before,
.border-left::before,
.border-topbottom::before,
.border-topbottom::after,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::before,
.border-topleft::after,
.border-rightbottom::before,
.border-rightbottom::after,
.border-topright::before,
.border-topright::after,
.border-bottomleft::before,
.border-bottomleft::after {
content: "\0020";
overflow: hidden;
position: absolute;
}
/* border
* 因,边框是由伪元素区域遮盖在父级
* 故,子级若有交互,需要对子级设置
* 定位 及 z轴
*/
.border::before {
box-sizing: border-box;
top: 0;
left: 0;
height: 100%;
width: 100%;
border: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
left: 0;
width: 100%;
height: 1px;
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
top: 0;
width: 1px;
height: 100%;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
border-top: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-right::before,
.border-rightbottom::before,
.border-rightleft::before,
.border-topright::after {
border-right: 1px solid #eaeaea;
transform-origin: 100% 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::before {
border-bottom: 1px solid #eaeaea;
transform-origin: 0 100%;
}
.border-left::before,
.border-topleft::after,
.border-rightleft::after,
.border-bottomleft::after {
border-left: 1px solid #eaeaea;
transform-origin: 0 0;
}
.border-top::before,
.border-topbottom::before,
.border-topleft::before,
.border-topright::before {
top: 0;
}
.border-right::before,
.border-rightleft::after,
.border-rightbottom::before,
.border-topright::after {
right: 0;
}
.border-bottom::before,
.border-topbottom::after,
.border-rightbottom::after,
.border-bottomleft::after {
bottom: 0;
}
.border-left::before,
.border-rightleft::before,
.border-topleft::after,
.border-bottomleft::before {
left: 0;
}
@media (max--moz-device-pixel-ratio: 1.49), (-webkit-max-device-pixel-ratio: 1.49), (max-device-pixel-ratio: 1.49), (max-resolution: 143dpi), (max-resolution: 1.49dppx) {
/* 默认值,无需重置 */
}
@media (min--moz-device-pixel-ratio: 1.5) and (max--moz-device-pixel-ratio: 2.49), (-webkit-min-device-pixel-ratio: 1.5) and (-webkit-max-device-pixel-ratio: 2.49), (min-device-pixel-ratio: 1.5) and (max-device-pixel-ratio: 2.49), (min-resolution: 144dpi) and (max-resolution: 239dpi), (min-resolution: 1.5dppx) and (max-resolution: 2.49dppx) {
.border::before {
width: 200%;
height: 200%;
transform: scale(.5);
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
transform: scaleY(.5);
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
transform: scaleX(.5);
}
}
@media (min--moz-device-pixel-ratio: 2.5), (-webkit-min-device-pixel-ratio: 2.5), (min-device-pixel-ratio: 2.5), (min-resolution: 240dpi), (min-resolution: 2.5dppx) {
.border::before {
width: 300%;
height: 300%;
transform: scale(.33333);
}
.border-top::before,
.border-bottom::before,
.border-topbottom::before,
.border-topbottom::after,
.border-topleft::before,
.border-rightbottom::after,
.border-topright::before,
.border-bottomleft::before {
transform: scaleY(.33333);
}
.border-right::before,
.border-left::before,
.border-rightleft::before,
.border-rightleft::after,
.border-topleft::after,
.border-rightbottom::before,
.border-topright::after,
.border-bottomleft::after {
transform: scaleX(.33333);
}
}
为了减少前端项目打包后的体积,常规的做法是 引入图标字体,阿里的图标字体具体怎么申请 自行百度 这个地方就不做讲解了 字体下载成功后 同样需要在main.js中引入
import 'assets/fonts/iconfont.css'
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'Home',
component: Home,
children: [
{
path: '/index',
name: 'index',
component: () => import(/* webpackChunkName: "index" */ '../views/index/Index.vue'),
},
{
path: '/follow',
name: 'follow',
component: () => import(/* webpackChunkName: "fllow" */ '../views/follow/Follow.vue'),
},
],
},
];
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
});
export default router;
路由采用懒加载的方式引入 另外/ webpackChunkName: "fllow" / 号称是Magic Comments(魔术注释法) 为什么使用嵌套路由
就比如在一个页面中, 在页面的上半部分,有三个按钮,而下半部分是根据点击不同的按钮来显示不同的内容,那么我们就可以在这个组件中的下半部分看成是一个嵌套路由,
也就是说在这个组件的下面需要再来一个, 当我点击不同的按钮时,他们的router-link分别所指向的组件就会被渲染到这个中。
<template>
<div class="tab-bar">
<div class="item" @click="changeTab(0)">
<router-link to="/index" tag="span" :class="tabIndex === 0 ? 'active':''">首页</router-link>
</div>
<div class="item" @click="changeTab(1)">
<router-link to="/follow" tag="span" :class="tabIndex === 1 ? 'active':''">沈阳</router-link>
</div>
<div class="item" @click="changeTab(2)">
<router-link to="/index" tag="span" :class="tabIndex === 2 ? 'active':''"><img class="dy-btn"
alt=""
src="../../assets/img/dy-btn.png">
</router-link>
</div>
<div class="item" @click="changeTab(3)">
<router-link to="index" tag="span" :class="tabIndex === 3 ? 'active':''">消息</router-link>
</div>
<div class="item" @click="changeTab(4)">
<router-link to="index" tag="span" :class="tabIndex === 4 ? 'active':''">我的</router-link>
</div>
</div>
</template>
<script>
export default {
name: 'Tabbar',
data() {
return {
tabIndex: 0,
};
},
methods: {
changeTab(index) {
this.tabIndex = index;
},
},
};
</script>
<style lang="less" scoped>
.tab-bar {
height: 50px;
line-height: 50px;
width: 100%;
background: #000000;
position: fixed;
bottom: 0;
left: 0;
color: #cccccc;
font-size: 16px;
display: flex;
justify-content: center;
.item {
flex: 1;
text-align: center;
}
.active {
color: #ffff;
}
.dy-btn {
display: inline-block;
width: 50px;
height: 30px;
margin: 10px;
}
}
</style>
作者:米亚流年
链接:https://juejin.cn/post/6862327793200562184
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
完成后的效果
在你的工程内创建Topbar.vue 代码如下
<template>
<div class="top-bar">
<div class="left">
<span class="iconfont icon-live"></span>
</div>
<div class="center">
<div class="item" @click="changeTop(0)">
<span :class="topIndex === 0 ? 'active' : ''">关注</span>
</div>
<div class="item" @click="changeTop(1)">
<span :class="topIndex === 1 ? 'active' : ''">推荐</span>
</div>
</div>
<div class="right">
<span class="iconfont icon-sousuo"></span>
</div>
</div>
</template>
<script>
export default {
name: 'Topbar',
data() {
return {
topIndex: 1,
};
},
methods: {
changeTop(index) {
this.topIndex = index;
},
},
};
</script>
<style lang="less" scoped>
.top-bar {
background: #000000;
width: 100%;
height: 50px;
line-height: 50px;
font-size: 18px;
color: #cccccc;
display: flex;
box-sizing: border-box;
.left {
width: 20%;
padding-left: 10px;
.icon-live {
font-size: 24px;
}
}
.center {
flex: 1;
display: flex;
justify-content: center;
.item {
flex: 1;
text-align: center;
span {
padding: 2px 0px;
text-align: center;
position: relative;
}
.active {
color: #ffffff;
&:after {
content: "";
height: 1px;
width: 30px;
left: 3px;
bottom: -2px;
position: absolute;
background: #ffffff;
}
}
}
}
.right {
width: 20%;
padding-right: 10px;
text-align: right;
.icon-sousuo {
font-size: 24px;
}
}
}
</style>
完成后的效果
因为浏览器是有默认样式的 比如 padding、margin、input、box-sizing之类的 这些默认的样式都需要处理掉,这个地方我采用了第三方包
yarn add normalize.css
安装成功之后,需要在main.js中引入
import 'normalize.css/normalize.css';
目前顶部导航栏是点击切换的,导航栏文子下方的 横线 是用css的伪类实现的,再后续 的项目迭代中,会对此组件进行封装,并实现滑动切换标签的功能,敬请期待