Vue: Establish consistent naming convention for all hooks in Vue

Created on 29 Jun 2016  Â·  11Comments  Â·  Source: vuejs/vue

In lifecycle methods and the transition system, before/after prefixes (with camelCase) seem preferred instead of pre/post. For consistency and also because "before" and "after" are probably more accessible to Vue's non-native English speakers, perhaps postupdate should be renamed to afterUpdate.

discussion

Most helpful comment

I'd like to avoid big naming changes for the sake of API continuity, so the goal is

  1. consistency;
  2. as few changes as possible.

What I see right now that feels inconsistent are:

  1. postupdate hook in custom directives
  2. onEnter and onLeave for transitions

I think if we fix these we could settle on the following:

  1. present tense verb (bind, update, enter): indicates the user is implementing this hook to perform the specified action.
  2. past tense verb (created, mounted): indicates the action was performed by the framework and the hook is exposed for its timing.
  3. camelCase prefixed verb (beforeMount, afterEnter, enterCancelled): also indicates the action was/will be performed by the framework and the hook is exposed for timing purposes.

Based on these rules, the changes would be:

  1. postupdate -> componentUpdated
  2. onEnter -> enter, onLeave -> leave

The reason I changed them to onEnter and onLeave in the first place was due to appear, which is a boolean, not a hook. However I think we can just determine the need for appearing transition simply by testing the presence of appear, afterApear and beforeAppear, and appear can either be true or an actual hook.

All 11 comments

And actually, since the transition system's enter and leave have been renamed to onEnter and onLeave, would it make sense to rename bind, update, and unbind to onBind, onUpdate, and onUnbind? I'm really not sure about this one. The fact that onBind sounds a lot like unbind is part of my hesitation to fully recommend it.

Good point, I think we should just take a pass at all hooks across different parts of the lib and ensure we have a consistent naming convention.

A bit off-topic and far-stretched, but I've always been wondering about the convention of Vue's options as well, namely computed (adjective), methods (plural noun), and watch (singular noun / verb).

Sounds good. Here are the major patterns I think I'm seeing now:

  1. Verb simple past (e.g. created, mounted)
  2. Verb infinitive (e.g. bind, update)
  3. Prefix + verb infinitive (e.g. beforeCreate, onEnter)

@yyx990803 What do you think would be the best convention to settle on? For me, I think the 3rd option (which also seems to be what we've generally been moving towards) feels nicest. It may also be the only one that can fully accommodate every situation.

And places where we have hooks (may not be exhaustive - it is almost midnight here 😉 ):

  • Lifecycle methods
  • Transition system
  • Custom directives

@phanan Good point. This could be a good time to also set explicit rules to follow for naming component options. Looking at the API, I think this might be the reverse-engineered rules I'm seeing:

  1. If there's a noun for it, use the noun.

    1. If it can accept many things, use the plural (e.g. data, methods, props)

    2. If it can accept only 1 thing, use the singular (e.g. el, template)

  2. If there's no noun, but you're _doing_ something, use the verb infinitive (e.g. watch, render)
  3. If it's a boolean option, use an adjective (e.g. functional)

Current exceptions:

  • computed - verb simple past, perhaps should be compute?
  • extends - conjugated present, perhaps should be extend?

To be fair, I'm not a big proponent of renaming things, unless there will be a warning for when you try to use an old-style name in 2.0. But warning should not pop up when you use an arbitrary name (in my case redux), because it might be handled by custom code.

Just did a more thorough evaluation of the current directive hooks, in the context of a more far-reaching campaign for consistency. Here are a couple areas for confusion I've noticed, with possible solutions at the end:

1. Confusions with what's being "updated"

The directive interface's update and postupdate are actually referring to the updates of two separate things, which could cause confusion. The first is triggered when the directive's value is updated, the second is triggered when the component is updated. So there will be times when postupdate is called and update has _not_ been called. But that's not all - postupdate also runs _before_ the instance/component's updated lifecycle hook. Renaming both of these hooks to make their context and what has actually been updated more clear could be useful.

2. Consistency with lifecycle verbs

Within the component lifecycle, the created hook is the point at which we have access to data, but nothing has been mounted onto the DOM yet. My understanding is this is also the case in the bind hook, so should we use the create verb instead of bind, for consistency? Similarly, cleanup might happen in a destroyed or beforeDestroy hook, so it may also be good to use the destroy verb in preference over unbind.

With those changes, we'd then have the concepts of create, update, and destroy mirrored in directives. Which leaves mount conspicuously missing, despite waiting for the element to be in the document being part of one common use case for directives (see below), among others:

Vue.directive('focus', {
  bind: function (el) {
    Vue.nextTick(function () {
      el.focus()
    })
  }
})

For convenience, it may be good to complete the set with a hook for mounting, so that the above can be simplified to something like:

Vue.directive('focus', {
  onMount: function (el) {
    el.focus()
  }
})

Possible solution

Assuming the prefix + verb infinitive pattern, these are some possibilities:

  • bind -> onCreate
  • onMount new
  • update -> onValueUpdate
  • postupdate -> onVMUpdate / onInstanceUpdate
  • unbind -> onDestroy

@simplesmiler I think you're right that arbitrary renames can be pretty annoying. We do want to be sure that anything we're renaming isn't just because a new name "feels" better, but actually makes Vue's API clearer and more intuitive.

In the case of directives, since they work quite differently than they used to, changing all the hooks might actually _alleviate_ confusion, because then users won't expect the same behavior as before. A few quite big changes: they take new arguments, no longer have instances, and update is no longer called after the initial bind.

As for the existing 1.x lifecycle methods that would change with a move to the prefix + verb infinitive pattern (created and destroyed -> onCreate and onDestroy), most of the lifecycle methods have already changed in 2.0, so my thinking is that existing Vue users would basically have to learn them from scratch anyway.

And the transition system in 2.0 already follows this pattern, so no changes would be necessary there.

An advantage of consistent names, especially for new users, is that with a little experience they can probably _guess_ the name of a hook and be right most of the time, whether it has to do with the component lifecycle, directives, transitions, or whatever else. That's why I think it might be worth it.

I'm just worried that I'm be among the people who debug things for half an hour only to find that I did use an old name of the hook :grinning:

I'd like to avoid big naming changes for the sake of API continuity, so the goal is

  1. consistency;
  2. as few changes as possible.

What I see right now that feels inconsistent are:

  1. postupdate hook in custom directives
  2. onEnter and onLeave for transitions

I think if we fix these we could settle on the following:

  1. present tense verb (bind, update, enter): indicates the user is implementing this hook to perform the specified action.
  2. past tense verb (created, mounted): indicates the action was performed by the framework and the hook is exposed for its timing.
  3. camelCase prefixed verb (beforeMount, afterEnter, enterCancelled): also indicates the action was/will be performed by the framework and the hook is exposed for timing purposes.

Based on these rules, the changes would be:

  1. postupdate -> componentUpdated
  2. onEnter -> enter, onLeave -> leave

The reason I changed them to onEnter and onLeave in the first place was due to appear, which is a boolean, not a hook. However I think we can just determine the need for appearing transition simply by testing the presence of appear, afterApear and beforeAppear, and appear can either be true or an actual hook.

Implemented in next branch.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lmnsg picture lmnsg  Â·  3Comments

julianxhokaxhiu picture julianxhokaxhiu  Â·  3Comments

paulpflug picture paulpflug  Â·  3Comments

aviggngyv picture aviggngyv  Â·  3Comments

bdedardel picture bdedardel  Â·  3Comments