【饿了么】

您所在的位置:网站首页 饿了吗ui 【饿了么】

【饿了么】

#【饿了么】| 来源: 网络整理| 查看: 265

前言:学习Vue.js高仿饿了么课程过程中,总结了这个Web App项目从准备到开发完毕自己觉得很重要的知识点。这一篇主要介绍:项目准备、页面骨架开发、header组件开发。

项目github地址:https://github.com/66Web/ljq_eleme,欢迎Star。

 

App header

 

一、项目分析&学习目标

       当前最火的MVVM框架

Vue.js —— 轻量、简洁、高效、数据驱动、组件化

      高仿上线外卖App标准来开发

核心模块 —— 商家模块

      开发一个webApp的全流程

需求分析 脚手架工具 数据mock 架构设计 代码编写 自测 编译打包

      以线上生产环境的代码质量作标准

代码开发及测试环节: UI标注 真实数据演示 代码规范 架构设计 组件抽象 模块拆分 代码风格统一 JS变量命名规范 CSS代码规范

      功能技术分析

vue-resource:  和后端做数据交互 vue-router:  做前端路由,实现单页应用 第三方JS库better-scroll:  列表滚动的实现 最大程度组件化: 提高代码的复用 html5的localstorage:【收藏商家】功能—存储在浏览器端 细节:图标字体的使用 移动端1像素边框 css sticky footer布局 flex 弹性布局

      学习目标

掌握Vue.js在实战中的运用 学会使用Vue.js【完整的】开发移动端App 学会组件化、模块化的开发

      学习内容

Vue.js框架介绍 Vue-cli 脚手架 —— 搭建基本代码框架 vue-router 官方插件 —— 管理路由 vue-resource 官方插件 —— 和后端作Ajax通信 Webpack 开源构建工具(把源代码经过编译生成浏览器可以识别和运行的代码) es6 + eslint eslint —— es6代码风格检查工具 工程化 组件化 模块化 移动端常用开发技巧: flex弹性布局 css stickyfooter 酷炫的交互设计 二、Vue.js介绍

      近年来前端开发趋势

旧浏览器逐渐淘汰,移动端需求增加 前端交互越来越多,功能越来越复杂 架构从传统后台MVC 向REST API+ 前端MV* 迁移

      (前者传统MVC:更新数据会刷新页面 后者前端MV*: 向后端REST API异步请求数据,局部刷新页面)

        MV* —— MVC、MVP、MVVM

      MVVM框架

      View    ViewModel    Model

       视图        通讯           数据

DOM 观察者 Javascript对象 针对具有复杂交互逻辑的前端应用 提供基础的架构抽象 通过Ajax数据持久化,保证前端用户体验 MVVM框架技术:vue.js、react.js、Angular.js

      对比Anglar  React

Vue.js更轻量,gzip后大小只有 20K+ Vuejs更易上手,学习曲线平稳 吸收两家之长,借鉴了angular的指令和react的组件化

      vue.js 核心思想

数据驱动 组件化

      组件设计原则

页面上每个独立的可视/可交互区域视为一个组件 每个组件对应一个工程目录,组件所需要的各种资源在这个目录下【就近维护】 页面不过是组件的容器,组件可以嵌套自由组合形成完整的页面 三、Vue-cli开启Vue项目

      Vue-cli 是Vue的脚手架工具 —— 帮助写好Vue基础代码的工具

目录结构 本地调试 代码部署 热加载 单元测试

      安装使用

(sudo) npm install -g vue-cli // sudo:mac环境下有关管理权限的命令 vue init webpack my-project

      项目文件

src文件夹:存放项目源码 bulld目录+ config目录:webpack配置相关 node_modules文件夹:npm install 安装的依赖代码库 static—>.gitkeep: 当这个目录为空时也可以将它提交到git仓库中 babelrc : babel的一些配置,es6语法的转换 .editorconfig: 编辑器的配置 .eslintignore: 忽略语法检查的目录文件,一般忽略build目录和node_modules目录 .eslintrc.js: eslint的配置文件 gitignore: 上传git仓库要忽略的一些文件的配置 index.html: 入口html文件,要使用的css和js文件会在编译过程中自动插入 package.json:整个项目的配置文件,一般用来描述项目 ↓

        →  scripts:  配置一些需要执行的命令        →  dependencies:开发环境中的依赖        →  devdependencies: 编译过程中的依赖

      项目运行

npm run dev  src开发目录下: main.js —— 项目入口文件 App.vue —— 主页面组件 vue语法糖:  export default { } 一个对象——可以定义一个组件 【小知识点】sublime自动格式化 —— Command+option+L 或 Control+alt+L

 

