关于 vue@2
Vue@2
已经正式发布了,但其实这之前已经在 RC 版本下使用了一段时间,在使用过程中有一些心得,在此总结一下。
transition
与 transition-group
transition
与 transition-group
是 Vue@2
中借鉴自 React
与 Angular
的动画而来,其中 transition
主要处理单个节点的动画,而 transition-group
则用于处理 v-for
中渲染产生的多个节点的过渡动画。
关于 Vue
中的过渡动画,请参考最新的文档。transition
与 transition-group
大概就是依托于我们所提供的 name
或者 class
来寻找样式从而实现简单的过渡动画。在 Vue@1
中,是通过 transition
指令实现的,而现在在引入Virtual Dom
之后,通过 render function
已经可以很方便的渲染组件,因此它们已成为一个内置的组件。
首先关于 transition
,其使用方法与指令式的大致相同,尽管 transition
是一个组件,但它不会渲染出多余的节点,它仅仅是在节点过渡时对子节点添加相应的类型从而实现过渡动画效果(源码)。
在这里所想细说的是 transition-group
源码,与 ReactTransitionGroup
一样,它也需要指定一个唯一的 key
,而这个 key
大有用武之地。在官方实例中,这个 key
是数组的每一个元素的值,因为数组中的每一个值是不相同的,因此在每一次重新渲染的过程中可以看到过渡动画,无论插入、删除、还是打乱顺序,都能看到变化。但是倘若我们把这个 key
用 index
来代替,则不会产生动画,因为 index
对于 Vue
在重新渲染的过程中是没有变化,除非我们插入一个值,这才会引起对应值得 index
发生改变,如此才会有过渡动画,但是此时的过渡动画可能并不是我们想要的。
<!-- 使用 value 为 key -->
<div id="list-demo" class="demo">
<button @click="add">Add</button>
<button @click="remove">Remove</button>
<transition-group name="list" tag="p">
<span v-for="item in items" :key="item" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
<!-- 使用 index 为 key -->
<div id="list-demo" class="demo">
<button @click="add">Add</button>
<button @click="remove">Remove</button>
<transition-group name="list" tag="p">
<span v-for="(item, index) in items" :key="index" class="list-item">
{{ item }}
</span>
</transition-group>
</div>
new Vue({
el: '#list-demo',
data: {
items: [1, 2, 3, 4, 5, 6, 7, 8, 9],
nextNum: 10
},
methods: {
randomIndex: function() {
return Math.floor(Math.random() * this.items.length)
},
add: function() {
this.items.splice(this.randomIndex(), 0, this.nextNum++)
},
remove: function() {
this.items.splice(this.randomIndex(), 1)
},
}
})
从以上的效果中可以明显感受到差异,因此我们在用 transition-group
时,应当使用渲染过程中会发生变化的值作为 key
,这样才能使得我们所期望的过渡动画生效。
而 transition-group
的 moveClass
则为当渲染节点的位置发生相对改变时保存过渡动画。
但是无论 transition
还是 transition-group
都只为我们提供了 low-level
的过渡动画,若要使用更为炫酷的动画,Vue
依然支持使用第三方库。
生命周期函数之 updated
我们知道,Vue
在数据发生改变之后的 DOM
更新是异步的,因此有了 Vue.nextTick
和 vm.$nextTick
两个 API
来供我们在 DOM
更新完成之后调用。
而 updated
只是 Virtual DOM
更新完成之后的回调。我们来看源码:
if (vm._isMounted) {
callHook(vm, 'beforeUpdate')
}
const prevEl = vm.$el
const prevActiveInstance = activeInstance
activeInstance = vm
const prevVnode = vm._vnode
vm._vnode = vnode
if (!prevVnode) {
// Vue.prototype.__patch__ is injected in entry points
// based on the rendering backend used.
vm.$el = vm.__patch__(vm.$el, vnode, hydrating)
} else {
vm.$el = vm.__patch__(prevVnode, vnode)
}
activeInstance = prevActiveInstance
// update __vue__ reference
if (prevEl) {
prevEl.__vue__ = null
}
if (vm.$el) {
vm.$el.__vue__ = vm
}
// if parent is an HOC, update its $el as well
if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
vm.$parent.$el = vm.$el
}
if (vm._isMounted) {
callHook(vm, 'updated')
}
从源码中我们可以很明显的看到这里 updated
实际上仅仅是在 VNode
被 patch
之后调用的,并不是在 DOM
更新之后调用,因此在数据更新之后我们想要拿到最新的 DOM
节点,需要在 nextTick
中,而非 updated
中。
是否有必要用 Vuex
记得 redux
作者有一句话:当你不知道什么时候该用 redux
的时候,那就不要用它。这句话也适用于 Vuex
。
大多数模板都提供了完整的 Vue
、Vuex
、Vue-Router
的骨架,但有的时候你需要的仅仅是 Vue
,比如你只是要一个简单的页面,只有简单的数据处理逻辑和 Ajax
请求,那你大可不必将所有的东西都杂糅进去,那样反而会使得你简单的页面交互和数据处理逻辑变得更加复杂。
React
现如今已经有了全家桶
的问题,于是他们用了一个叫做 create-react-app
来解决,而 Vue
很早就有了 vue-cli
来为你提供一站式的项目构建,但是我并不推荐这么做,结合你的实际需求,取你所需,用你所能应该才是更好的,他们永远都只是一个参考,并不是必须。
Don’t start with a boilerplate when learning a new tech.
文章均采用 CC BY-NC-SA 3.0 许可协议,转载请注明出处。
本文链接:https://blog.kingsongao.com/2016/10/05/关于-vue-2/