准备
vue-cli是Vue的脚手架工具,通过vue-cli,可以快速构建一个vue项目,并且vue-cli自带webpack的各种配置。
//3.0 4.0版本
npm install -g vue/cli
vue create project-name
......
//2.0版本在4.0版本下运行
npm install -g @vue/cli-init
vue init webpack project-name
......
- 项目结构
build:项目的webpack配置文件 config:针对于开发环境和线上环境的配置文件 node_modules:项目的依赖 static:静态资源(本地数据),只有放在static文件下的数据才能被访问到 index.html是整个项目最外层的html文件 src:源代码,是主要编写代码的地方: main.js:整个项目的入口文件。 App.vue:是总的根组件。APP组件显示当前路由对应的内容。 router:index.js:路由 assets:项目中的资源,如:iconfont components:项目中的小组件,以.vue结尾的文件都是单文件组件。<tempalate></tempalte>中是组件的模板,<script></script>中是组件的逻辑,<style></style>中是组件的样式。
- 前端路由:Vue Router(快速开发单页面应用)
路由就是根据网址的不同,返回不同的内容给用户。
路由的初步配置:import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home/Home' Vue.use(Router) export default new Router({ routes: [ { path: '/', name: 'Home', component: Home } ] })
- 移动端网页的准备
(1)在index.html文件里加上禁止用户在手机上通过手指来进行页面的缩放的设置
(2)因为有些元素的样式在不同浏览器上表现不同,所以引入reset.css文件,重置元素样式,来保障所有浏览器上的样式是一样的。<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
(3)移动端有1像素边框的问题:引入border.css
(4)移动端有300ms点击延迟的问题:引入第三方库fastclicknpm install fastclick --save import fastClick from 'fastclick' fastClick.attach(document.body)
首页
组件结构
Home.vue是home页面的根组件,下面有很多子组件。
HomeHeader
-
iconfont的使用
- IconFont阿里巴巴矢量库中将需要的图标加入购物车,添加至创建的一个项目
- 下载至本地,将压缩包中iconfont.eot, .svg, .ttf, .woff 放入assets/styles/iconfont下,将iconfont.css放入assets/styles下。
- 将iconfont.css中url地址改正确
- 在模板中通过复制十六进制代码使用iconfont
<span class="iconfont"></span>
-
移动端rem的使用
UI图中:height: 86px(UI图是iphone6的二倍图,所以css中height应为43px)
html中的font-size = 50px,1rem = 50px, 所以43px = 0.86rem -
布局:(flexbox布局)
.header height: .86rem display: flex flex-direction: row align-items: center .header_input flex: 1
-
用stylus在css中定义变量
//安装 npm install stylus --save npm install stylus-loader --save //定义 $bgColor = #00bcd4 //css中引入 @import '~@/assets/styles/varibles.styl'
HomeSwiper
- 引入第三方轮播插件
npm install vue-awesome-swiper --save
vue-awesome-swiper的使用。 - 如果网络条件不好,页面加载时会出现图片抖动问题。
css解决抖动问题:(占位)在资源外部加一个div,class为wrapper。<style lang="stylus" scoped> .wrapper >>> .swiper-pagination-bullet-active background-color: white !important .wrapper overflow: hidden width: 100% height: 0 padding-bottom: 31.25% (117/375=31.25%) /*这里的百分比是图片高度相对宽度的百分比,其比值为图片的高宽比。这样设置能实现图片宽高自适应比例。*/ .slide_img width: 100%
HomeIcons
-
页面布局
<template> <div class="icons"> <!--占位--> <div class="icon"> <!--小图标布局--> <div class="icon-img"> <!--图片外部包裹一个div--> <img class="icon-img-content" src="http://img1.qunarzz.com/piao/fusion/1611/54/ace00878a52d9702.png"> </div> <p class="icon-desc">景点门票</p> </div> </div> </template> <style lang="stylus" scoped> @import '~styles/varibles.styl' .icons overflow: hidden height: 0 padding-bottom: 50% background-color: green .icon position: relative overflow: hidden float: left width: 25% height: 0 padding-bottom: 25% //padding-bottom的高宽比的宽度相对的是父元素的宽度 background-color: red .icon-img position: absolute top: 0 left: 0 right: 0 bottom: .44rem background-color: blue box-sizing: border-box padding: .1rem .icon-img-content height: 100% display: block margin: 0 auto .icon-desc position: absolute left: 0 right: 0 bottom: 0 text-align: center height: .44rem line-height: .44rem color: $darkTextColor </style>
-
图标分页算法
将pages变成二维数组,
pages[0]: array[8],
pages[1]:array[1]。computed: { pages () { const pages = [] this.iconList.forEach((item, index) => { const page = Math.floor(index/8) if(!pages[page]) { pages[page] = [] } pages[page].push(item) }) return pages } }
-
如果文字内容很多,想做成用三个点提示的样式:
overflow: hidden white-space: nowrap text-overflow:ellipsis
Ajax获取首页数据
-
在vue中发送ajax的工具有fetch函数,vue-resource,axios(第三方模块)。我们使用axios,因为它可以实现跨平台数据请求。
-
整个首页(Home.vue)发一个ajax请求,获取到数据后传给每一个组件。
methods: { getHomeInfo () { //axios返回的结果是一个promise对象,所以使用then, axios.get('/api/index.json').then(this.getHomeInfoSucc) }, //数据获取成功后,将数据赋值给当前组件的属性。 getHomeInfoSucc (res) { // console.log(res) res = res.data if (res.ret &&console.log(res) res.data) { this.city = res.data.city this.swiperList = res.data.swiperList } } }, //页面挂载完成后,执行getHomeInfo(),请求ajax数据, mounted () { this.getHomeInfo() }
-
本来axios获取静态数据,应该是: axios.get(’/static/mock/index.json’).then(this.getHomeInfoSucc)
但是为了上线,应该将静态地址托管为:
axios.get(’/api/index.json’).then(this.getHomeInfoSucc)
使用webpack-dev-server工具
在webpack/index.js中设置proxyTable: { '/api': { target: 'http://localhost:8080', pathRewrite: { '^/api': '/static/mock' } } }
css样式小细节
- scoped穿透
如果我们给样式设置了scoped,这个时候组件里面的样式既不能影响外部样式,也不能被外部样式所影响。如果我们有要影响我们所使用的子组件的样式需求,我们需要进行穿透 query >>> query, query为选择器,例如:.wrapper >>> .swiper-pagination-bullet-active background-color: #ffffff !important
- vue-awersome-swipper插件,轮播图默认情况下显示最后一页?
使用axios获取数据传递给轮播组件以后直接默认显示在最后一页,因为在获取数据之前dom结构是根据空的数组来渲染的,所以在最后一页。此时可以使用v-if来解决问题、当数据完全获取到的时候再开始渲染dom结构。