最近在做2.0版本的饿了么,在慕课网上的教程是1.0版本的,跟着做的过程改了一些地方。特此记录下踩坑过程。
1.代码规范
严格,动不动就是expected 4 spaces but 1 tab或者indent这种错误。开始直接去build/webpack.base.config.js把
`{
test: /.(js|vue)$/,
loader: ‘eslint-loader’,
enforce: ‘pre’,
include: [resolve(‘src’), resolve(‘test’)],
options: {
formatter: require(‘eslint-friendly-formatter’)
}’
直接注释掉了,不过后期在引用图片的时候又出现一个问题。
错误为:ParseError:expected “indent”,got “media”
截图如下
找原因找解决办法超多次一直无解。。。。
(所以有哪位知道怎么解决的麻烦告诉我好吗?跪谢!!!!!!)
我干脆又把注释取消了,手动将所有格式调好,也是为了后期的打包等情况能更顺手一点。
但是上面这个问题真的无解了。。。。
还有个办法是把eslint规则配为0,就不去检测这条规则了。
打开.eslint.js文件,在‘rules’尾部加入:
'indent': 0,
'space-before-function-paren': 0
保存,重新npm run dev。
20170711-15:08更新:
**!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
我终于调好了,真的想打死自己,一直在找index.styl和mixin.styl中出现@media地方的问题,然后发现是在base.styl的@media后面没有敲一个空格的原因!格式真的太严格了~**
2.vue2.0&1.0
老版本
<div class="tab-item">
<a link = "{path:/goods}">商品</a>
</div>
新版本
<div class="tab-item">
<router-link to="/goods">商品</router-link>
</div>
定义路由也要改成下面的格式
{
path: '/ratings',
component: ratings
}
挂载时的方法也作了修改
new Vue({
template: '<App/>',
components: { App },
router: router
}).$mount('#app')
3.v-el和ref
v-el是1.0的。2.0改成了ref
v-el 和 v-ref 合并为一个 ref 属性了,可以在组件实例中通过 $refs 来调用。这意味着 v-el:my-element将写成这样: ref=”myElement”, v-ref:my-component 变成了这样:ref=”myComponent”。绑定在一般元素上时,ref 指DOM元素,绑定在组件上时,ref 为一组件实例。 因为 v-ref不再是一个指令了而是一个特殊的属性,它也可以被动态定义了。这样在和v-for 结合的时候是很有用的:
<p v-for="item in items" v-bind:ref="'item' + item.id"></p>
以前 v-el/v-ref 和 v-for 一起使用将产生一个DOM数组或者组件数组,因为没法给每个元素一个特定名字。现在你还仍然可以这样做,给每个元素一个同样的ref:
<p v-for="item in items" ref="items"></p>
$refs不是响应的,而在1.x中不同。
因为它们在渲染过程中注册/更新。只有监听变化并重复渲染才能使它们响应。 另一方面,设计$refs主要是提供给 js 程序访问的,并不建议在模板中过度依赖使用它。因为这意味着在实例之外去访问实例状态,违背了 Vue 数据驱动的思想。
所以在代码中做相应的修改:
1.x中使用better-scroll
<div class="menu-wrapper" v-el:menuWrapper></div>
<div class="foods-wrapper" v-el:foodsWrapper></div>
methods: {
_initScroll() {
this.menuScroll = new BScroll(this.$els.menuWrapper,{})
this.foosScroll = new BScroll(this.$els.foodsWrapper,{})
}
}
2.0中使用better-scroll
<div class="menu-wrapper" ref="menuWrapper"></div>
<div class="foods-wrapper" ref="foodsWrapper"></div>
methods: {
_initScroll() {
this.menuScroll = new BScroll(this.$refs.menuWrapper,{})
this.foosScroll = new BScroll(this.$refs.foodsWrapper,{})
}
}
4.transition的变化
在2.X中transition被封装成一个组件了,所以在使用时只需要将想要添加过渡效果的部分写在 中即可,会有 6 个(CSS)类名在 enter/leave 的过渡中切换
- v-enter: 定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。
- v-enter-active: 定义过渡的状态。在元素整个过渡过程中作用,在元素被插入时生效,在 transition/animation 完成之后移除。
- v-enter-to: 2.1.8版及以上定义进入过渡的结束状态。在元素被插入一帧后生效(于此同时 v-enter 被删除),在 transition/animation完成之后移除。
- v-leave: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。
- v-leave-active: 定义过渡的状态。在元素整个过渡过程中作用,在离开过渡被触发后立即生效,在 transition/animation 完成之后移除。这个类可以被用来定义过渡的过程时间,延迟和曲线函数。
- v-leave-to: 2.1.8版及以上定义离开过渡的结束状态。在离开过渡被触发一帧后生效(于此同时 v-leave 被删除),在 transition/animation完成之后移除。
5.$dispatch被弃用
现在官方推荐使用专用的状态管理层Vuex。
官方文档说:
父子组件上的相互通信使用v-on来监听子组件上$emit的变化。然而,如果是跨多层父子组件通信的话, $emit并没有什么用。相反,用集中式的事件中间件可以做到简单的升级。这会让组件之间的通信非常顺利,即使是兄弟组件。因为 Vue 通过事件发射器接口执行实例,实际上你可以使用一个空的 Vue 实例。在组件中,可以使用 $emit, $on, $off分别来分发、监听、取消监听事件。
6.nextTick()
nextTick()官方文档的说明是:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
nextTick()我的理解是获取更新后的DOM。异步更新。几个组件在DOM变化后都需要重新计算scrollY并更新scroll。只有先获取更新后的DOM,才能正常的使用滑动插件。此时nextTick()就是必须的。
看到一个更全面的解释贴上来:
什么时候需要用的Vue.nextTick()
- 你在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
原因是,Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop)
当中观察到数据变化的 watcher 推送进这个队列。如果这个watcher被触发多次,只会被推送到队列一次。
这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOM操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置vm.someData = ‘new value’,DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。 如果此时你想要根据更新的 DOM状态去做某些事情,就会出现问题。
为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
7.keep-alive
vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗
<keep-alive>
<component>
<!-- 组件将被缓存 -->
</component>
</keep-alive>
有时候 可能需要缓存整个站点的所有页面,而页面一般一进去都要触发请求的
在使用keep-alive的情况下
<keep-alive>
<router-view></router-view>
</keep-alive>
将首次触发请求写在created钩子函数中,就能实现缓存,
比如列表页,去了详情页 回来,还是在原来的页面
8.axios
在vue1.x的时候,vue的官方推荐HTTP请求工具是vue-resource,但是在vue2.0的时候将推荐工具改成了axios。
使用方式都差不多,但需要注意的是:接口返回的res并不直接是返回的数据,而是经过axios本身处理过的json对象。真正的数据在res.data里:
axios.get(url).then((res)=>{
this.data = res.data
})