123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /* @flow */
- import { emptyNode } from 'core/vdom/patch'
- import { resolveAsset, handleError } from 'core/util/index'
- import { mergeVNodeHook } from 'core/vdom/helpers/index'
- export default {
- create: updateDirectives,
- update: updateDirectives,
- destroy: function unbindDirectives (vnode: VNodeWithData) {
- updateDirectives(vnode, emptyNode)
- }
- }
- function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {
- if (oldVnode.data.directives || vnode.data.directives) {
- _update(oldVnode, vnode)
- }
- }
- function _update (oldVnode, vnode) {
- const isCreate = oldVnode === emptyNode
- const isDestroy = vnode === emptyNode
- const oldDirs = normalizeDirectives(oldVnode.data.directives, oldVnode.context)
- const newDirs = normalizeDirectives(vnode.data.directives, vnode.context)
- const dirsWithInsert = []
- const dirsWithPostpatch = []
- let key, oldDir, dir
- for (key in newDirs) {
- oldDir = oldDirs[key]
- dir = newDirs[key]
- if (!oldDir) {
- // new directive, bind
- callHook(dir, 'bind', vnode, oldVnode)
- if (dir.def && dir.def.inserted) {
- dirsWithInsert.push(dir)
- }
- } else {
- // existing directive, update
- dir.oldValue = oldDir.value
- dir.oldArg = oldDir.arg
- callHook(dir, 'update', vnode, oldVnode)
- if (dir.def && dir.def.componentUpdated) {
- dirsWithPostpatch.push(dir)
- }
- }
- }
- if (dirsWithInsert.length) {
- const callInsert = () => {
- for (let i = 0; i < dirsWithInsert.length; i++) {
- callHook(dirsWithInsert[i], 'inserted', vnode, oldVnode)
- }
- }
- if (isCreate) {
- mergeVNodeHook(vnode, 'insert', callInsert)
- } else {
- callInsert()
- }
- }
- if (dirsWithPostpatch.length) {
- mergeVNodeHook(vnode, 'postpatch', () => {
- for (let i = 0; i < dirsWithPostpatch.length; i++) {
- callHook(dirsWithPostpatch[i], 'componentUpdated', vnode, oldVnode)
- }
- })
- }
- if (!isCreate) {
- for (key in oldDirs) {
- if (!newDirs[key]) {
- // no longer present, unbind
- callHook(oldDirs[key], 'unbind', oldVnode, oldVnode, isDestroy)
- }
- }
- }
- }
- const emptyModifiers = Object.create(null)
- function normalizeDirectives (
- dirs: ?Array<VNodeDirective>,
- vm: Component
- ): { [key: string]: VNodeDirective } {
- const res = Object.create(null)
- if (!dirs) {
- // $flow-disable-line
- return res
- }
- let i, dir
- for (i = 0; i < dirs.length; i++) {
- dir = dirs[i]
- if (!dir.modifiers) {
- // $flow-disable-line
- dir.modifiers = emptyModifiers
- }
- res[getRawDirName(dir)] = dir
- dir.def = resolveAsset(vm.$options, 'directives', dir.name, true)
- }
- // $flow-disable-line
- return res
- }
- function getRawDirName (dir: VNodeDirective): string {
- return dir.rawName || `${dir.name}.${Object.keys(dir.modifiers || {}).join('.')}`
- }
- function callHook (dir, hook, vnode, oldVnode, isDestroy) {
- const fn = dir.def && dir.def[hook]
- if (fn) {
- try {
- fn(vnode.elm, dir, vnode, oldVnode, isDestroy)
- } catch (e) {
- handleError(e, vnode.context, `directive ${dir.name} ${hook} hook`)
- }
- }
- }
|