Fork me on GitHub
余鸢

饿了么45个页面重构(一)框架搭建

开发相关的技术栈

vue2 + vuex + vue-router + webpack + ES6/7 + sass + flex + svg + axios

构建项目框架

使用vue-cli脚手架搭建项目

1
2
3
4
5
6
7
8
# 创建一个基于 webpack 模板的新项目hs
$ vue init webpack hs
# 进入项目目录
$ cd hs
# 安装依赖
$ npm install
# 运行项目
$ npm run dev

项目运行成功!

h1

注意:早期的vue-lic下面有dev-server.js和dev-client.js两文件,请求本地数据在dev-server.js里配置,最新的vue-webpack-template 中已经去掉了dev-server.js和dev-client.js 改用webpack.dev.conf.js代替,所以 配置本地访问在webpack.dev.conf.js里配置即可。

项目结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
├── build #webpack编译相关文件目录,一般不用动
├── config #配置目录
│ ├────dev.env.js #开发环境变量
│ ├────index.js #主配置文件
│ └────prod.env.js #生产环境变量
├── dist #生产环境下build后的文件存放目录(发布目录)
├── src #前端项目源码目录
│ ├───—api #封装的接口文件目录
│ ├───—assets #资源目录
│ ├───—base #基础组件目录
│ ├───—common #公用文件目录
│ ├───—components #组件及页面文件目录
│ ├───—router #路由目录
│ ├───—App.vue #项目入口文件
│ ├───—bus.js #公共通信组件
│ └────main.js #项目的核心文件
├── static #开发模式下的静态资源目录
├── index.html #首页入口文件,你可以添加一些 meta 信息或同统计代码啥的
├── package.json #项目配置文件
└── README.md #项目的说明文档,markdown 格式

设置路径别名

设置路径别名,以减少开发过程中路径的复杂性,比如../../这类路径。

修改webpack.base.conf.js

1
2
3
4
5
6
7
8
9
10
11
12
13
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'@': resolve('src'),
'components': resolve('src/components'),
'config': resolve('src/config'),
'common': resolve('src/common'),
'page': resolve('src/page'),
'api': resolve('src/api'),
'elm': resolve('src/elm'),
'base': resolve('src/base')
}
},

创建基础页面

创建基本页面

home.vue

1
2
3
<template>
<div>首页</div>
</template>

这里不一一展示,直接看截图

e1

组件明细:

  • home ——– 首页城市列表页
  • checkout ——– 确认订单页
  • city ——– 当前选择城市页
  • forget ——– 修改密码页
  • login ——– 登陆注册页
  • msite ——– 所有商铺列表页
  • order ——– 订单列表页
  • profile ——– 个人信息页
  • search ——– 商铺详情页
  • vipcard ——– vip卡页

配置及安装依赖

在package.json中配置所需的依赖

1
2
3
4
5
6
7
8
9
10
11
"dependencies": {
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuex": "^3.0.1",
"axios": "^0.17.1",
},
"devDependencies": {
...
"babel-polyfill": "^6.26.0",
...
}

安装依赖

1
$npm install

配置router

在router/index.js配置routers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
routes: [
{
path: '/',
redirect: '/home'
},
{
path: '/',
component: App,
children: [
{
path: '/home',
component: Home // 首页城市列表页
},
{
path: '/checkout',
component: Checkout // 确认订单页
},
{
path: '/city/:cityId',
component: City // 当前选择城市页
},
{
path: '/forget',
component: Forget // 修改密码页
},
{
path: '/login',
component: Login // 登陆注册页
},
{
path: '/msite',
component: Msite, // 所有商铺列表页
meta: {keepAlive: true}, // 需要被缓存
},
{
path: '/order',
component: Order // 订单列表页
},
{
path: '/profile',
component: Profile // 个人信息页
},
{
path: '/search/:geohash',
component: Search // 搜索页
},
{
path: '/shop',
component: Shop // 商铺详情页
},
{
path: '/vipcard',
component: Vipcard // vip卡页
}
]
}
]

创建e-header.vue基础组件,因为后面可能有多个页面会用到这种组件,把它分离出来单独一个组件,方便使用。

e-header.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
<header id='head_top'>
<slot name='logo'></slot>
<div class="head_goback" v-if="goBack" @click="back"></div>
<router-link to='/login' v-if='signinUp' class="head_login">登陆|注册</router-link>
<div class="title_head" v-if="headTitle">{{headTitle}}</div>
<slot name="changecity"></slot>
</header>
</template>
export default{
props: {
// 名称
signinUp: {
type: String,
default: ''
},
// 头名称
headTitle: {
type: String,
default: ''
},
// 返回
goBack: {
type: Boolean,
default: false
}
},
methods: {
// 返回上一页
back () {
this.$router.go(-1)
}
}
}

css样式

scss

css部分这里不写了,参考代码。此项目用到的是scss,首先就是安装依赖。

1
2
3
4
5
6
"devDependencies": {
"sass": "^1.0.0-beta.4",
"sass-loader": "^6.0.6",
"scss": "^0.2.4",
"scss-loader": "^0.0.1",
}
安装
1
$npm install

如果安装失败的话,在项目内添加一个 .npmrc 文件:

1
2
3
phantomjs_cdnurl=http://cnpmjs.org/downloads
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
registry=https://registry.npm.taobao.org

然后使用 npm install 安装。

rem

此项目是移动端项目,我使用rem实现自适应,或叫rem响应式布局,通过使用一个js脚本就可以实现自适应,不用再为各种设备宽度不同而烦恼如何实现自适应的问题。

设置viewport配合进行缩放

通常在写移动端页面的时候,我们都会设置viewport,保证页面缩放没有问题,在index.js添加一下meta标签:

1
<meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">

基于JS进行屏幕分辨率计算

通过js来调整html的字体大小,而在页面中的制作稿则统一使用rem这个单位来制作。代码如下:

config/rem.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(function (doc, win) {
let docEl = doc.documentElement
let resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize'
let recalc = function () {
let clientWidth = docEl.clientWidth
if (!clientWidth) {
return
}
docEl.style.fontSize = 20 * (clientWidth / 320) + 'px'
}
if (!doc.addEventListener) {
return
}
win.addEventListener(resizeEvt, recalc, false)
doc.addEventListener('DOMContentLoaded', recalc, false)
})(document, window)

orientationchange:这是一个事件,菜鸟教程中做了这么一个解释:事件是在用户水平或者垂直翻转设备(即方向发生变化)时触发的事件。

引入rem文件

vue项目中,在main.js中引入rem.js就可以使用了。

1
2
3
4
5
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import './common/js/rem'

具体代码见:https://github.com/kakajing/vue-elmm