本人是一个从事Android开发5年的程序员,对各大优秀的编程语言都很感兴趣,Vue.js为啥会引起我的注意并且想学好它呢?一是因为Vue.js的理念和Android的Compose UI相似,可以对比学习,取长补短;其次,我想学习web应用的开发来做一些Web应用辅助Android的开发。实际上在Android开发中,多人开发的时候,不管是版本发布,还是自动打包,还是组件化,都离不开Maven仓库,打包服务器,还有邮件的折磨,在大公司里面,这一套都会有各种平台,比如京东的主站打包有一个专门的界面友好的Web页面,加上集成的CI/CD工具,程序员可以使用最少的沟通成本去完成自己组件的发布和打包。开发完的需求也可以通过一个web页面实时的提交到测试的系统,这些都离不开前端友好界面交互的支持。另外:本文适合有Vue基础的小伙伴学习,若是不熟悉Vue的小伙伴,看了本文后请先去学习基础知识,再来看一遍,然后下载源码动手实践一遍
以前因为前端页面都是Html5+CSS+JS开发,比较难维护,理念也和Android和IOS这类的大前端不太符合,以前的Html5+CSS+JS开发完成后,还需要交给后端去渲染数据,然后整个项目放到服务器上,每次我们打开浏览器,都是把整个页面加载到本地然后展示出来,这和Android,IOS这种拿到服务器端接口,自己渲染数据的方式不太相同。随着Vue.js的出现,我们发现好像Web的开发好像和Android,IOS 的开发比较相似了,前后端分离了,即我们可以用Vue.js编写一个前端的页面后,直接拿到服务器端提供的接口,自己进行渲染数据了。和Android,IOS一样,甚至可以共用接口了。而且Vue的设计理念和Android最近推崇的ComposeUI比较相似,可以对比学习,取长补短。下面我们就一起看下Vue.js有啥魔力吧。
比如我们仿造一个京东到家的小程序页面,效果图如下
我们分别使用原始的Html+Css方式实现和用Vue.js的方式来实现,对比下Vue.js带来的好处。
<div>
<div class="wrapper">
<div class="position">
<span class="iconfont position__icon">span>
北京联合大学北四环东路97号
<span class="iconfont position__notice">span>
div>
<div class="search">
<span class="iconfont">span>
<span class="search__text">山姆会员商店优惠卷span>
div>
<div class="banner">
<img
class="banner__img"
src="http://www.dell-lee.com/imgs/vue3/banner.jpg"
/>
div>
<div class="icons">
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/超市.png"
class="icons__item__img"
/>
<p class="icons__item__desc">超市便利p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/菜市场.png"
class="icons__item__img"
/>
<p class="icons__item__desc">菜市场p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/水果店.png"
class="icons__item__img"
/>
<p class="icons__item__desc">水果店p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/家居.png"
class="icons__item__img"
/>
<p class="icons__item__desc">家居时尚p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/蛋糕.png"
class="icons__item__img"
/>
<p class="icons__item__desc">烘培蛋糕p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/签到.png"
class="icons__item__img"
/>
<p class="icons__item__desc">签到p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/鲜花.png"
class="icons__item__img"
/>
<p class="icons__item__desc">鲜花绿植p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/医药健康.png"
class="icons__item__img"
/>
<p class="icons__item__desc">医药健康p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/大牌免运.png"
class="icons__item__img"
/>
<p class="icons__item__desc">大牌免运p>
div>
<div class="icons__item">
<img
src="http://www.dell-lee.com/imgs/vue3/红包.png"
class="icons__item__img"
/>
<p class="icons__item__desc">红包套餐p>
div>
div>
<div class="gap">div>
<div class="nearby">
<h3 class="nearby__title">附近店铺h3>
<div class="nearby__item">
<img
class="nearby__item__img"
src="http://www.dell-lee.com/imgs/vue3/near.png"
/>
<div class="nearby__content">
<div class="nearby__content__title">沃尔玛div>
<div class="nearby__content__tags">
<span class="nearby__content__tag">月售1万+span>
<span class="nearby__content__tag">月售1万+span>
<span class="nearby__content__tag">月售1万+span>
div>
<p class="nearby__content__highlight">
VIP尊享满89元减4元运费卷(每月3张)
p>
div>
div>
<div class="nearby__item">
<img
class="nearby__item__img"
src="http://www.dell-lee.com/imgs/vue3/near.png"
/>
<div class="nearby__content">
<div class="nearby__content__title">沃尔玛div>
<div class="nearby__content__tags">
<span class="nearby__content__tag">月售1万+span>
<span class="nearby__content__tag">月售1万+span>
<span class="nearby__content__tag">月售1万+span>
div>
<p class="nearby__content__highlight">
VIP尊享满89元减4元运费卷(每月3张)
p>
div>
div>
// 省略部分重复代码……
div>
<div class="spacer">div>
div>
<div class="docker">
<div class="docker__item docker__item--active">
<div class="iconfont">div>
<div class="docker__title">首页div>
div>
<div class="docker__item">
<div class="iconfont">div>
<div class="docker__title">购物车div>
div>
<div class="docker__item">
<div class="iconfont">div>
<div class="docker__title">订单div>
div>
<div class="docker__item">
<div class="iconfont">div>
<div class="docker__title">我的div>
div>
div>
div>
template>
<style lang="scss">
//省略CSS部分代码
<style>
}
上面的代码就是使用Html+CSS实现的仿京东到家主页的代码,还特意把部分CSS代码和部分重复的代码删掉,因为太多了。而且这里的代码看起来就不想维护,因为很乱,我要修改底部导航栏就得找很久,而且假设哪一个div标签每注意给删了,整个界面都会乱套。
我们仔细观察京东到家的主页是可以给分块的,比如我们可以将主页划分成几个不同的组件,然后组合成一个页面,这里就要用到Vue中的组件相关的内容了。如下图:
我们可以把图中标记出的组件1
Header部分做成一个组件,代码如下所示:
<template>
<div class="position">
<span class="iconfont position__icon"></span>
北京联合大学北四环东路97号
<span class="iconfont position__notice"></span>
</div>
<div class="search">
<span class="iconfont"></span>
<span class="search__text">山姆会员商店优惠卷</span>
</div>
<div class="banner">
<img
class="banner__img"
src="http://www.dell-lee.com/imgs/vue3/banner.jpg"
/>
</div>
<div class="icons">
<div
class="icons__item"
v-for="item in iconList"
:key="item.desc"
>
<img
:src="`http://www.dell-lee.com/imgs/vue3/${item.imgName}.png`"
class="icons__item__img"
/>
<p class="icons__item__desc">{{ item.desc }}</p>
</div>
</div>
<div class="gap"></div>
</template>
<script>
export default {
name: 'Header',
setup () {
const iconList = [
{ imgName: '超市', desc: '超市便利' },
{ imgName: '菜市场', desc: '菜市场' },
{ imgName: '水果店', desc: '水果店' },
{ imgName: '家居', desc: '家居时尚' },
{ imgName: '蛋糕', desc: '烘培蛋糕' },
{ imgName: '签到', desc: '签到' },
{ imgName: '鲜花', desc: '鲜花绿植' },
{ imgName: '医药健康', desc: '医药健康' },
{ imgName: '大牌免运', desc: '大牌免运' },
{ imgName: '红包', desc: '红包套餐' }]
return { iconList }
}
}
</script>
<style lang="scss" scoped>
@import "../../style/viriable.scss";
@import "../../style/mixins.scss";
.position {
position: relative;
@include ellipsis;
padding: 0.16rem 0.24rem 0.16rem 0;
line-height: 0.22rem;
font-size: 0.16rem;
color: $content-font-color;
.position__icon {
position: relative;
top: 0.01rem;
font-size: 0.2rem;
}
.position__notice {
position: absolute;
right: 0;
top: 0.17rem;
font-size: 0.2rem;
}
}
.search {
margin-bottom: 0.12rem;
line-height: 0.32rem;
background: #f5f5f5;
color: #b7b7b7;
border-radius: 0.16rem;
font-size: 0.14rem;
.iconfont {
display: inline-block;
padding: 0 0.1rem 0 0.16rem;
font-size: 0.2rem;
}
&__text {
display: inline-block;
}
}
.banner {
height: 0;
overflow: hidden;
padding-bottom: 25.4%; //计算图片的高度,
&__img {
width: 100%;
}
}
.icons {
display: flex;
flex-wrap: wrap;
margin-top: 0.16rem;
&__item {
width: 20%;
padding: 0.05rem 0 0.05rem 0;
&__img {
display: block;
width: 0.4rem;
height: 0.4rem;
margin: 0 auto;
}
&__desc {
margin: 0.06rem 0 0.16rem 0;
text-align: center;
color: $content-font-color;
}
}
}
.gap {
margin: 0 -0.18rem;
height: 0.01rem;
background: $content-bgColor;
}
</style>
上面的代码就是使用Vue.js抽取出来的Header部分代码,有几点需要解释下
例如:
是配置的阿里图标库里面对应的图标值。阿里图标库地址,创建一个项目后,想要的图标直接点击添加到购物车,然后添加到项目,进入你自己的项目中就会看到如下的内容:
复制上面标记出的代码后,在项目的style目录下新建一个iconfont.css文件,粘贴上我们在阿里图标库中的配置就行了,如下所示:
注意,新添加的图标会导致配置文件改变,所以每新添加一次图标,都需要重新复制粘贴下最新的配置
在组件中我们还发现这样的代码
export default {
name: 'Header',
}
这个 name: 'Header'
实际上是使用Vue调试工具时便于我们调试的,我们需要安装一个Vue dev tools扩展程序到chrome浏览器中,具体的安装方法大家可以自行去查,这里不多说了。我们看下最终的效果:
我们可以试想下,假设我们的两个组件间拥有相同的类名,任何一个组件修改了这个相同类名的CSS样式后,另一个组件具有相同类名的dom元素也会收到影响,所以为了解决这个问题,我们需要在样式的标签中添加一个scoped
关键字,消除组件间的CSS相互影响,如下所示:
<style lang="scss" scoped>
//省略部分代码……
<style>
附近店铺,也就是图中标出的组件2
部分,这里只贴代码:
<template>
<div class="nearby">
<h3 class="nearby__title">附近店铺</h3>
<div class="nearby__item"
v-for="item in nearByList"
:key="item.id">
<img class="nearby__item__img" :src="item.imgurl"/>
<div class="nearby__content">
<div class="nearby__content__title">{{ item.title }}</div>
<div class="nearby__content__tags">
<span
class="nearby__content__tag"
v-for="(innerItem,index) in item.tags"
:key="index"
>{{ innerItem }}</span>
</div>
<p class="nearby__content__highlight">
{{ item.desc }}
</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'NearBy',
setup () {
const nearByList = [{
id: 1,
title: '沃尔玛',
imgurl: 'http://www.dell-lee.com/imgs/vue3/near.png',
tags: ['起送', '运费', '基础运费5¥'],
desc: 'VIP尊享满89元减4元运费卷(每月3张)'
},
{
id: 2,
title: '京东',
imgurl: 'http://www.dell-lee.com/imgs/vue3/near.png',
tags: ['起送', '运费', '基础运费5¥'],
desc: 'VIP尊享满89元减4元运费卷(每月6张)'
}]
return { nearByList }
}
}
</script>
<style lang="scss" scoped>
@import "../../style/viriable.scss";
.nearby {
&__title {
margin: 0.16rem 0 0.02rem 0;
font-size: 0.18rem;
color: $content-font-color;
font-weight: normal;
}
&__item {
display: flex;
padding-top: 0.12rem;
&__img {
width: 0.56rem;
height: 0.56rem;
}
}
&__content {
padding-bottom: 0.12rem;
border-bottom: 1px solid $content-font-color;
margin-left: 0.16rem;
flex: 1;
&__title {
line-height: 0.22rem;
font-size: 0.16rem;
color: $content-font-color;
}
&__tags {
margin-top: 0.08rem;
line-height: 0.18rem;
font-size: 0.13rem;
color: $content-font-color;
}
&__tag {
margin-right: 0.16rem;
}
&__highlight {
margin: 0.08rem 0 0 0;
line-height: 0.18rem;
font-size: 0.13rem;
color: #e93b3b;
}
}
}
</style>
图中标出的组件3
部分为底部导航栏,代码如下:
<template>
<div class="docker">
<div
v-for="(item, index) in dockerList"
:class="{'docker__item':true,'docker__item--active': index === 0}"
:key="item.icon"
>
<!--需要使用 v-html来展示图标,否则图标会被转义导致无法显示 -->
<div class="iconfont" v-html="item.icon" />
<div class="docker__title">{{ item.text }}</div>
</div>
</div>
</template>
<script>
export default {
name: 'DockerPart',
setup () {
const dockerList = [
{ icon: '', text: '首页' },
{ icon: '', text: '购物车' },
{ icon: '', text: '订单' },
{ icon: '', text: '我的' }
]
return { dockerList }
}
}
</script>
<style lang="scss" scoped>
@import "../../style/viriable.scss";
.docker {
display: flex;
box-sizing: border-box;
padding: 0 0.18rem;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 0.49rem;
background: #f5f5f5;
border-top: 0.01rem solid $content-bgColor;
color: $content-font-color;
// docer 下的item元素
&__item {
flex: 1;
text-align: center;
.iconfont {
margin: 0.07rem 0 0.02rem 0;
font-size: 0.18rem;
}
&--active {
color: #1fa4fc;
}
}
&__title {
font-size: 0.2rem;
transform: scale(0.5, 0.5);
transform-origin: center top;
}
}
</style>
上面就是拆分好的三个组件,我们要组成一个主页时,只需要拼接三个组件即可,如下:
<template>
<div class="wrapper">
<Header/> // 头部组件
<NearBy /> // 附近店铺组件
<div class="spacer"></div>
</div>
<DockerPart /> // 底部导航栏组件
</template>
<script>
import StaticPart from './Header.vue'
import NearBy from './NearBy.vue'
import DockerPart from './DockerPart.vue'
export default {
name: 'HomeView',
components: { Header, NearBy, DockerPart }
}
</script>
<style lang="scss" scoped>
.wrapper {
overflow-y: scroll;
position: absolute;
left: 0;
top: 0;
bottom: 0.05rem;
right: 0;
padding: 0 0.18rem 0.3rem 0.18rem;
}
.spacer {
height: 0.4rem;
width: 100%;
}
</style>
上面描述的就是使用Vue去实现一个主页的过程,将主页拆成不同的组件不仅可以使代码更容易维护吗,而且还可以提高代码的可复用性,比如我们要再写一个新的其他项目,底部导航栏完全可以改下图标和标题就能使用了。是不是非常方便,上面的例子只是为了介绍Vue拆分组件的过程,不能直接运行,读者想要体验的可以在末尾拿到所有源码的地址
为了更好的体验vue带来的便利性,建议读者下载完整源码跟着练习一遍,有条件的可以去买一节完整的课跟着学,很简单的。
源码地址