Vue 插件或第三方库

  1. 学会使用 vue-router 开发单页应用
  2. 学会使用 axios/vue-resource 与后端进行数据交互
  3. 学会使用 vuex 管理应用组件状态
  4. 学会使用 better-scroll/vue-scroller 实现页面滑动效果
  5. 学会使用 mint-ui 组件库构建界面
  6. 学会使用 vue-lazyload 实现图片惰加载
  7. 学会使用 mockjs 模拟后台数据接口

样式/布局/效果相关

  1. 学会使用 stylus 编写模块化的 CSS
  2. 学会使用 Vue.js 的过渡编写酷炫的交互动画
  3. 学会制作并使用图标字体
  4. 学会解决移动端 1px 边框问题
  5. 学会移动端经典的 css sticky footer 布局
  6. 学会 flex 弹性布局

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

基本步骤:

npm install -g vue-cli 
vue init webpack gshop
cd gshop
npm install
npm run dev
访问: localhost:8080

项目结构分析

gshop:

|-- build : webpack 相关的配置文件夹(基本不需要修改) 
|-- config: webpack 相关的配置文件夹(基本不需要修改)
|-- index.js: 指定的后台服务的端口号和静态资源文件夹
|-- node_modules
|-- src : 源码文件夹
|-- main.js: 应用入口 js
|-- static: 静态资源文件夹
|-- .babelrc: babel 的配置文件
|-- .editorconfig: 通过编辑器的编码/格式进行一定的配置
|-- .eslintignore: eslint 检查忽略的配置
|-- .eslintrc.js: eslint 检查的配置
|-- .gitignore: git 版本管制忽略的配置
|-- index.html: 主页面文件
|-- package.json: 应用包配置文件
|-- README.md: 应用描述说明的 readme 文件

编码测试与打包发布项目

1) 编码测试

npm run dev 
访问: http://localhost:8080
编码, 自动编译打包(HMR), 查看效果

2) 打包发布

npm run build 
npm install -g serve
serve dist
访问: http://localhost:5000

iconfont 使用(本地有 svg)

a. 图标字体: 使用 IcoMoon 将 SVG 格式的图标转换生成图标字体及样式

b. 进入 icoMoon 官网: ​​https://icomoon.io/​​ c. 点击右上角

vue项目开发概览_css


, 进入处理页面

d. 点击左上角

vue项目开发概览_vue_02


, 选择 resource\SVG*.svg, 上传显示到页面

e. 在页面选择所有 svg, 点击右下角

vue项目开发概览_git_03


生成图标字体样式

f. 点击左上角

vue项目开发概览_ajax_04


指定 Font-Name 为 sell-icon, 点击右下角

vue项目开发概览_git_05


下 载到本地

vue项目开发概览_css_06

g. 解压 zip 包, 访问 demo.html 测试
h. 我们项目需要的是 fonts 和 style.css

项目源码目录设计

vue项目开发概览_vue_07

ESLint

ESLint 提供以下支持

  1. ES6
  2. AngularJS
  3. JSX
  4. Style 检查
  5. 自定义错误和提示

ESLint 提供以下几种校验

  1. 语法错误校验
  2. 不重要或丢失的标点符号,如分号
  3. 没法运行到的代码块(使用过 WebStorm 的童鞋应该了解)
  4. 未被使用的参数提醒
  5. 漏掉的结束符,如}
  6. 确保样式的统一规则,如 sass 或者 less
  7. 检查变量的命名

规则的错误等级有三种

  1. 0:关闭规则检查。
  2. 1:打开规则检查,并且作为一个警告(输出提示文本黄色)。
  3. 2:打开规则检查,并且作为一个错误(输出提示文本红色)。

相关配置文件

  1. .eslintrc.js : 规则相关配置文件, 可以在此修改规则
  2. .eslintignore: 指令检查忽略的文件, 可以在此添加想忽略的文件

Vue 组件化

配置 vue 组件文件模板

<template>
<div>

</div>
</template>
<script>
export default {

}
</script>
<style lang="stylus" rel="stylesheet/stylus">
</style>

引入 reset 样式

/*** Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */
html,body,div,span,applet,object,iframe,
h1,h2,h3,h4,h5,h6,p,blockquote,pre,
a,abbr,acronym,address,big,cite,code,
del,dfn,em,img,ins,kbd,q,s,samp,
small,strike,strong,sub,sup,tt,var,
b,u,i,center,
dl,dt,dd,ol,ul,li,
fieldset,form,label,legend,
table,caption,tbody,tfoot,thead,tr,th,td,
article,aside,canvas,details,embed,
figure,figcaption,footer,header,
menu,nav,output,ruby,section,summary,
time,mark,audio,video,input {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font-weight: normal;
vertical-align: baseline;
}

/* HTML5 display-role reset for older browsers */
article,aside,details,figcaption,figure,
footer,header,menu,nav,section {
display: block;
}

