Vue.js 仿饿了么Web App
- vue
- vuex
- vue-router
- vue-resource
- webpack
- eslint
- better-scroll
- stylus
- postCss
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
vue1.0升至2.0+后,v-link改为<router-view></router-view>
,入口js文件的设置也跟随变化,需要按照官网配置router.vuejs.org,
不仅把这些.vue .js文件的配置改了,还需要在package.json中的dependencies内,把vue和vue-router的版本也改为最新;
在手机等移动端物理像素有别于逻辑像素,具体的比例根据不同设备的设备像素比不同而不同;
一个在开发过程中使用手机浏览页面的方法:
- 使用
ipconfig
查看自己PC局域网IP; - 将浏览器url中的localhost改为局域网IP;
- 复制链接至草料网生成二维码;
- 使用同在一个局域网的手机扫码访问即可!
实现移动端一像素边框的方法:利用min-device-pixel-ratio媒体功能实现真正的1像素
使用vue-resource时注意this.$http.get(url).then((res) => {})
中回调函数then()中获取到的json内容在res.body,data中。
在使用ajax的get方法获取数据来填充app.vue内seller等对象之前,seller等对象还是空对象,所以在用seller内的数据渲染时,需要加v-if判断seller等对象是否有值,
否则会报错。
sticky footers,即粘性页脚布局,在遇到下面两个布局的时候需要用到:
- 在内容未撑满页面时,footer固定在底部
- 在内容超出页面高度时,footer随着页面的变大而往下移动,也保持在页面底部。
一般情况下,一个网页分为header、content、footer;
- 将头部和内容装入一个容器wrapper-main,再将wrapper-main封装到wrapper中;
- 将wrapper的min-height设为100%,wrapper-main的padding-bottom设为footer的高度;
- 将footer的margin-top设为负的自身的高度;
这样就达到了当wrapper的高度为100%时,footer固定在视口的底部,当其高度大于100%时,footer则一直在wrapper后面的效果;
<div class="wrapper clearfix">
<div class="wrapper-main">
<header>头部</header>
<div class="content">页面内容</div>
</div>
</div>
<footer>页脚</footer>
.wrapper{
min-height: 100%;
}
.wrapper-main{
padding-bottom: 50px;
}
footer{
position: relative;
height: 50px;
margin-top: -50px;
clear: both;
}
.clearfix:after {
display: block;
content: '';
clear: both;
height: 0;
visibility: hidden
}
讲header和content包装在一个wrapper-main内,再将footer和wrapper-main包装在display为flex的一个wrapper内。
<div class="wrapper">
<div class="wrapper-main">
<header>头部</header>
<div class="content">页面内容</div>
</div>
<footer>页脚</footer>
</div>
.wrapper{
display: flex;
flex-direction: column;
min-height: 100%;
}
.wrapper-main{
flex: 1;
}
footer{
flex: 0;
}
vue2+已经将过渡效果升级为transition
的封装组件,具体使用:
<transition name="fade">
<p>hello</p>
</transition>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s
}
.fade-enter, .fade-leave-to /* .fade-leave-active in below version 2.1.8 */ {
opacity: 0
}
写css时尽量用class名而非标签名,在渲染性能上,class优于标签,尤其在层级嵌套较深时。
在vue 1.0中使用v-el
定义element,2.0 升级为 ref
vm.$nextTick( [callback] )
在修改数据之后立即使用这个方法,获取更新后的 DOM。
new Vue({
methods: {
example: function () {
// 修改数据
this.message = 'changed'
// DOM 还没有更新
this.$nextTick(function () {
// DOM 现在更新了
// `this` 绑定到当前实例
this.doSomething();
})
}
}
})
<div class="goods">
<div class="menu"></div>
<div class="content"></div>
</div>
<style>
.goods{
display: flex;
height: 400px;
}
.menu{
background: #4FB3A4;
flex: 0 0 100px;
/*flex: none | [ <'flex-grow'> <'flex-shrink'> <'flex-basis'> 默认 0 1 auto]*/
/*flex-grow:定义项目的放大比例,默认为0*/
/*flex-shrink:定义了项目的缩小比例,默认为1*/
/*flex-basis:定义了在分配多余空间之前,项目占据的主轴空间(main size)*/
}
.content{
flex: 1;
background: yellow;
}
</style>
更多方法参考我的一篇总结:左侧定宽,右侧自适应与双飞翼布局
v-for
遍历数组时的参数顺序已经变更,当包含 index
时,之前遍历数组时的参数顺序是 (index, value)
,现在是 (value, index)
。来和 JavaScript 的原生数组方法 (例如 forEach
和 map
) 保持一致。
首先遍历获取每个li标签的clientHeight
值,依次叠加并存入数组listHeight
,之后给右侧ul
添加scroll
事件,获取滚动的值后,利用vue的计算属性计算当前滚动的值在listHeight
的区间,从而通过该区间确定左侧菜单栏对应的active类的位置
动态地切换 class可以通过v-bind绑定class,可以使用对象语法(传入一个对象,通过判断对象属性值是否为true来切换class)、数组语法(同理):
:class="{'hightLight': totalCount>0}"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
data: {
isActive: true,
hasError: false
}
在ES6之前,拼接字符串需要使用+
,在ES6中只需使用反引号配合${ 变量 }
即可;
// 旧版
alert("你好,\n 我叫\n Olive");
// ES6
alert(`你好
我叫
olive`);
// 旧版
let name = 'cat';
console.log('你好,' + name + '!');
// ES6
console.log( `你好,${name}!` );
- 首先父组件内通过import引入子组件
- 通过components注册组件
- 将子组件名作为标签名实现在父组件内使用子组件
- 子组件内通过props引入父组件数据
props() {
food: {
type: Object
}
}
- 父组件通过在子组件标签内使用v-bind传入数据food
<food :food="food"></food>
组件的方法如果是私有的,命名时最好在前面加上_
,如:"_show",公有则不加
使用 ref
为子组件指定一个引用 ID
,然后在父组件中使用this.$ref.id.show()
即可使用子组件的方法。
Vue.js 为 v-on
提供了事件修饰符,使用@.stop阻止冒泡
官方文档