2019独角兽企业重金招聘Python工程师标准>>>
首先,慕课网提供的视频是基于vue1.0的规范写的,因此有一些地方在vue2.0下不能正常运行。虽然课程补充文件也提供了vue2.0的代码,但多多少少也有一些问题。参考他人写的代码以及官方文档,修改了部分内容,整个项目能够流畅运行,不会报错。
项目请移步我的github地址:https://github.com/gqbwoai2016/-VUE2.0-APP-。里面内容还不是很多,以后会继续丰富的。
-------------------------------------------------------------------------------------------------------------------------------------------------
废话就这么多,开始实质的内容吧:
涉及的工作有:由商家模块入手,进行需求分析,利用脚手架工具搭建,mock数据,架构设计,代码实现,自测以及编译打包。本项目注重代码规范:架构设计,组建抽象,模块拆分,代码风格统一,JS变量命名规范及CSS代码规范。
所涉及的技术有:vue-cli脚手架工具;vue-resource与后端数据交互(类似AJAX);vue-router插件管理路由;第三方库better-csroll;最大程度组件化(优点:可维护性和复用性);localstorage;flex弹性布局;
实现的功能
• Goods、Ratings、Seller组件视图均可上下滚动
• 商品页 点击左侧menu,右侧list对应跳转到相应位置
• 点击list查看商品详情页,父子组件的通信
• 评论内容够可以筛选查看
• 购物车组件,包括添加删除商品及动效,购物控件与购物车组件之间非父子组件通信,点击购物车图标,展示选择的商品列表
• 商家实景图片可以左右滑动
• loaclStorage缓存商家信息(id、name)
0、用vue-cli脚手架工具搭建项目结构,有以下结构
项目名称
->build ------------------------------------------ webpack配置相关文件
->config ------------------------------------------ webpack配置相关文件
->node_modules ------------------------------------------ 依赖代码库
->src ------------------------------------------ 存放源码
->common ---- 通用的css和fonts
->components ---- Vue 组件
->router ---- vue-router相关配置(linkActiveClass,routes注册组件路由)
->build ---- webpack 的打包编译配置文件
->config ---- 一些配置项,比如我们服务器访问的端口配置等
->dist ---- 项目经过 build 之后才会生成
->prod.server.js----模拟的服务器配置,用来运行dist里面的文件,在config/index.js中,build对象中
添加一条端口设置port:9000,
->App.vue ---- 根组件,所有的子组件都将在这里被引用
->index.html ---- 整个项目的入口文件,将会引用我们的根组件 App.vue
->main.js ---- 入口文件的 js 逻辑,在 webpack 打包之后将被注入到 index.html 中
->static ------------------------------------------ 存放第三方静态资源
->.babelrc.JSON ------------------------------------------ babe的配制,用于从es6编译至es5
->.editorconfig ------------------------------------------ 编译器配置
->.eslintignore ------------------------------------------ 忽略语法检查的目录文件
->.eslintrc.js ------------------------------------------ eslint的配置
->.gitignore ------------------------------------------ git忽略的目录或文件
->index.html ------------------------------------------ 入口文件,项目编译过程中会自动插入其中
->package.json ------------------------------------------ 配置文件,描述一个项目
->README.md ------------------------------------------ 项目描述文件
所有项目文件放在src下,main.js为入口文件,APP.vue为整个页面的vue,components存放组建文件,里面有许多子目录,子目录中存放.vue文件及图片等资源(满足组件化开发的就近维护)。common包含公共模块资源(js,scss,fonts等)。
- Hot-reload Vue的热更新,修改代码之后无需手动刷新网页,对前端开发来说非常方便
- PostCss,再也不用去管兼容性的问题了,只针对chrome这样的现代浏览器写css代码,会自动编译生成兼容多款浏览器的css代码
- ESlint,统一代码风格,规避低级错误(在eslintrc.js文件里面:rules是自定义的检查规则,可以覆盖默认的检查规则,例如要加分号,函数要加空格,这个跟代码风格有关)。在.eslintrc.js里的rules中写自定义规则,如'space-before-function-paren': 0,函数定义是括号前空格取消。
- Bable,ES2015出来已经有一段时间了,但是不少浏览器还没有兼容ES6,有了bable,放心使用ES6语法,它会自动转义成ES5语法
- SCSS,一款 CSS预处理器,编译后成正常的CSS文件。为CSS增加一些编程的特性
1、 数据mock
mock就是做假数据,这样可以便于前后端分离开发,前端不需要等后端做好数据来开发或者测试验证
假数据data.json.实现:sell(项目总文件)->插入data.json,然后在build->webpack.dev.conf.js中写数据接口,然后写数据的路由。
坑1,最新版的vue中dev-server.js被替换成了webpack.dev.conf.js,修改时注意
2、reset
sell->static->css->reset.css,写好后给index.html用link标签引用这个文件
3、meta
对其设置viewport以规范显示大小,缩放等移动端视口初始化。
4、header组件开发
a)使用vue-router实现点击切换;在这里,当前模块样式在vue-router中有个默认属性linkActiveClass,在main.js对其配置后,在APP.vue中通过
vue-router详解:
路由,其实就是指向的意思。我们页面中所有内容都是组件化的,我们只要把路径和组件对应起来就可以了,然后在页面中把组件渲染出来。
页面实现:定义了两个标签
js中配置路由:首先定义route,由path,component组成,前者指路径,后者指组件,如下所示,最后创建router管理路由。配置完成后,把router 实例注入到 vue 根实例中,就可以使用路由了
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
//管理路由
const router = new VueRouter({
routes // routes: routes 的简写
})
//配置完成,注入到实例中
const app = new Vue({
router
}).$mount('#app')//$mount为手动挂载
//上面这个写法也可以改为
new Vue({
el:"#box",
router
});
注意:当首次进入页面的时候,页面中并没有显示任何内容。这是因为首次进入页面时,它的路径是 '/',我们并没有给这个路径做相应的配置。在这里使用重定向解决问题。
const routes = [
{
path:"/home",
component: home
},
{
path: "/about",
component: about
},
// 重定向
{
path: '/',
redirect: '/home'
}
]
b)1像素实现:在APP端由于dpr不同,展示会有问题,因此添加minxin.scss设置通用样式后再通过base.scss使用@media 媒体查询来分别设置不同dpr的scale控制样式;
window.devicePixelRatio是设备上物理像素和设备独立像素(device-independent pixels (dips))的比例。公式表示就是:window.devicePixelRatio = 物理像素 / dips
非视网膜屏幕的iphone上等于1,在视网膜屏幕的iphone上,屏幕物理像素640像素,独立像素还是320像素,因此等于2。
2x和3x图是为了适应不同dpr比例的,不同比例的显示是不一样的.2x就是普通的dpr为1的屏幕使用的; 对于高清屏幕就是用3x,dpr为2或者以上; 2x和3x就是尺寸的大小,2x的图片比3x的小
c)满减图标在export default中create()内使用
classMap=['discount'...]
创建,在标签中通过
:class="classMap[seller.supports[0].type]"
引用。
d)背景模糊:整个header组件中有模糊背景图,可通过创建一个div然后绝对定位至相关位置,再用z-index=-1设置后,使用
filter:blur(15px)增加模糊效果。
e)css sticky footers模块:简而言之就是底部有一个固定图标,只有移动至底部区域才展示,否则不显示的一种布局。
父级 position:fixed,内容设 为padding-bottom:64px,页脚相对定位,margin-top:-64px,clear:both
为了保证兼容性,父级要清除浮动
坑2:新旧版vue-router不同,旧版支持router.map(),新版则使用const router=new VueRouter()直接在里面写即可
g)flex布局:
意为"弹性布局",用来为盒状模型提供最大的灵活性。设为Flex布局以后,子元素的float
、clear
和vertical-align
属性将失效。以下六个属性设置在容器上:
flex-direction 容器内项目的排列方向(默认横向排列)。可选值为row(默认)沿水平主轴由左向右排列、row-reverse沿水平主轴由右向左排列、column沿垂直主轴右上到下和column-reverse。
flex-wrap 换行方式。nowrap(默认)不换行、wrap换行(第一行在上方)和wrap-reverse
flex-flow 以上两个属性的简写方式 .box { flex-flow:
justify-content 主轴上的对齐方式。主轴究竟是哪个轴要看属性flex-direction的设置了flex-start:在主轴上由左或者上开始排列;flex-end:在主轴上由右或者下开始排列;center:在主轴上居中排列;space-between:在主轴上左右两端或者上下两端开始排列;space-around:每个项目两侧的间隔相等。
align-items 交叉轴上如何对齐(纵轴对齐方式)flex-start顶对齐| flex-end底对齐 | center居中 | baseline文字基准线 | stretch撑开整个盒子
align-content 定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
设置在子元素的属性也有六个:
order:项目排列顺序,数值越小排名靠前,默认为0;
flex-grow:项目放大比例,默认0;
flex-shrink:缩小比例,默认1;
flex-basis:计算主轴是否有多余空间,默认auto,项目本来大小;
flex:是上面三个简写,默认0 1 auto;
align-self:允许单个项目有与其他项目不一样的对齐方式。
f)自适应布局
左侧宽度固定,右侧宽度自适应
// 左侧固定width:80px,右侧自适应
parent:
display:flex;
child-left:
flex:0 0 80px
child-right:
flex:1
5、goods模块
a)采用better-scroll实现滚动,在package.json表明版本,使用npm安装。BScroll接受两个参数,第一个是DOM对象,第二个是方式,在method中写方法,需要设置 click:true,否则移动端滑动无效。
注意:vue提供一种方法获取DOM,在需要获取地方添加ref="**",然后在js中通过this.$ref.**来引用;
DOM真正映射实在nextTick后,因此一些计算属性应该写在里面,否则在页面中无响应;
6、seller组件
a)商家实景图片横向滚动:
解决方案:每个 li 要 display:inline-block,因为width不会自动撑开父级ul,所以需要将计算后的宽度赋值给ul的width,(每一张图片的width+margin)*图片数量-一个margin,因为最后一张图片没有margin,同时new BScroll里面要设置scrollX: true, eventPassthrough: 'vertical', // 滚动方向横向
b)打开seller页面,无法滚动
问题分析:出现这种现象是因为better-scroll插件是严格基于DOM的,数据是采用异步传输的,页面刚打开,DOM并没有被渲染,所以,要确保DOM渲染了,才能使用 better-scroll;解决方案:用到mounted钩子函数,同时必须搭配this.$nextTick()
c)刷新后,无法滚动
问题分析:出现这种情况是因为mounted函数在整个生命周期中只会只行一次;解决方案:使用watch方法监控数据变化,并执行滚动函数 this._initScroll();this._initPicScroll();
d)缓存数据
使用window.localstorage保存舍设置缓存信息,封装在store.js中
e)axios
在vue1.x的时候,vue的官方推荐HTTP请求工具是vue-resource,但是在vue2.0的时候将推荐工具改成了axios。如果想像以前使用 vue-resource 那样 this.$http.get 调用,要这样定义:Vue.prototype.$http=axios;
通过 this.$http.get 来定义通过vue实例来发送get请求,然后通过then后面的回调函数将请求成功的数据接收,通过状态码来判断是否成功以及复制给vue的数据对象。由于这里是用的mock数据(模拟后台数据),所以用的模拟状态码。
const ERR_OK = 0;//表示没有错误信息,即获取数据成功
this.$http.get('/api/seller').then((response) => {
response = response.data;
if (response.errno === ERR_OK) {
this.seller = Object.assign({}, this.seller, response.data);
}
});
vue-resource详解:
vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应。也就是说,$.ajax能做的事情,vue-resource插件一样也能做到,而且vue-resource的API更为简洁。
优点:体积小;支持主流浏览器;支持PromiseAPI和URI Templates;支持拦截器。
使用:
首先引入vue-resourec;然后发送请求即可
import VueResource from 'vue-resource';
Vue.use(VueResource);
this.$http.get('/someUrl',jsonData).then(function(response){ //jsonData是传给后端的数据
// 响应成功回调
}, function(response){
// 响应错误回调
});
下面给个实例,从a.txt取数据
最新版Vue推荐使用axio,两个功能类似,首先也要安装然后引入,最后再使用:(注:他的注册不能使用Vue.use()方法)
import axios from "axios";
//注册
Vue.prototype.$axios = axios;
//使用axios
created:function(){
this.$axios.get("/seller",{"id":123}).then(res=>{
console.log(res.data);
});
}
f)组件间通讯
父传子: props
// 父组件
// 子组件 header.vue
props: {
seller: {
type: Object
}
}
子传父: $emit 如果是子组件想传递数据给父组件,需要派发自定义事件,使用 $emit 派发,父组件使用v-on接收监控(v-on可以简写成@)
// 子组件 RatingSelect.vue,派发自定义事件isContent,将this.onlyContent数据传给父级
this.$emit('isContent', this.onlyContent);
this.$emit('selRatings', this.selectType);
// 父组件 foodInfo.vue 在子组件的模板标签里,使用v-on监控isContent传过来的数据
非父子组件之间通信: 1. 大型项目可以用 Vue官方推荐的vuex;event bus: 利用一个中间组件来作为信息传递中介;
g)better-scroll
better-scroll是一个移动端滚动的解决方案,基于iscroll的重写(多年没人维护了,有很多bug;有些情况是基于js实现的帧动画,体验差,bs基于css3等)
使用:首先应有一个父容器div,固定高度且overflow:hidden,给它设置bscroll,子元素高度由内容撑开。
//主div
//子元素
- ...
- ...
...
***重要:在mounted钩子函数里,this.$nextTick的回调函数中初始化better-scroll。是因为wrapper的DOM在这个时候已经渲染了,可以正确计算其高度。
异步数据处理
- {{item}}
初始化bs需要在数据获取之后。之所以放在created而不是mounted,是因为requestData是一个异步过程,拿到相应数据时,DOM已经渲染好,但是,数据改变后到DOM重新渲染仍然是异步过程,所以还是要异步初始化bs(nextTick)。
注意:在PC上,点击事件会执行两次。由于better-scroll派发的事件有event_constructed:true属性。可以进行处理。
if (!event._constructed) {
return;
}
7、sass
Sass的学名叫“CSS预处理器”,就是在CSS的基础上,引入了变量、嵌套、mixin(混合)、运算以及函数等功能,增加了代码的灵活性,可以让我们以更少的代码实现同样的效果,而且代码的整洁度、可读性更强。
.scss是Sass3引入的新语法,基本写法与CSS大致相同
基本语法:
a)变量。css属性的值(1px,bold)都可替换为变量。
$box-color: red; //定义变量
ul{
color: $box-color; //引用
}
li{
background-color: $box-color; //引用
}
b)嵌套
/***********************************************选择器嵌套*******************************************/
div {
h1 {
color: #333;
}
p {
margin-bottom: 1.4px;
a {
color: #999;
}
:hover{
color: #888;
}
}
}
/* 编译后 */
div h1 { color: #333; }
div p { margin-bottom: 1.4px; }
div p a { color: #999; }
div p:hover{ color: #888; }
/***********************************************属性嵌套*******************************************/
div {
border: {
style: solid;
width: 1px;
color: #ccc;
}
}
//编译后
div {
border-style: solid;
border-width: 1px;
border-color: #ccc;
}
c)继承:使用选择器的继承,要使用关键词@extend,后面紧跟需要继承的选择器。
.class1 {
border: 1px solid #333;
}
.class2 {
@extend .class1;
background-color: #999;
}
//编译后
.class1, .class2 {
border: 1px solid #333;
}
.class2 {
background-color: #999;
}
d)Mixin混合器:使用@mixin声明,通过@include minxin名称调用
@mixin mixName {
float: left;
margin-left: 10px;
}
div {
@include mixName;
}
//编译后:
div {
float: left;
margin-left: 10px;
}
/*带参数的声明及调用*/
@mixin left($value: 10px) {
float: left;
margin-left: $value;
}
div {
@include left(66px);
}
//编译后:
div {
float: left;
margin-left: 66px;
}
e)颜色函数
$box-color: red;
li{
background-color: darken($box-color,30%);
}
//编译后
li{
background-color: #660000;
}
//更多
lighten(#cc3,10%)//#d6d65c
grayscale(#cc3)//#808080
complement(#cc3)//#33c
f)导入:@import "地址"; 如@import "../../common/scss/mixin.scss";
8、优化:
每次切换模块后,都会重新渲染DOM,解决方法为给APP.vue下的
9、打包:
使用npm run build打包文件,其执行了node build/build.js脚本,最终产生一个dist目录,里面包含css,js,index.html文件,打包后文件通过HTTP server启动(sell总目录下创建一个produ.server.js写完代码后使用node prode.server.js启动)
技巧:(1).如果要使用new创建对象,由于本项目使用了ESlint检查代码规范,因此会报错,在这里使用/*eslint-disable no-new*/来跳过校验;
(2). 在build->webpack.base.conf.js中,module.exports下的resolve的alias下可以定义路径,就不用每次引用时加./表示当前路径 等类似问题了;
(3).图标与文字不齐,可设置vertical-align:top来对齐,还不行可以对图片设置paddingtop。
(4).手机测试网页技巧:将localhost换成自己的ip,然后复制地址栏地址,进入草料二维码,然后生成二维码,然后用手机扫一扫就可以查看了,前提是,你手机和电脑必须在同一个局域网。