代码入下:

function addGlobalStyle(css) {
    var head, style
    head = document.getElementsByTagName('head')[0]
    if (!head) {
        return
    }
    style = document.createElement('style')
    style.innerHTML = css
    head.appendChild(style)
}

function removeNodeInsertedListener(bindedFunc) {
    var eventTypeList = ['animationstart', 'webkitAnimationStart', 'MSAnimationStart', 'oAnimationStart']
    eventTypeList.forEach(function (eventType) {
        document.removeEventListener(eventType, bindedFunc, false)
    })
}

function addNodeInsertedListener(elCssPath, handler, executeOnce, noStyle) {
    var animName = 'anilanim'
    var prefixList = ['-o-', '-ms-', '-khtml-', '-moz-', '-webkit-', '']
    var eventTypeList = ['animationstart', 'webkitAnimationStart', 'MSAnimationStart', 'oAnimationStart']
    if (!noStyle) {
        var css = elCssPath + '{'
        var css2 = ''
        prefixList.forEach(function (prefix) {
            css += prefix + 'animation-duration:.001s;' + prefix + 'animation-name:' + animName + ';'
            css2 += '@' + prefix + 'keyframes ' + animName + '{from{opacity:.9;}to{opacity:1;}}'
        })
        css += '}' + css2
        addGlobalStyle(css)
    }
    if (handler) {
        var bindedFunc = e => {
            var els = document.querySelectorAll(elCssPath)
            var tar = e.target
            // var match = false
            if (els.length !== 0) {
                els.forEach(function (el) {
                    if (tar === el) {
                        if (executeOnce) {
                            removeNodeInsertedListener(bindedFunc)
                        }
                        handler.call(tar, e)
                        return
                    }
                })
            }
        }
        eventTypeList.forEach(function (eventType) {
            document.addEventListener(eventType, bindedFunc, false)
        })
        return bindedFunc
    }
}

调用方式:

addNodeInsertedListener('.some-class', function(e) {
    // do something
    // e.target 为目标元素
    console.log($(e.target))
})

实现思路

  1. 通过 css 选择器, 为需要监听的元素动态添加一个动画效果
  2. 监听全局的animationstart事件
  3. 监听到animationstart事件后, 比对目标元素是否在监听的元素里
  4. 如果在, 则触发回调

缺点

功能比较单一, 就是只能监听目标元素的插入(原本就存在也可), 由于是使用的监听动画的方式, 对于目标元素里的子元素发生变化, 并不会触发

优点

只要触发了回调, 肯定是你需要的目标元素, 不会出现大量乱七八糟的元素, 让你去做筛选

用在?

比如为微博写个插件, 监听下微博列表, 过滤掉一些你不想看的微博