在父组件中使用子组件,如Hello.vue: 引用  import Hello from './compoments/Hello' 注册 export default{ components: { Hello //es6语法 相当于 'Hello': Hello } } 使用标签

      开发时的Webpack配置与编译

build->dev-server.js 或 Webpack.dev.conf.js webpack.base.conf.js : 配置各种文件的Loader

      →  配置默认识别的路径

resolve: { extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), } } 四、准备工作

      图标字体制作 

在线制作网站:https://icomoon.io/app/#/select 将自己的SVG图标导入,输出自己的图标字体文件 Import Icons → Generate Fonts → preferences修改名称 → Download 使用:icon.css和fonts文件夹下所有文件

      项目目录设计

src->common目录下:项目公用文件 js、style、fonts

【css的stylus语法】

删掉分号和大括号, &表示父元素,冒号也可以省略 文件后缀为styl,style中添加lang="stylus" 需要安装: npm install stylus stylus-loader --save-dev

 

resource目录下:项目图片文件——可以删掉无用的assets目录,但需要修改引用到的地方 components目录下:布局、业务功能等分模块管理组件,如header目录,footer目录 static->css目录下:reset.css 标签默认样式 在  index.html 中引入:

      前后端分离

Vue SPA —— 前端通过 vue-resource  Ajax从后端获取数据 前端最重要的任务:mock数据(后台数据模拟) data.json { "seller":{} //商家相关字段 "goods":{} //商品相关字段 "rattings":{} //评论相关字段 } 

      webpack.dev.conf.js中配置

使用 express框架  开启一个node server,用 express.Router 编写这些接口请求 首先:在 const portfinder = require(‘portfinder’) 后添加 const express = require('express')//开启一个node server const app = express() //定义一个对象,包含express返回的数据 var appData = require('../data.json') //定义一个对象引入data数据 var seller = appData.seller; var goods = appData.goods; var ratings = appData.ratings; app.use('/api', apiRoutes); //调用app对象 然后:找到 devserver{}, 在里面添加 before(app) { app.get('/api/seller', (req, res) => { res.json({ errno: 0, //错误码:实际上是业务方根据业务自己定的 data: seller }) //接口返回json数据,上面配置的数据seller就赋值给data请求后调用 }), app.get('/api/goods', (req, res) => { res.json({ errno: 0, data: goods }) }), app.get('/api/ratings', (req, res) => { res.json({ errno: 0, data: ratings }) }) } 注意:每次配置完 express 之后都需要重新启动

      查看json数据

在Google地址栏中输入:localhost:8080/api/seller  依赖Google的jsonview插件 —— 安装 使数据格式化

【Google安装第三方插件】

打开https://github.com ; 搜索 jsonView 链接:https://github.com/search?utf8=%E2%9C%93&q=jsonview; 选择需要的插件(我下载的是这个gildas-lormeau/JSONView-for-Chrome);  点击【Download Zip】,插件下载完成,解压缩到相应目录(D:\Download\JSONView-for-Chrome-master);  安装,打开chrome - 扩展程序 (地址栏输入chrome://extensions/);  右上角,选中开发模式;  点击”加载正在开发的扩展程序…”  选择插件目录(D:\Download\JSONView-for-Chrome-master\WebContent);  安装完成,重新加载 (Ctrl+R)。  测试地址:http://jsonview.com/example.json

—— 转载自【小白白打酱油博客】

 

五、页面骨架开发

      移动端视口

index.html   中通过meta设置视口可被缩放,初试宽高设置

      App.vue 中把页面拆为三个区块

header tab content

    然后,分别抽成一个组件,引用 —— 所有组件自定义标签名不可与html本身标签重合 'v-header': header 

      移动端经典布局  flex 

商品 评论 商家 .tab display: flex width: 100% height: 40px line-height: 40px .tab-item flex:1 text-align: center

      vueRouter

Vue2.0 使用  进行【导航】 商品 【路由外链 】 —— 单页面切换的内容页,替换content div区块

 main.js 中设置单页面应用路由的【挂载组件】—— 默认App.vue 也可以自定义组件如layout.vue

/* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '' })

配置【路由map】:router->index.js

export default new Router({ mode: 'history', routes: [ { path: '/', redirect: '/goods',//默认页面重定向 }, { path: '/goods', component: goods }, { path: '/ratings', component: ratings }, ] }) 【点击】高亮显示   a.router-link-active  #app .tab .tab-item>a{ display: block; font-size: 14px; color: rgb(77, 85, 93); } #app .tab .tab-item>a.router-link-active{ color: rgb(240, 20, 20) }

      1像素border实现 

错误做法:直接给tab加1像素边框  X .tab{ border-bottom: 1px solid rgba(7,17,27,0.1) } 问题是:这段代码在PC端显示,是1像素,但是在手机端显示,就不是1像素。 因为手机端有一个DPR的概念:它的物理像素是设备像素的两倍。所以iPhone6上面可能就是一个2像素的边框

【PC开发中用手机实时预览的小技巧】

新开一个gitbash,mac环境下输入命令:ifconfig, windows下输入:ipconfig 获知本机IP地址192.168.1.1,替换掉localhost(表示本机) 将地址http://192.168.1.1:8080/goods#/输入到草料二维码网站中,生成二维码,用手机扫描,即可查看 必须与PC使用的是同一局域网

 

正确做法:给 tab 加一个伪类:after , 让它是一条1像素的线,然后在DBR为2或3的手机端缩放  √ 定义mixin.styl:  通过css预处理器的函数方法,实现伪类线 border-1px($color) position: relative &:before display: block position: absolute left:0 top: 0 width: 100% border-bottom: 1px solid $color content: '' &:after display: block position: absolute left:0 bottom: 0 width: 100% border-top: 1px solid $color content: '' 定义base.styl: 实现不同DBR的移动端的缩放 @media(-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)//DPR为1.5的缩放0.7倍 .border-1px &:before -webkit-transform: scaleY(0.7) transform:scaleY(0.7) &:after -webkit-transform: scaleY(0.7) transform:scaleY(0.7) @media(-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)//DPR为2的缩放0.5倍 .border-1px &:before -webkit-transform: scaleY(0.5) transform:scaleY(0.5) &:after -webkit-transform: scaleY(0.5) transform:scaleY(0.5) 定义index.styl: 引用所有styl文件,最后在 main.js 中全局引用 @import"./mixin" //import后无空格 @import"./icon" @import"./base" main.js: import '@/common/stylus/index.styl' //import后有空格 六、header组件开发

      vue-resource

安装 vue-resource npm install vue-resource --save

注意:每次install完插件等之后需要重新启动项目

main.js 文件中: import VueResource from 'vue-resource' Vue.use(VueResource)

之后就可以在项目任何地方:使用 this.$http 命令

App.vue 组件中: export module{} 外: const ERR_OK = 0; //定义常量,增强程序可读性 export module{} 内: data() { return { seller:{} //维护数据 seller } } 异步请求数据,返回的是Promise对象 created: function () { this.$http.get('/api/seller') //发送get请求, .then(function(res){ //.then方法 请求完成后调用 //第一个函数是请求成功后方法 }, function (err) { //第二个函数是请求失败后方法 }) }

使用ES6 箭头函数:箭头函数前后必须有空格

created: function () { this.$http.get('/api/seller') .then((res) => { res = res.body //拿到response返回的promise对象的body(Data Object) if (res.errno === ERR_OK) { this.seller = res.data; //console.log(this.seller) } }, (err) => { }) }

     外部组件

父组件  App.vue 中 组件标签中用v-bind绑定seller属性,传给子组件seller数据 子组件 header.vue 中通过 props属性 获取父组件传来的seller数据 props: { seller: { type: Object } } 模板对应位置 显示 对应seller.xxx 子数据 标签: 使用seller数据图片地址,v-bind绑定src属性 :src="seller.avatar" 文本内容: 双向数据绑定显示seller数据 {{seller.name}} 如果要获取的是 seller数据对象的  子对象数组的  某一项:因为异步获取数据,子对象可能为undefined,需要先 v-if 判断是否存在 {{seller.supports[0].description}} 定义 classMap数组,通过获取seller数据中的索引值,应用对应索引的class created (){ this.classMap = ['decrease','descount','guarantee','invoice','special'] } mixin.styl 文件中伪函数:实现图片在不同DPR下引用不同的图片路径 bg-image($url) background-image: url($url+"@2x.png") @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) background-image: url($url+"@3x.png") 公告内容 —— 文字【省略号效果】 white-space: nowrap overflow: hidden text-overflow: ellipsis 背景图片【模糊滤镜效果】 .background position: absolute top: 0 left: 0 width: 100% height: 100% z-index: -1 filter: blur(10px)

      详情弹层页

实现弹出层 v-show指令 ——  控制弹出层的显示/隐藏 data () { return { detailShow: false //通过改变数据detailShow 的true/false,控制元素的显示/隐藏 } } @click —— 触发点击事件,执行显示函数


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3