Vue 插件或第三方库
- 学会使用 vue-router 开发单页应用
- 学会使用 axios/vue-resource 与后端进行数据交互
- 学会使用 vuex 管理应用组件状态
- 学会使用 better-scroll/vue-scroller 实现页面滑动效果
- 学会使用 mint-ui 组件库构建界面
- 学会使用 vue-lazyload 实现图片惰加载
- 学会使用 mockjs 模拟后台数据接口
样式/布局/效果相关
- 学会使用 stylus 编写模块化的 CSS
- 学会使用 Vue.js 的过渡编写酷炫的交互动画
- 学会制作并使用图标字体
- 学会解决移动端 1px 边框问题
- 学会移动端经典的 css sticky footer 布局
- 学会 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. 点击右上角
, 进入处理页面
d. 点击左上角
, 选择 resource\SVG*.svg, 上传显示到页面
e. 在页面选择所有 svg, 点击右下角
生成图标字体样式
f. 点击左上角
指定 Font-Name 为 sell-icon, 点击右下角
下 载到本地
g. 解压 zip 包, 访问 demo.html 测试
h. 我们项目需要的是 fonts 和 style.css
项目源码目录设计
ESLint
ESLint 提供以下支持
- ES6
- AngularJS
- JSX
- Style 检查
- 自定义错误和提示
ESLint 提供以下几种校验
- 语法错误校验
- 不重要或丢失的标点符号,如分号
- 没法运行到的代码块(使用过 WebStorm 的童鞋应该了解)
- 未被使用的参数提醒
- 漏掉的结束符,如}
- 确保样式的统一规则,如 sass 或者 less
- 检查变量的命名
规则的错误等级有三种
- 0:关闭规则检查。
- 1:打开规则检查,并且作为一个警告(输出提示文本黄色)。
- 2:打开规则检查,并且作为一个错误(输出提示文本红色)。
相关配置文件
- .eslintrc.js : 规则相关配置文件, 可以在此修改规则
- .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 请求模块
-
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">