关于 vue@2

Vue@2 已经正式发布了,但其实这之前已经在 RC 版本下使用了一段时间,在使用过程中有一些心得,在此总结一下。

transitiontransition-group

transitiontransition-groupVue@2 中借鉴自 ReactAngular 的动画而来,其中 transition 主要处理单个节点的动画,而 transition-group 则用于处理 v-for 中渲染产生的多个节点的过渡动画。

关于 Vue 中的过渡动画,请参考最新的文档transitiontransition-group 大概就是依托于我们所提供的 name 或者 class 来寻找样式从而实现简单的过渡动画。在 Vue@1中,是通过 transition 指令实现的,而现在在引入Virtual Dom 之后,通过 render function 已经可以很方便的渲染组件,因此它们已成为一个内置的组件。

首先关于 transition,其使用方法与指令式的大致相同,尽管 transition 是一个组件,但它不会渲染出多余的节点,它仅仅是在节点过渡时对子节点添加相应的类型从而实现过渡动画效果(源码)。

在这里所想细说的是 transition-group 源码,与 ReactTransitionGroup 一样,它也需要指定一个唯一的 key,而这个 key 大有用武之地。在官方实例中,这个 key 是数组的每一个元素的值,因为数组中的每一个值是不相同的,因此在每一次重新渲染的过程中可以看到过渡动画,无论插入、删除、还是打乱顺序,都能看到变化。但是倘若我们把这个 keyindex 来代替,则不会产生动画,因为 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>

使用 `value` 为 `key`

<!-- 使用 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>

使用 `index` 为 `key`

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-groupmoveClass 则为当渲染节点的位置发生相对改变时保存过渡动画。

`moveClass`

但是无论 transition 还是 transition-group 都只为我们提供了 low-level 的过渡动画,若要使用更为炫酷的动画,Vue 依然支持使用第三方库。

生命周期函数之 updated

我们知道,Vue 在数据发生改变之后的 DOM 更新是异步的,因此有了 Vue.nextTickvm.$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 实际上仅仅是在 VNodepatch 之后调用的,并不是在 DOM 更新之后调用,因此在数据更新之后我们想要拿到最新的 DOM 节点,需要在 nextTick 中,而非 updated 中。

是否有必要用 Vuex

记得 redux 作者有一句话:当你不知道什么时候该用 redux 的时候,那就不要用它。这句话也适用于 Vuex

大多数模板都提供了完整的 VueVuexVue-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/