body {
line-height: 1;
}

blockquote,
q {
quotes: none;
}

blockquote:before,blockquote:after,
q:before,q:after {
content: none;
}

table {
border-collapse: collapse;
border-spacing: 0;
}

/* custom */
a {
color: #7e8c8d;
text-decoration: none;
-webkit-backface-visibility: hidden;
}

li {
list-style: none;
}

::-webkit-scrollbar {
width: 5px;
height: 5px;
}

::-webkit-scrollbar-track-piece {
background-color: rgba(0, 0, 0, 0.2);
-webkit-border-radius: 6px;
}

::-webkit-scrollbar-thumb:vertical {
height: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}

::-webkit-scrollbar-thumb:horizontal {
width: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}

html,body {
width: 100%;
height: 100%;
}

body {
-webkit-text-size-adjust: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}

/*显示省略号*/
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

index.html 中引入

<link rel="stylesheet" href="/static/css/reset.css">

移动端

viewport

<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,u ser-scalable=no">

解决点击响应延时 0.3s 问题

<script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js">
</script>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}
if (!window.Promise) {
document.writeln(
'<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js" ' +
'>' + '<' + '/' + 'script>');
}
</script>

引入 vue-router

下载 vue-router

npm install vue-router --save

编码

1) router/index.js

/* 路由模块*/
import Vue from 'vue'
import Router from 'vue-router'

import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld
}
]
})

2)main.js

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App)
})

前后台交互 ajax

下载依赖包

npm install --save axios

封装 ajax 请求模块

  1. api/ajax.js
/*
ajax请求函数模块
返回值: promise对象(异步返回的数据是: response.data)
*/
import axios from 'axios'
export default function ajax (url, data={}, type='GET') {

return new Promise(function (resolve, reject) {
// 执行异步ajax请求
let promise
if (type === 'GET') {
// 准备url query参数数据
let dataStr = '' //数据拼接字符串
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&'
})
if (dataStr !== '') {
dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
url = url + '?' + dataStr
}
// 发送get请求
promise = axios.get(url)
} else {
// 发送post请求
promise = axios.post(url, data)
}
promise.then(function (response) {
// 成功了调用resolve()
resolve(response.data)
}).catch(function (error) {
//失败了调用reject()
reject(error)
})
})
}

/*
const response = await ajax()
const result = response.data

const resule = await ajax()
*/

使用 vuex 管理状态

下载 vuex

npm install --save vuex

定义 state

/*
状态对象
*/
export default {
latitude: 40.10038, // 纬度
longitude: 116.36867, // 经度
address: {}, //地址相关信息对象
categorys: [], // 食品分类数组
shops: [], // 商家数组
}

定义 mutation-types

/*mutation type 常量名称模块 */ 
export const RECEIVE_ADDRESS = 'receive_address' // 接收地址信息
export const RECEIVE_CATEGORYS = 'receive_categorys' // 接收分类数组
export const RECEIVE_SHOPS = 'receive_shops' // 接收商家数组

定义 mutations

/*vuex 的 mutations 模块 */
import {
RECEIVE_ADDRESS,
RECEIVE_CATEGORYS,
RECEIVE_SHOPS
} from './mutation-types'

export default {
[RECEIVE_ADDRESS](state, {
address
}) {
state.address = address
},
[RECEIVE_CATEGORYS](state, {
categorys
}) {
state.categorys = categorys
},
[RECEIVE_SHOPS](state, {
shops
}) {
state.shops = shops
},
}

定义 actions

/*vuex 的 actions 模块 */
import {reqAddress,reqCategorys,reqShops} from '../api'
import {RECEIVE_ADDRESS,RECEIVE_CATEGORYS,RECEIVE_SHOPS} from './mutation-types'

export default {
// 异步获取地址
async getAddress({commit,state }) {
const geohash = state.latitude + ',' + state.longitude
const result = await reqAddress(geohash)
commit(RECEIVE_ADDRESS, {address: result.data})
},
// 异步获取分类列表
async getCategorys({commit}) {
const result = await reqCategorys()
commit(RECEIVE_CATEGORYS, {categorys: result.data})
},
// 异步获取商家列表
async getShops({commit,state}) {
const {latitude,longitude } = state
const result = await reqShops({ latitude,longitude })
commit(RECEIVE_SHOPS, { shops: result.data })
}
}

定义 store 对象

/*vuex 的核心管理对象 store 对象模块 */ 
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
actions,
getters
})

注册 store

main.js

import store from './store' 
new Vue({
store
})

图片懒加载: vue-lazyload

下载包

npm install --save vue-loader

使用

import VueLazyload from 'vue-lazyload' 
import loading from './common/img/loading.gif' Vue.use(VueLazyload, {
loading
})

<img v-lazy="food.image">